VM Query: Contexts on Stack?
Allen_Wirfs-Brock at Instantiations.com
Thu Mar 30 19:09:24 UTC 2000
At 07:34 PM 3/29/00 -0800, Dan Ingalls wrote:
>If we are talking about putting contexts in the hardware stack, I did this
>half a decade earlier. Smalltalk-78 ran on a 4MHz 8086(*). The VM was 6K
>of code. And it put its contexts right in the hardware stack. I also used
>the trick of overlapping adjacent contexts so there was no need to transfer
>arguments (Ian and I have been discussing doing this for Squeak -- it
>requires pushing the receiver last instead of first).
Pat Caudill and I did something similar in Tektronix Smalltalk but did not
have to change the push order. Probably the most interesting aspect of this
implementation was that we used two stacks to cache the active contexts.
One stack (the "object stack")contained the args/temps/evaluation-stack and
the other stack (the "control stack") contains the control data (IP, method
pointer, home pointer, etc.). The object stack used overlapping stack
frames and only contained oops. The control stack only contained machine
addresses. Object stack frames are variable sized, control stack frames
are fixed size. The control stack state was design such that it could
address into either the object stack or into a heap allocated context
object in a manner that was transparent to the bytecode implementations.
Thus there was no need to re-cache a context if it had been flushed to the
The use of the two stacks eliminates almost all of the complexity of
"parsing the stack" by the GC or when reifying the stack. In general we
have been very happy with the two stack model. Subsequent to the Tektronix
implementation we have used it with success in all of our VM designs as
well as a Java runtime environment that we designed.
Much of the complexity of context caching schemes arises because in the
most general case a Smalltalk-80 context aggregates into a single object
entities with inherently different lifetime extents. Some entities("the
activation record") have LIFO extents others ("block objects", variables
referenced from blocks, etc.) have indefinite ("heap") extents. Things get
much simpler if the architecture explicitly separates the entities with
different life cycles into separate objects. For example, the Smalltalk
compiler can easily identify which local variables are solely referenced
from within a single activation and which are "captured" by a block with
indefinite extent. With this knowledge it is possible to place the
captured variables in a heap allocated "environment" object while placing
all other local variables in a stack allocated activation record. Different
bytecodes are then used to distinguish between accesses to "stack" or
"heap" allocated variables.
All of the Digitalk Smalltalk virtual machines used architecturally
explicit stacks in this manner. One of last of these designs is documented
Allen_Wirfs-Brock at instantiations.com
More information about the Squeak-dev