Tuesday, June 10, 2008

Just In Time Compilation

A Just in time compiler is one which is somewhat mid-way between an interpreter and a static compiler. Historically, JITs were design to overcome the slow performance of interpreters by caching native code of frequently interpreted source statements. But nowadays, with the advent of multicore, JITs are playing an interesting role in leveraging the extra cores for a variety of tasks like (data, target cpu) specialized generation of code, much beyond the realm of traditional static compilers. Some comparisons with other models of compilation/execution:
  • JIT vs Interpretation: Both usually operate on same low level IR (bytecode), translation to native code is done at runtime. However, an interpreter translates one instruction at a time and usually does not cache the generated native code to prevent re-translation. On the other hand, a JIT compiler translates a much coarser level entity like a function/module at a time and also the translated native code is cached to speed up execution.
  • JIT vs Static Compilation: Static compilers translate high level code like C source code to low level IR and low level IR in turn to machine code at the same (compile) time. However in a JIT, this is broken down into two steps: Translation from C source code to Low Level IR is done at compile time while the translation from Low Level IR to Machine Code is done at runtime (just before execution). Some of the potential advantages of JIT over static compilation are: Target CPU specialization (where at runtime, it is determined whether the CPU supports certain type of instructions, like for eg, vector instructions, and emitting code using those instructions), Whole program dynamic optimization (inlining dynamic library calls) and Runtime data specialization (where a JIT can generate different versions of a function depending upon the certain variable values, known only at runtime, which may in turn lead to optimizations like memoization)
  • JIT vs Dynamic Binary Compilation: A JIT usually has more semantic information (eg, low level IR with types, basic block information etc) and recompilation is usually done from the low level IR (usually called bytecode). A dynamic binary translator, on the other hand, does re-translation of machine code to machine code by going through byte-code, ie, Machine Code → ByteCode → Machine Code or even directly re-translates Machine Code → Machine Code. Because machine code has very little semantic information, re-translation is usually done for smaller compilation units, like a basic block and unlike a JIT, whole program optimization is usually not possible.

Labels: , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home