VM Query: Contexts on Stack?

Allen Wirfs-Brock 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 
at: http://www.smalltalksystems.com/publications/avmarch.pdf.

Allen_Wirfs-Brock at instantiations.com

More information about the Squeak-dev mailing list