Chris Double, Mozilla contributor and excellent programmer, posted a great overview of what the new JavaScript/ActionScript runtime is going to be like in upcoming versions of Mozilla Firefox and Adobe Flash Player. Specifically, how the new tracing portions of the compiler work. I got permission from him to re-post it here – enjoy!
I attended the Tamarin Tech summit at Adobe on Friday. My main interest for attending was to learn more about the tamarin-tracing project. The goal of Tamarin is to produce a high performance ECMAScript 4 implementation.
‘Tamarin Tracing’ is an implementation that uses a ‘tracing jit’. This type of ‘just in time compiler’ traces code executing during hotspots and compiles it so when those hotspots are entered again the compiled code is run instead. It traces each statement executed, including within other function calls, and this entire execution path is compiled. This is different from compiling individual functions. You can gain more information for the optimizer to operate on, and remove some of the overhead of the calls. Anytime the compiled code makes a call to code that has not been jitted, the interpreter is called to continue.
Apparently the JIT for Lua is also being written using a tracing jit method and a post by Mike Pall describes the approach they are taking in some detail and lists references. A followup post provides more information and mentions Tamarin Tracing.
‘Tamarin Tracing’ is open source and can be obtained from the mercurial repository:
$ hg clone http://hg.mozilla.org/tamarin-tracing/
To build the source you create a directory to hold the build files, change to it, and run the configure script:
$ $ mkdir mybuild $ cd mybuild $ ../tamarin-tracing/configure --enable-shell $ make
The ‘enable-shell’ option is required to produce the ‘avmshell’ binary that executes the bytecode. At the end of the build you’ll see the avmshell binary in the shell subdirectory:
$ shell/avmshell avmplus shell 1.0 build cyclone ...
‘avmshell’ operates on files containing bytecode not JavaScript. To use it you’ll need to have a front end that compiles JavaScript to the ‘abc’ bytecode format it uses. The bytecode is the ActionScript bytecode. You’ll need a compiler that generates this. This can be obtained from the Flex SDK. This is a free download from Adobe. You can also use any other tool that generates the correct bytecode.
Included with Tamarin Tracing is the source for ‘esc’. This is a work-in-progress implementation of an ECMAScript 4 compiler written in ECMAScript. It generates the ‘abc’ bytecode but is (I think) not quite ready for prime time. In this post I’m using the ‘asc’ compiler from the Flex 2 SDK on Linux. This compiler is written in Java and is in the ‘lib/asc.jar’ file in the SDK.
A quick test that the avmshell program works:
$ echo 'print(\'hello world!\');' >>hello.as $ java -jar asc.jar hello.as hello.abc, 86 bytes written $ shell/avmshell hello.abc hello world!
‘avmshell’ has a number of debugging options that are only available when configuring the build with ‘–enable-debugger’. This allows you to get some information about the trace jit. Here’s the build process with a debug enabled build and the available options:
$ mkdir mybuild $ cd mybuild $ ../tamarin-tracing/configure --enable-shell --enable-debugger $ make $ shell/avmshell avmplus shell 1.0 build cyclone ...
To demonstrate some of the output I’ll use a simple fibonacci benchmark. This is the contents of fib.as:
function fib(n) { if(n <= 1) return 1; else return fib(n-1) + fib(n-2); } print('fib 30 = ' + fib(30));
A comparison of times with and without the tracing jit enabled:
$ shell/avmshell -lifespan -interp fib.abc fib 30 = 1346269 Run time was 26249 msec = 26.25 sec $ shell/avmshell -lifespan fib.abc fib 30 = 1346269 Run time was 1967 msec = 1.97 sec
There's a lot of other interesting stuff in the Tamarin Tracing source that I hope to dive into. For example:
- the interpreter is written in Forth. There are .fs files in the 'core' subdirectory that contains the Forth source code. Each 'abc' bytecode is implemented in lower level instructions which are implemented in Forth. The tracing jit operates on these lower level instructions. The system can be extended with Forth code to call native C functions. The compiler from Forth to C++ is written in Python and is in 'utils/fc.py'
- The jit has two backends. One for Intel x86 32 bit, and the other for ARM. See the 'nanojit' subdirectory.
- The complete interpreter source can be rebuilt from the Forth using 'core/builtin.py'. This requires 'asc.jar' to be placed in the 'utils' subdirectory of Tamarin Tracing.
At the summit there was an in-depth session of the internals of the Forth code and how to extend it. I'll write more about that later when/if I get a chance to dig into it.
El Alecs (February 8, 2008 at 11:56 am)
So, right now the Tamarin Project can be used just with abc files? and this ones need to be created from the Flex SDK? Or you can make this files from the Tamarin?
And the idea for the abc files is to create file between the source and the machine bytecodes, something like Java?
timothy (February 8, 2008 at 9:06 pm)
When are these JIT versions of JavaScript supposed to first show up in Firefox?
Chris Double (February 9, 2008 at 1:31 am)
Tamarin Tracing is an implementation of a virtual machine, so it operates on the abc files. There needs to be a compiler from JS (or any other language) to the abc bytecode.
One is included with Tamarin Tracing, called ‘esc’. It’s written in ECMAScript 4 and is a work in progress so may or may not be in a workable state.
The Flex SDK compiler is the most mature and easily used so that’s why I used it in my post.
The ‘abc’ files are the equivalent of .class files in Java. They are the bytecode for the Tamarin VM, as the JVM Bytecode is for the Java VM.
Timothy, I don’t know a specific version of Firefox when a JIT will be included, sorry.