The call stack of the running Java program is modelled by three interfaces: Frame, which encapsulates the data stored in a single stack frame, such as the operand stack and local variables; FrameSource, which encapsulates the allocation and layout of Frames, controlling such things as the argument-passing mechanism; and Context, which encapsulates the storage and management of the call stack as well as the locking logic required by synchronized methods.
Representing the Java context entirely as a data structure allows Java threads to be migrated, simply by executing a given Context on a different thread. This stands in contrast to the more straightforward scheme used in Kaffe, which implements method invocation by recursion within the execution engine , causing context information to be stored on the native stack, and precluding this kind of migration.
The objects representing the execution stack are shown in Figure 9. The system's view of the stack is provided by the Context object on the left, which encapsulates a large array of word-sized slots in which the stack contents are stored. Each slot is capable of holding up to 32 bits of data; 64-bit data types require two adjacent slots, as prescribed by the Java specification .
Individual stack frames are manipulated through the Frame interface, shown as a trapezoid in the figure. A number of design techniques provide the illusion that Frames are just like any other objects , but in reality, the data for each Frame is stored in a contiguous group of slots within the slot array. This allows the frames to be overlapped, making method argument copying unnecessary, while preserving the object-oriented interface. The resulting layout of two adjacent stack frames is shown in the diagram, with overlapping frames labelled twice to indicate their role in each of the frames.