JEP 243: Java-Level JVM Compiler Interface
|Component||hotspot / compiler|
|Discussion||hotspot dash compiler dash dev at openjdk dot java dot net|
|Reviewed by||Douglas Simon, Mikael Vidstedt, Thomas Wuerthinger, Vladimir Kozlov|
|Endorsed by||Mikael Vidstedt|
Develop a Java based JVM compiler interface (JVMCI) enabling a compiler written in Java to be used by the JVM as a dynamic compiler.
Allow a Java component programmed against the JVMCI to be loaded at runtime and used by the JVM’s compile broker.
Allow a Java component programmed against the JVMCI to be loaded at runtime and used by trusted Java code to install machine code in the JVM that can be called via a Java reference to the installed code.
- Integration of a dynamic compiler (such as Graal) based on JVMCI.
- The ability of a JVMCI based dynamic compiler to run on the unmodified JVM. The performance of compiler and its generated code are not of high concern since JVMCI will be an experimental feature in JDK 9 and as such only enabled by specifying certain flags on the command line.
An optimizing compiler is a complex piece of software that benefits greatly from the features provided by Java such as automatic memory management, exception handling, synchronization, excellent (and free) IDEs, excellent unit testing support and runtime extensibility via service loaders just to name a few. In addition, a compiler does not require the low-level language features required by many other JVM subsystems such as the bytecode interpreter and garbage collector. These observations strongly suggest that writing a JVM compiler in Java should allow production of a high quality compiler that will be easier to maintain and improve than existing compilers developed in C or C++. JVMCI provides the API necessary to demonstrate and experiment with this potential.
The JVMCI API will be composed of mechanisms for:
- Accessing VM data structures required by an optimizing bytecode-to-machine-code compiler such as classes, fields, methods, profiling information etc.
- Installing compiled code along with all the metadata required by the JVM for managing compiled code such as GC maps and information to support deoptimization.
- Plugging into the JVM's compilation system to handle servicing JVM requests to produce machine code for methods.
An excellent demonstration of using JVMCI to write and deploy a high performance compiler in the JVM is provided by Graal which has demonstrated peak performance on par with C2 across a wide range of benchmarks.
There are no existing alternatives for a Java based compiler that is usable as a dynamic compiler in the JVM.
The JVMCI implementation includes an extensive set of unit tests for the parts of the API exposed to a compiler developer as well as white box tests for internal parts that makes calls into the VM to implement the public parts.
Risks and Assumptions
A Java API that allows VM internals to be accessed and compiled code to be installed and executed presents an obvious security risk. In JDK8 (where JVMCI was first prototyped and is still co-developed along with the JDK 9 port), the JVMCI API was hidden from untrusted code by loading it with a class loader inaccessible to anything but code on the boot class path. In JDK 9, the intention is to use access controls that are part of the Module System (JSR 261) to prevent untrusted code from being able to use JVMCI. JVMCI needs to be as secured as the Unsafe class is.
JVMCI will be experimental in JDK 9 and such will require extra command line options to enable it. For example:
-XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler -Djvmci.Compiler=<name of compiler>
Making JVMCI experimental allows for extensive experimentation while mitigating any risk to JVM customers.
As mentioned above, JVMCI is dependent on the access controls in JSR 261 to isolate JVMCI from untrusted code.