We looked last week at some of the things that can influence the speed of programming languages and how different approaches to running code can influence program performance. Some work described by Apple this week shows how techniques common in one language can be applied to another.
Modern browsers use a scheme called just-in-time compilation to convert JavaScript into executable code and achieve high performance when they do so. As the optimization process has become more advanced and performance improved, Apple's WebKit developers have realized that they're increasingly building the same capabilities as traditional compiler developers have already built. Feeling that's rather wasteful, they've decided to stop building their own and instead leverage the optimization capabilities of the LLVM compiler.
The work was described earlier this week in a blog post. The WebKit JavaScript engine previously had three different stages that achieved different performance levels for the scripts they ran. The first stage was an interpreter that ran script programs without compiling them. This allows scripts to run "instantly" without having to wait for a compiler.
If a JavaScript function is called more than six times, or loops more than 100 times, it gets fed into the next stage: a basic JIT compiler that produces executable code. This doesn't optimize heavily, but it removes some of the overheads that the interpreter has to produce code in the ballpark of ten times faster than the interpreter.
If the function is then called more than 66 times, or loops more than 1,000 times, it gets fed into the third stage, a JIT compiler that actually spends a relatively long time to optimize the code. The third stage output is about three times faster than the basic JIT, or 30 times faster than the interpreter. It would take too long to optimize every function with this compiler, which is why this staged approach is used.
Though that third stage is much faster than the interpreter, it still doesn't match a typical C or C++ compiler for low-level optimizations: figuring out which values to store into which registers, for example. The WebKit developers wanted to add a fourth stage to perform this kind of work, but while they thought that writing it from scratch would be "super fun," it'd also be a lot of work. A lot of work that existing C and C++ compilers already do. Hence, they decided to investigate the use of LLVM's code generation and optimization.