Comments on Smalltalk block closure designs, part 1

Anthony Hannan ajh18 at cornell.edu
Thu May 3 01:16:42 UTC 2001


"Tim Rowledge" <tim at sumeru.stanford.edu> is widely believed to have written:
> If people (you, Ian, etc) can agree a spec for how you want this, then
> I can incorporate much of it in the NewCompiledMethod rework I hope to
> get done soon.

Here is my Block closure design:

The compiler creates a separate CompiledMethod for every first-level block
in a method and stores them along with other literals in the literal array.
However, references in the block's compiledMethod to variables outside its
scope will require new bytecodes (pushOuterSharedTemporaryVariable,
popIntoOuterSharedTemporaryVariable, &
storeIntoOuterSharedTemporaryVariable).  Likewise, references to these
shared variables in the home method will require new bytecodes
(pushLocalSharedTemporaryVariable, popIntoLocalSharedTemporaryVariable, &
storeIntoLocalSharedTemporaryVariable).  Like Allen said, upon method (or
block) activation, shared temporary variables are placed in a local
SharedContext (environment) array on the heap, while other variables can
live in a StackContext (method/block context) on the stack.

Upon block construction ([...]) (blockCopy:), a BlockFunction object is
created.  BlockFunction is a subclass of CompiledMethod with two additional
inst vars: receiver, and outerSharedContext.  The method header, literal
array, and bytecodes from the CompiledMethod that the compiler created for
the block (and stored as a literal) are placed in the new BlockFunction.
Then the active context's receiver is placed in the BlockFunction's receiver
inst var, if necessary, and the active context's localSharedContext is
placed in the outerSharedContext inst var, if necessary.  The compiler
supplies a type to the block construction (blockCopy:) message indicating if
the receiver and/or outerSharedContext are neccessary.

An (outer) block that has inner blocks can be treated recursively like a
home method.  Shared block temporary variables between an outer block and
its inner blocks are put into the outer block's local SharedContext, plus if
an inner block accesses any very outer temp vars (ie. home method temp vars)
then the first element of the outer block's local SharedContext will be a
pointer to the outer block's outerSharedContext (ie. the home method's local
SharedContext).  This creates a chain of SharedContexts from inner to outer.
Inner Block code created by the compiler will access very outer variables
using at: and at:put: messages sent to the SharedContext arrays.  Only local
and outer SharedContext variables can be quickly accesses using the new
bytecodes mentioned above.  This should not be a performance hit since inner
blocks that access very outer temps are rare, and at: and at:put: is not too
slow anyway.

Upon block function (or method) activation, a StackContext (replaces Block
and Method Context) is created on the stack.  Local shared variables are
placed in a localSharedContext array on the heap.  The BlockFunction's
literals, bytecodes, receiver, and outerSharedContext are copied to the
StackContext.  And if indicated in the method header, the outerSharedContext
is copied to the first element of the localSharedContext.  Method headers
have to encode the number of local shared temps and whether or not to add
the outerSharedContext to the localSharedContext.

Summary of classes:

CompiledMethod
	header - encoding num args, num shared vars, num stack vars, frame size
needed (large or small), and share-outer-context-with-inner flag.  args
always go on stack and copied to shared (in first few bytecodes) if
necessary.
	literals
	bytecodes

BlockFunction (superclass: CompiledMethod)
	receiver
	outerSharedContext

StackContext (replaces BlockContext and MethodContext)
	sender - implicit if allocated on the stack
	pc - points to next bytecode instruction
	stackp - not necessary if using the stack pointer
	methodLiterals
	methodBytecodes
	receiver
	outerSharedContext
	localSharedContext - holds local shared vars
	(indexed vars) - args, stack vars, and local execution stack

SharedContext (superclass: Array)
	(indexed vars) - first one may be the outer SharedContext


Cheers,
Anthony





More information about the Squeak-dev mailing list