JIT

Subverge compiles quotes to native x86-64 code while it runs. This page shows you how to look at the compiler's work, what it generates and when its output is thrown away.

Usage

A quote is compiled the second time it runs, so you do not have to ask for it (it just happens, enjoy).

jit                   status
jit-off  jit-on       toggle
'fib compile          compile now, gives address and length
addr n dis            disassemble n instructions
addr len disr         disassemble a region
'fib xray             source and machine code together
bench                 time a quote with the JIT off, then on

The full list of words is jit jit-on jit-off compile addr dis disr jitdis xray bench. 'name compile returns the address and length of the native code, 'name xray shows it beside the source, and bench times a quote with the JIT off and then on. On a recursive fib it reports 85 ticks interpreted and 3 compiled (yes, that fucking fast).

Check the tour for screenshots of xray and bench.

Design

The JIT produces call-threaded x86-64. These registers are fixed while compiled code runs (this is the nerdy part):

Register Holds
rbx omega state
r12 top of stack pointer
r13 stack base
r14 depth
r15 saved local count
rbp frame

These words are inlined, each with a type check and a fallback to the built-in: + - * & | xor, the comparisons, and dup over drop swap nip not neg. The literal-quote forms of if when unless times for while become native jumps. Everything else is a call back into the interpreter.

That is why fib speeds up so much, from 85 ticks to 3, while a loop that is mostly arithmetic speeds up less.

Invalidation

Compiled code is guarded by jit_version, which is increased when a definition shadows a built-in or when root is rebuilt. Stale code cannot be freed immediately, because another tab may be executing it. It goes onto a 512-entry dead list, and an atomic jit_running counter shows when nothing anywhere is inside compiled code. The list is swept only at that point.

A root rebuild retires the code of the units that it replaced. Your quote is compiled again the next time it runs twice.

Disassembler

xray uses kernel/dis.c, a small x86-64 disassembler that is checked against objdump.

See also