A Just-In-Time compiler is a hybrid between a compiler and an interpreter. At the beginning of execution of a program the JIT-compiler interprets the program, but it does also record how many times it has interpreted a given piece of the program. When a certain threshold is met, the compiler kicks in and compiles the section into efficient machine code.
Usually a JIT-compiler is used on ByteCode, so the program is compiled into fast code, yet it maintains the portability advantages of ByteCode. Furthermore, by starting with interpretation, the user does not have to wait for the compiler to compile the program each time. It is also possible for the compiler to do profiling on the interpreted code first and then optimizing the resulting code for the usual behaviour.
JIT-compilers are often very complex, which is their biggest disadvantage. Another important point is they need to have fast compilation times or the user would notice. Therefore they often employ simpler and faster analysis phases compared to normal compilers.
It is possible to build a Poor Mans JIT from an interpreter. An interpreter tends to have a main loop, which reads a command and then executes it. Each execution is in fact a basic-block, which can be compiled to machine code and appended together to form the JIT-compiled program. Branches are resolved by the usual interpreter, by jumping back into it. This leads to a couple of factors speed increase with minimal work (2-3 times speedup is normal).
The following are some languages that use Just-in-time compilers:
- Microsoft's .net languages
VisualBasicLanguage in it's .net version
If you're interested in writing your own JIT compiler, there is a useful and portable C library called GNU Lightning to help you in that respect.
