The Register VM
Loon v0.6 replaces the tree-walking interpreter with a register-based virtual machine. Programs compile to Evidence IR — a flat, typed intermediate representation — then execute on a NaN-boxed register VM. The result: 4x faster interpretation, with a Cranelift native backend that hits 370x on compute-heavy code.
Evidence IR
EIR is a register-based IR where every value lives in a virtual register. Functions lower to blocks of flat instructions — no recursion, no tree walks. The compiler resolves closures, pattern matching, and effect dispatch at compile time.
; source
[fn add [a b] [+ a b]]
; lowers to
; r0 = param 0 (a)
; r1 = param 1 (b)
; r2 = add r0, r1
; ret r2NaN-boxing
Every value fits in 8 bytes. Floats are stored as-is. Integers, booleans, nil, and heap pointers are encoded in the NaN payload bits. No allocation for small values, no type tags to check — the IEEE 754 NaN space gives us 51 bits of payload for free.
; all of these are a single u64:
42 ; tagged integer
3.14 ; raw f64
true ; tagged boolean
:hello ; interned symbol indexThree backends
EIR compiles to three targets from the same IR:
- Register VM — 4x faster than the tree-walker, portable, debuggable
- WASM — runs in browsers and edge workers via wasm32 codegen
- Cranelift — native x86-64/aarch64, up to 370x on numeric code
loon run fib.oo ; VM (default)
loon run --native fib.oo ; Cranelift
loon build --wasm fib.oo ; WASM moduleTrace recorder
The VM includes a trace recorder that captures hot loop iterations — instruction sequences, types, branch decisions. This is the foundation for a future tracing JIT: record a trace, type-specialize it, emit native code via Cranelift, guard on type assumptions.
loon run --trace fib.oo
; Trace 0: 12 instructions, 3 guards
; loop_header -> int_add -> int_sub -> branch ...Benchmarks
Release mode, Apple M4 Max. Shorter bars are faster.
Status
All 14 sample programs pass. 465 tests. Three backends from one IR. The tree-walking interpreter remains available via --legacy.