Trace-based Compilation for the Java HotSpot Virtual Machine
Traditional method-based just-in-time (JIT) compilation translates whole methods to optimized machine code. Trace-based compilation only generates machine code for frequently executed paths, so-called traces, that may span multiple methods.
In this paper, we present our implementation of a trace-based JIT compiler in which we modified the mature, method-based Java HotSpot client compiler. To simplify trace recording, we added a bytecode preprocessing step that detects and directly marks loops within the bytecodes. We duplicated the existing bytecode interpreter and instrumented it for trace recording. In our implementation, traces can be anchored both at loop headers and at method entries. When a trace anchor has been executed frequently enough, trace recording is started. After several times of trace recording, our modified JIT compiler merges the recorded traces into a structure suitable for compilation. During compilation, trace-specific optimizations are applied and guarded with runtime checks if necessary. The generated machine code is then invoked by the interpreter or by already compiled traces. If a method part must be executed that was not covered by traces and therefore not compiled, or if a runtime guard fails, execution falls back to the interpreter.
Benchmarks show an improved performance, less generated machine code and faster compilation compared to the methodbased Java HotSpot client compiler. The peak performance of the SPECjvm2008 benchmarks is increased by 9% on average, while 29% less machine code is generated. Similarly, the performance of the SPECjbb2005 benchmark is increased by 13% and the DaCapo 9.12 Bach benchmarks show a peak performance increase of 5% on average.