SpiderMonkey is the JavaScript VM embedded in Mozilla firefox . TraceMonkey is a scheme in SpiderMonkey to turn some JavaScript hot code to native instructions in order to make it run fast. It was been developed by Andreas Gal etc in mozilla and the paper about it was published on PLDI,2009. The paper was named :Trace-based Just-in-Time Type Specialization for Dynamic Languages.
TraceMonkey simply identifies loop back edges and do the optimization only on loops. every loop back edge is a potential trace point.The loop becomes hot on its second iteration,so TraceMonkey records the code along the trace in a low-level compiler intermediate representation LIR(In Nanojit, LIR is the source language for compilation to machine code. LIR stands for low-level intermediate representation.) .TraceMonkey stops recording when execution returns to the loop header or exits the loop.After recording is finished,TraceMonkey compiles the trace to native code using the recorded type information for optimization.These code can be entered if the interpreter PC and the types of values match those observed when trace recording was started.
When Tacemonkey detects a loop header and when the loop header has been executed 2 times, It starts a tree to record the trace and type map and mark the trace as the root of a tree.
Then the backend of TraceMonkey-Nanojit comes up ,It will turn the traced LIR to native code .nanojit is part of the tracemonkey,which will translate the recorded trace to an optimized machine code tree.
Traces are in SSA form and have no join points or phi-nodes.And the optimizaions of nanojit must run quickly.Every time the trace recorder emits a LIR instruction,the instruction is immediately passed to pipeline filters which will do optimizations.
There are two types of filters: forward filters and backward filters. The forward filters will do some constant subexpression elimination,expression simplification,then the trace will be recorded. When the recording is completed,nanojit runs the backward optimization filters.nanojit reads one LIR instruction ata a time,and pass it through the pipeline. backward filters do dead data-stack store elimination ,dead call-stack store elimination and dead code elimination optimizations. After a LIR instruction is successfully read from the backward filter pipeline,nanojit’s code generator emit native machine instructions for it.
Register allocation in nanojit is a simple greedy algorithm.It makes a single backward paass over the trace and use a class heuristic that selects the “oldest” register carried values.
So,How does TraceMonkey coorperate with firefox?
Compiled traces are stored in a trace cache,indexed by interpreter PC and type map,The intepreter must hit a loop edge and enter the monitor in order to call a native trace for the first time.To execute a trace, the monitor must build a trace activation record containing imported local and global variables, temporary stack space, and space for arguments to native calls.The local and global values are then copied from the interpreter state to the trace activation record,then the trace is called like a normal C function pointer.
When a trace call returns.the monitor first checks the reason for the trace exit,then it pops or synthesizes interpreter JavaScript call stack frames as needed, finally it copies the impored variables back from the trace activation record to the interpreter state.

Pingback 引用通告: 拥有Nanojit龙芯后端的firefox发布 « 编译点滴
Pingback 引用通告: 《编译点滴》半年记 « 编译点滴