A couple of people have asked me to explain what I mean by “the C++ interpreter” and why bits of it are written in assembler. Here is a brief summary:

  • OpenJDK is the implementation of the Java platform of Sun Microsystems.
  • Hotspot is the Java virtual machine of OpenJDK.
  • Hotspot comprises two interpreters and two JITs.
  • A running instance of Hotspot comprises one interpreter optionally supplemented by one JIT.
  • The interpreters are the template interpreter (aka the asm interpreter) and the C++ interpreter (aka the bytecode interpreter).
  • The JITs are client (aka compiler 1 aka C1) and server (aka compiler 2 aka C2).

The point of intersection between the two interpreters and the two JITs is method dispatch. Every method in Hotspot is defined by a methodOop, and each methodOop has a method entry* which is the address of the code that will execute the method. Different methods have different entries, depending upon whether they are native or not, synchronized or not, JIT-compiled or not, etc etc, but every method is invoked the same way: you put the address of the methodOop in one register, the address of the parameters in another, then jump to the method entry. The way the C++ interpreter differs from the template interpreter is that in the template interpreter everything is done in assembler whereas in the C++ interpreter the non-native entries simply** call BytecodeInterpreter::run(). The C++ interpreter’s entries are therefore much smaller and so easier to port. But they are still written in assembler.

* This is a slight lie: they have two.
** ha ha ha ha ha!