Just-in-Time Compilation

Another Form of Optimization

Just-in-Time Compilation

... this section is incomplete. I will fill in details as time permits. If you are interested, let me know, and I'll try to get to it sooner.

Ordinarily, we think of our programs as being compiled "up front": We run the compiler, which produces machine language, or bytecodes for a virtual machine. Then we run the compiled code.

One alternative is to compile the program "just-in-time" (JIT). The compiler is run while the program is executing.

... consider Javascript in your browser.

A jitter will still interpret the program, but when it finds a hot spot in the program, it might produce assembly code instead:

for (size_t pc = 0; pc < p.instructions.size(); ++pc) {
  char instruction = p.instructions[pc];
  switch (instruction) {
  case '>':
    // inc %r13
    emitter.EmitBytes({0x49, 0xFF, 0xC5});
    break;
  case '<':
    // dec %r13
    emitter.EmitBytes({0x49, 0xFF, 0xCD});
    break;
  case '+':
    // Our memory is byte-addressable, so using addb/subb for modifying it.
    // addb $1, 0(%r13)
    emitter.EmitBytes({0x41, 0x80, 0x45, 0x00, 0x01});
    break;
  case '-':
    // subb $1, 0(%r13)
    emitter.EmitBytes({0x41, 0x80, 0x6D, 0x00, 0x01});
    break;
  }
}

... the interpreter pattern is the same: write code to memory, then branch to that code and run it! This is possible in many languages, using libraries. Most commonly in C.

... this does not save interpretation steps, like the optimizer might, but executes assembly code directly, rather than the interpreter's implementation of it. Less overhead.

So much work in JIT compilation took off with the advent of Java. The rise of Javascript has kept the interesting work going. We can do the same things for Racket and Python, too, and many of our tools do.