[ENH] ClosureCompiler-ajh

Anthony Hannan ajhannan at yahoo.com
Tue Jun 24 05:18:25 UTC 2003


ClosureCompiler-ajh (previously ClosureCs-ajh) has been updated to reduce new
protocols required.  It exists as a package on SqueakMap, but requires SmaCC
Development, GeneralEnh-ajh, and ContextCleanup-ajh.  Below is its description
copied from its Readme file:

This package adds a closure compiler to the standard Squeak image without
replacing the existing compiler. A new 'general' preference called
#compileBlocksAsClosures determines which compiler to use for NEW methods only.
When true the closure compiler is used, when false the existing compiler is
used (default). Block contexts will still be created by existing methods.

The closure compiler is a total rewrite of the Smalltalk compiler using the
SmaCC parser generator and the Refactory abstract systax tree. A special thanks
goes to John Brant and Don Roberts for creating both the Refactory Browser and
Smacc, and to Daniel Vainsencher and Markus Gaelli for porting them,
respectively, to Squeak.

For more details on the compiler organization itself see the Compiler class
comment. Below is a description of how the compiler creates block closures.

Block Closures

The closure compiler compiles non-inlined blocks as separate CompiledMethods.
These block methods are held in the literals of the home method and sent the
#createBlock... message at runtime to create BlockClosures. Outer temps
referenced by the block are given as args to the #createBlock... message which
adds them to the closure it creates. The block closure consists of the method
in its sole named field plus its captured temps in its indexable fields. When
#value... is sent to a block closure its method is executed in a new
MethodContext with the block closure remaining as the receiver. The block
method accesses captured temps in indexed fields as if they were named instance
variables.

Captured temps that may change after being captured are wrapped in
SharedTempHolders and all methods (home and block) access those values
indirectly through the holders. Captured temps that may not change (most
common) are placed directly in the closure, avoiding the creation and
indirection of a holder.

BlockClosures that return to its home context hold the home context as one of
its captured temps. Actually, to support safe continuations, it holds the tag
of its home context. A ContextTag is a unique object for each context that
stays the same for all copies of each context. When a BlockClosure attempts to
return to its home context it searches the sender chain for the context that
has the right ContextTag and returns to it. This works with copied contexts
(continuations) as well as original contexts.

Thanks to captured temps and context tags, block closures are totally separate
from their home context. They are reentrant and each activation has its own
block-local temps.

BlockClosures are slower primarily because each activation creates a new
context, while BlockContexts reuse the same context. An optimizing VM (Jitter,
VI4) that stack allocates contexts should rectify this problem. For an example
of its slowness (and general slowness of context activation) execute '[(1 to:
1000000) do: [:i | i]] timeToRun' under each compiler (toggle the preference). 
On my Pentium II its about 50% slower.

The above example will be unbearably slow under the closure compiler until you
rebuild your VM to include a couple of new primitives (186 and 187) added with
the closure compiler. They implement BlockClosure>>value... directly. Without
them the failure code has to add the closure method to the BlockClosure method
dictionary then call #perform:.  A pre-build Windows 3.2.3 VM is on the Closure
Compiler home page.

Test Cases

Thanks to Boris Gaertner and Rob Withers for writing closure test cases
(BlockClosuresTestCase).

Cheers,
Anthony


__________________________________
Do you Yahoo!?
SBC Yahoo! DSL - Now only $29.95 per month!
http://sbc.yahoo.com



More information about the Squeak-dev mailing list