About the new compiler, Part II

Marcus Denker denker at iam.unibe.ch
Sat Jan 19 14:51:23 UTC 2008


Part II: Examples
-----------------------

I was made aware that the first part put far to much emphasis on  
performance of compilation. I think
it's true that it's fairly unimportant, I did that because in an  
ealier thread we got a comment that
suggested that the compiler has to be bad just because of that. This  
is of course completely not the
case, performance of compilation is not at all that important...  
especially considering today's machines.
And both SmaCC nor the rest of the Compiler were ever optimized for  
speed of compilation...

What counts is flexibility and good design, so that the code is  
maintainable, reusable and enables
experiments. So I hope this part emphasis the right points better.

Having a framework with the right abstractions simplifies  
everything... "Modeling is cheating".

So the question was if the modular design with all these visitors, the  
use of SmaCC instead
of a hand-written parser and the IR at the end really are that  
interesting to have... I think they
are, but the only way to prove it is to explain a bit what we used the  
framework for in the past.
For all these, the architecture proved to be quite useful.

All the things mentioned in the following are *not* part of the  
NewCompiler. They have been
build using it, and while building them, we fixed bugs and generalized  
the framework a little.

So what did we do with the NewCompiler Framework?

1) Language experiments. Some time ago, I did a small experiment for  
Impara with different syntax
    for Squeak. The stated goal was to see  how little is needed for  
having python or JS like syntax
    in Squeak.
    (Of course, the result was that just having the syntax is not  
enough: It's completely unclear
    where the similarity to the other language brakes down, and thus  
it's unusable.. people want to
    pick a book and just type in the code without even undestanding it  
completely... the semantics
    are where it starts to get interesting and *a lot* of work).

    But it's a cool demo... and easy to do: Grammar of JS in SmaCC,  
AST Nodes for all constructs, then
    a visitor that calls the IRBuilder to generate code. No dealing  
with bytecode, but nevertheless
    the complete freedom of bytecode abstraction level code generation.

    Slides (Squeak image with all code): http://www.iam.unibe.ch/~denker/talks/BabelTalk.zip
	
2) Bytecode Transformation.

    I got interested in Behavioral Reflection some time ago, and  
wanted to implement the Reflex model
    of partial behavioral Reflection [1] with a student (David  
Roethlisberger). For that, we needed
    bytecode transformation (at least at that time we thought so...).

    So we looked at Javassist [2] and inspired from that build  
ByteSurgeon. The idea here is that
    we want to insert (or replace) code at any bytecode instruction.  
Of course, we don't want to write
    the to-be-inlined code as bytecode itself, and we do not want to  
deal with the very low level view
    of bytecode where there a many different send-bytecodes, for  
example.

	When you look now at the NewCompiler framwork, then there are two  
things directly trivially visible:
	1) The IR is exactly on the right level of abstraction.
	2) Implementing a small compiler to generate us the to-be-inlined  
code as IR is trivial with the
	   the modular design.
	
	So this is what we did... added transformation (adding/deleting  
nodes) to the IR, wrote a Compiler
	as a simple subclass of the standard SmaCC based compiler that  
generates IR (extended with
	special syntax to be able to access e.g. the receiver and arguments  
of a send). Then the bytecode
	inling framework is a simple thing.
	
	As an example, here is a the code that would annotate the class  
Example to log the
	receiver objecrs of all message sends:
	
		Example instrumentSend: [ :sendInstr |
		 	sendInstr insertBefore: ’Logger logSendTo: <meta: #receiver> ’
		].
	
	More information:
	Slides: http://www.iam.unibe.ch/~denker/talks/ByteSurgeon-slides.pdf
	Paper: http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Denk06a
	
    ByteSurgeon was then used as the basis for some things:
  		-> first Geppetto (Unanticipated Partial Behavioral Reflection)
            	Slides: http://www.iam.unibe.ch/~denker/misc/GeppettoESUG2006.pdf
             Paper: http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Roet08a
  		-> a proof-of concept implementation of an Omniscient Debugger  
similar to Bill Lewis' work
            for Java:
		      Slides: http://www.iam.unibe.ch/~denker/talks/06NODE/UnstuckNode06.pdf
			  Paper: http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Hofe06a
		-> It's one of the backends in the Test Coverage tool Christo done  
by Stefan Reichart
		     http://smallwiki.unibe.ch/stefanreichhart/codecoverage/
	
3) Compiler hack: Global variables as message sends.
    For ChangeBoxes, Pascal Zumkehr needed globals not the be hard- 
coded, but to be accessed via
    message sends. For this, he changed the NewCompiler. It's easy to  
do, and he did it after a short
    introduction over the NewCompiler. The old compiler is quie arcane  
for all these things. (But for
    sure as soon as you get used to the patterns it's not  
impossible... but I think it's odd way of
    coding)
	
    Paper: http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Denk07c
	

5) Sub-Method Reflection
	Joined work with Phillippe Marschall. This uses the SmaCC/RB-AST part  
of the NewCompiler to
	generate "Reflective" Methods that use and extendend AST instead of  
bytecodes, and it provides
	a small in-image "JIT" that generate bytecode on-demand, which is  
based on the standard NewCompiler
	backend.

     Slides: http://www.iam.unibe.ch/~denker/talks/07TOOLS/07PersephoneTOOLS.pdf
     Paper: http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Denk07b

	This was used e.g. for Adrian Lienhard's work on first class aliases  
and Object-Flow Analysis
	 http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Lien07a
      http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Lien07c


6) Textual Annotations on every language constructs.
     Phillippe provided textual annotations for all language  
constructs in the Persephone system.
	This was realized as it's own extended smalltlak compiler (based on  
the SMacc grammar)
	
     Nik Haldiman used this to build a pluggable type system for Squeak.
     	Slides: http://www.iam.unibe.ch/~denker/talks/07ESUG/07TypePlugESUG.pdf
		Paper: http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Hald07b

6) Reflectivity. This merges sub-method reflection with partial  
behavioral reflection.

	Homepage: http://www.iam.unibe.ch/~scg/Research/Reflectivity/index.html
	Slides: http://www.iam.unibe.ch/~denker/talks/07DYLA/07ReflectivityDylan.pdf
	
	This was used e.g.
		-> for Dynamic Analysis http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi?query=Denk07d&abstract=yes
		-> for Transactional Memory (Lukas Renggli): http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Reng07b
		-> HistOOry, by Frederic Pluquet: http://decomp.ulb.ac.be/frdricpluquet/researchactivities/histoory/
		

So, all in all I am quite convinced that an open, reusable compiler  
infrastructure provides *huge* benefits for building
experiments and tools and thus exploring the future.

Next part:
	-> Closures and Performance of Closure code. (this may take some  
days... busy)

In addition, I will try to answer the questions that came up and give  
a status report soon.

	Marcus

(I am not subscribed to Squeak-dev anymore, so please CC: me)
	

References
==========

[1] Reflex: http://www.iam.unibe.ch/~scg/cgi-bin/scgbib.cgi/abstract=yes?Tant03a
[2] Javassist: http://www.csg.is.titech.ac.jp/paper/chiba-gpce03.pdf

--
Marcus Denker  --  denker at iam.unibe.ch
http://www.iam.unibe.ch/~denker






More information about the Squeak-dev mailing list