March 8, 2014

Just-In-Time Java Compilation in Eclipse

Just-in-time (JIT) compilation is usually applied to get a better execution performance compared to interpreter-based approaches. There are also other scenarios where JIT compilation is useful, e.g., when programming-level code needs to be generated at run-time. Either way, this technique is usually considered to be the domain of experts since it requires a combination of code generation, compilation and dynamic loading and linking. In this post, I show you a simple pipeline based on EMF, JET, JDK and Java core that allows you to do this with minimal effort.

Our starting point is the EMF model (class diagram) shown below. It is a model for simple arithmetic expressions. It consists of an abstract class Term and three concrete implementations of it: Operation, Constant and Parameter.

Below you see an example instance model in the reflective EMF editor. It is basically just a model representation of the expression (3.7 + (p0 * (p1 / 2.0))) where p0 and p1 are parameters. We use here the actual arithmetic operators as enum literals.

The easiest way to evaluate an expression like this one is to write an interpreter which can be as simple as a tree visitor in this case. But today, we want to use a JIT compilation approach to evaluate these expressions. Specifically, given an expression like the one above, we want to generate a Java object that implements this interface:

It contains only one method which evaluates the expression for specific parameter values. The first thing we do is write a pretty-printer that generates a string representation of a term in Java syntax. We extend the EMF-generated Switch class for this:

We get "(3.7 + (params[0] * (params[1] / 2.0)))" if we feed the above Term model into this pretty-printer. Now that we are able to generate the Java expression from Term objects, we just need to generate the rest of the class that will implement the Calculator interface. We use a simple JET template for this, as shown below. There are much more sophisticated template languages, but JET will do just fine in our case.

What is left to do is the actual JIT compilation consisting of three steps:
  1. Generate the Java code from a given Term model using JET,
  2. Compile the generated Java code using the BatchCompiler of JDK,
  3. Dynamically load the compiled calculator class and instantiate it.
The code below does all the three steps. So, again: it takes a Term model and generates an executable calculator instance. Voila, our JIT-compilation.

If you would like to try it out yourself, you can check out the complete source code from GitHub.

No comments:

Post a Comment