|
[Table of Contents/Page 1] [Page 2] [Page 3] [Page 4] [Page 5] Chapter 4The Java HotSpot Compilers Overview Most attempts to date to accelerate Java programming language performance have focused on applying compilation techniques developed for traditional languages. Just-In-Time (JIT) compilers are essentially fast traditional compilers that translate the Java-technology bytecodes into native machine code on-the-fly. A JIT runs on the end-user's machine and actually executes the bytecodes, and compiles each method the first time it is executed. There are several issues with JIT compilation. First, because the compiler runs on the execution machine in "user time," it is severely constrained in terms of compile speed: if it is not very fast, then the user will perceive a significant delay in the startup of a program or part of a program. This entails a trade-off that makes it far more difficult to perform advanced optimizations, which usually slow down compilation performance significantly. Secondly, even if a JIT had time to perform full optimization, such optimizations are less effective for the Java programming language than for traditional languages like C and C++. There are a number of reasons for this effect:
As a result, any attempt to achieve fundamental advances in Java programming language performance must provide non-traditional answers to these performance issues, rather than blindly applying traditional compiler techniques. The Java HotSpot VM architecture addresses the Java programming language performance issues described above by using adaptive optimization technology. Hot Spot DetectionAdaptive optimization solves the problems of JIT compilation by taking advantage of an interesting property of most programs. Virtually all programs spend the vast majority of their time executing a small minority of their code. Rather than compiling method-by-method, just in time, the Java HotSpot VM runs the program immediately using an interpreter, and analyzes the code as it runs to detect the critical "hot spots" in the program. It then focuses the attention of a global native-code optimizer on the hot spots. By avoiding compilation of infrequently executed code (most of the program), the Java HotSpot compiler can devote much more attention to the performance-critical parts of the program, without necessarily increasing the overall compilation time. This hot spot monitoring is continued dynamically as the program runs, so that it literally adapts its performance on-the-fly to the needs of the user. A subtle but important benefit of this approach is that by delaying compilation until after the code has already been executed for a while ("a while" in machine time, not user time), information can be gathered on the way the code is used, and then used to perform more intelligent optimization. As well, the memory footprint is decreased. In addition to collecting information on hot-spots in the program, other types of information are gathered, such as data on caller-callee relationships for virtual method invocations. Method InliningThe frequency of "virtual" method invocations in the Java programming language is an important optimization bottleneck. Once the Java HotSpot adaptive optimizer has gathered information during execution about program hot spots, it not only compiles the hot spot into native code, but also performs extensive method inlining on that code. Inlining has important benefits. It dramatically reduces the dynamic frequency of method invocations, which saves the time needed to perform those method invocations. But even more importantly, inlining produces much larger blocks of code for the optimizer to work on. This provides a situation that significantly increases the effectiveness of traditional compiler optimizations, thus overcoming a major obstacle to increased Java programming language performance. Inlining is synergistic with other code optimizations, because it makes them more effective. As the Java HotSpot compiler matures, the ability to operate on large, inlined blocks of code will open the door to a host of even more advanced optimizations in the future. Dynamic DeoptimizationAlthough inlining, described in the last section, is an important optimization, it has traditionally been very difficult to perform for dynamic object-oriented languages like the Java programming language. Furthermore, while detecting hot spots and inlining the methods they invoke is difficult enough, it is still not sufficient to provide full Java programming language semantics. This is because programs written in the Java programming language can not only change the patterns of method invocation on-the-fly, but can also dynamically load new Java code into a running program. Inlining is based on a form of global analysis. Dynamic loading significantly complicates inlining, because it changes the global relationships in a program. A new class may contain new methods that need to be inlined in the appropriate places. So the Java HotSpot VM must be able to dynamically deoptimize (and then reoptimize if necessary) previously optimized hot spots, even during the execution of the code for the hot spot. Without this capability, general inlining cannot be safely performed on Java technology-based programs. Java HotSpot Client CompilerThe Java HotSpot Client Compiler is a simple and fast three-phase compiler. In the first phase, a platform independent front end constructs a high level intermediate representation (HIR) from the bytecodes. In the second phase the platform specific backend generates a low level intermediate representation (LIR) from the HIR. The final phase does peephole optimization on the LIR and generates machine code from it. Emphasis is placed on extracting and preserving as much information as possible from the bytecodes. It focuses on local code quality and does very few global optimizations since those are often the most expensive in terms of compile time. It has support for inlining any function that has no exception handlers or synchronization and also supports deoptimization for debugging and inlining. Java HotSpot Server CompilerThe server compiler is tuned for the performance profile of typical server applications. The Java HotSpot Server Compiler is a high-end fully optimizing compiler. It uses an advanced static single assignment (SSA)-based IR for optimizations. The optimizer performs all the classic optimizations, including dead code elimination, loop invariant hoisting, common subexpression elimination, and constant propagation. It also features optimizations more specific to Java technology, such as null-check and range-check elimination. The register allocator is a global graph coloring allocator and makes full use of large register sets commonly found in RISC microprocessors. The compiler is highly portable, relying on a machine description file to describe all aspects of the target hardware. While the compiler is slow by JIT standards, it is still much faster than conventional optimizing compilers. And the improved code quality "pays back" the compile time by reducing execution times of compiled code. The server compiler performs full inlining and full deoptimization. [Table of Contents/Page 1] [Page 2] [Page 3] [Page 4] [Page 5] | ||||
|
| ||||||||||||