Comments on Smalltalk block closure designs, part 1
Allen Wirfs-Brock
Allen_Wirfs-Brock at Instantiations.com
Thu May 3 06:38:23 UTC 2001
At 09:16 PM 5/2/2001 -0400, Anthony Hannan wrote:
...
>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.
A more general mechanism would be push/pop indirect bytecodes that
load/store indirectly through any activation record slot. The parameters
are slot offset and offset within indirect object. With these basic
instructions. Your can build any sort of environment structure including
chaining through multiple lexical levels.
>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
With a little bit of thought the same class can be used to represent the
code (and literals) for either a method or a block (of any nesting level).
There really isn't much, if any, any difference between them from the
perspective of the execution mechanisms. For debugging purposes it may be
useful to have a separate class for compiled blocks code to help the
debugger display the source code as embedded within a method.
>BlockFunction (superclass: CompiledMethod)
> receiver
> outerSharedContext
Don't try to combine CompiledMethods and closures into a single
class. This is a problematic as combining activation records and closures.
Roughly speaking a Block closure object would be:
Block (superclass: Object)
outerEnvironment
method
but there are many ways to elaborate the design to optimize special cases.
>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
See comments above about push/pop indirect bytecodes. If you use those you
don't necessarily have to dedicate slots for a sharedContext or even an
outerSharedContext. You may find this it is better to link through the
environment objects rather that the activation records.
>SharedContext (superclass: Array)
> (indexed vars) - first one may be the outer SharedContext
Allen
More information about the Squeak-dev
mailing list
|