Expand description
Register bytecode VM (work/VM_PLAN.md).
A fast, portable interpreter that runs the same RuntimeValue semantics as
the tree-walker. It is the browser/WASM execution engine and the substrate
the native copy-and-patch JIT tiers up from. Built incrementally, RED-first,
differential-tested against the tree-walker.
Re-exports§
pub use compiler::Compiler;pub use disasm::disassemble;pub use disasm::format_constant;pub use disasm::op_io;pub use disasm::DisasmLine;pub use disasm::OpIo;
Modules§
- aot_
tier - AOT-native tier loader (HOTSWAP §Axis-3 / P15):
dlopena rustc-built cdylib (produced bycrate::compile::build_native_cdylib) and wrap an exportedlogos_native_<fn>symbol as aNativeFnthe VM dispatches through the existingNativeSlot::Readypath — no new dispatch, the hot-swap seam already exists. - bg_aot
- Background AOT-native compilation (HOTSWAP §Axis-3 / P18).
- compiler
- AST → bytecode compiler.
- disasm
- Bytecode disassembler — readable text for the Studio debug drawer and any
future
largo --disasm. Pure, headless, no VM state. Bytecode disassembler — renders aCompiledProgram’sOpstream as readable text for the debugger (status line, bytecode tape) and any futurelargo --disasm. Common ops get a clean infix form (constants resolved, registers asR{n}, jump targets inline); the long tail falls back to theOpDebugform, so a newly added op is never a panic — just a plainer line. - fn_
bytecode - A relocatable, self-contained per-function bytecode unit (HOTSWAP §7).
- tier_
cache - Tier cache (HOTSWAP §P12): persist a compiled
FnBytecodekeyed by(source, optimization-config, tier)so a re-run skips re-optimization. - tier_
trace LOGOS_TIER_TRACE— one line per execution-tier hot-swap (HOTSWAP §P13).- wasm
- WebAssembly code generation from VM bytecode: the shared byte emitter (
wasm::encode+wasm::func, always built) plus the WS6 browser WASM-JIT tier (wasm::region_jit, behind thewasm-jitfeature). The direct AOT backend (largo build --emit wasm) consumes the same emitter. WebAssembly code generation from VM bytecode — one shared codegen, two consumers. - wasm_
jit - Back-compat facade: the WS6 browser WASM-JIT tier moved into the shared
wasmcodegen submodule —wasm::funcfor the byte emitter,wasm::region_jitfor the tier + host.machine.rs(super::wasm_jit::WasmTier) and thewasm_jit_*differential/browser test suites still reach it here, unchanged.
Structs§
- Array
Pin - Callee
Sig - A natively-compiled LOOP REGION (OSR-lite): no arguments, no return — every effect flows through the enclosing frame’s registers. What a REGION needs to know about a function it might call: the declared signature (all-scalar = replay-pure = inlinable) and the function index for its table slot.
- Compiled
Program - A compiled program: the constant pool, the linear bytecode (Main first, then
every function body), the size of Main’s register frame, and the function
table (indexed by
FuncIdx, with a name → index map for call resolution). - FnTable
- The per-program native ENTRY TABLE (EXODIA 4.7’s hot-swap seam): two atomic slots per function — [entry pointer, register count] — written when a function’s chain compiles, read by native call stencils through a patched slot address, and the place Tier-2 swaps optimized code in. The backing Vec never reallocates (fixed at construction), so slot addresses are stable for the program’s lifetime.
- Hoist
Guard - A hoisted region-entry bounds check (V8 loop bound-check elimination): the loop’s covered accesses run unchecked iff, at entry, the pinned array is long enough for the whole loop and the induction floor is in range. The VM declines the region (replays on bytecode) if it fails.
- Native
Ctx - Per-program cells the native tier shares with every chain it compiles:
the deopt status (any side-exit anywhere unwinds the whole native stack),
and the LIVE LOGOS DEPTH the call stencils count against MAX_CALL_DEPTH.
Cloneis anArcbump on each cell — a background-compile request carries a clone so the worker patches the same per-program table/status/depth the interpreter does. - Native
Frame - One materialized native frame for a PRECISE deopt (outermost first).
offset/return_pc/return_regdescribe the link from the PREVIOUS frame (they are meaningless for index 0, whose link belongs to the interpreted call site). - Region
Return - A
Returnstatement INSIDE the region (the siftDown early-exit shape): the value slot, its re-boxing kind, and the flag slot the return path sets — after write-back the VM performs the actual function return. - Value
- A VM value (fat 16-byte representation).
- Vm
Enums§
- Chan
Elem - A bytecode instruction. Every field is a small
Copyscalar (registers, constant-pool indices, interned symbols), so the dispatch loop reads each op by value instead ofclone()-ing through theClonemachinery. The declared element type of aPipe of T, carried onOp::ChanNewso a consumer that models a channel as a typed FIFO queue (the direct-WASM AOT) can type aReceive/selectarm’s bound variable even when the pipe is never sent to (an emptyPipe of Textin a timeout-onlyselect). ACopytag — the scalar element types cover every pipe the corpus declares; a struct/enum element resolves toChanElem::Unknown(falls back to the untyped queue, exactly as before). - Constant
- A constant-pool entry.
- Native
Outcome - What one native function call produced.
- Native
Ret - How a native function’s return value re-boxes.
- Observed
Kind - What the VM OBSERVED in each register at the hot back-edge that triggered region compilation — the kinds the adapter SPECULATES on (sound because every later entry re-checks them via the guard set).
- Op
- Param
Kind - A DECLARED parameter’s native representation.
- PinElem
- One pinned array for a region run: the register holding the list, the
frame slots that receive its buffer pointer and length at entry, and the
element kind the region speculated on. The VM borrows each DISTINCT
Rc<RefCell<…>>exactly once for the whole native run (aliased registers resolve to the same buffer, so native writes through one name are visible through every other — and there is zero refcount or borrow traffic inside the loop). Arrays mutate IN PLACE: no write-back, and the deopt replay is sound by prefix-idempotence (the replay recomputes exactly the values the native prefix already wrote). Element kind of a pinned buffer (decides the stencil’s access width: 8-byte for Int/Float bits, 1-byte for Bool). - RegBox
- How one raw register slot re-boxes during frame materialization.
- Region
Outcome - What one native region run produced.
- Region
Return Kind - How a region-return value travels.
- Slot
Kind - The runtime kind a native frame slot carries: entry guards check the VM register’s discriminant against it and copy the raw representation in (f64 travels as bits); write-back re-boxes by it.
Constants§
- MAX_
EXPR_ DEPTH - Maximum expression nesting depth the compiler will descend before erroring
(guards the compiler’s own recursion against adversarial inputs). Debug
builds allocate every match arm’s locals in
compile_expr_into_inner’s frame — measured in the tens of KiB per nesting level as the compiler grows — so 64 keeps the worst case well inside a default 2 MiB test-thread stack while still exceeding any realistic expression depth. (An explicit-work-stack compiler would remove the native-stack coupling entirely; tracked as future work.) - MAX_
REGISTERS_ PER_ FRAME - Hard cap on registers a single frame may claim. Generous for real programs; prevents a pathological frame from claiming the whole register file.
- MAX_
REGISTER_ FILE - Hard cap on the total register file across all live frames. Deep recursion hits this and errors instead of consuming unbounded memory.
- NATIVE_
TIER_ THRESHOLD - Calls before a function is considered hot.
- REGION_
TIER_ THRESHOLD - Back-edge crossings before a Main loop is considered hot.
Traits§
- Native
Fn - A natively-compiled function: integer registers in, integer result out.
depthis the LIVE LOGOS frame count at the call (the callee’s own frame included) — native self-calls count against the same MAX_CALL_DEPTH the bytecode enforces. - Native
Tier - A backend that can try to compile one VM function to native code.
- Region
Fn
Functions§
- branch_
entropy - Shannon entropy of a two-outcome branch profile, in bits (EXODIA 3.3). 0.0 = perfectly predictable (the hardware branch predictor wins; Tier-1 code is fine), 1.0 = a coin flip (Tier-2 should restructure the branch away). Zero samples are zero entropy.
- compile_
and_ run - Compile a statement block to bytecode and run it, returning captured output.
- install_
native_ tier - Install
tieras the process-wide native tier. Idempotent: the first install wins and later calls returnfalse. - installed_
native_ tier - The installed process-wide tier, if any.
- run_
to_ outcome - Compile and run, preserving partial output alongside any error — the shape
the differential harness compares against the tree-walker (which also keeps
the lines emitted before a runtime error).
typescarries the discovery pass’s struct definitions (for default-fill on construction). - run_
to_ outcome_ bg run_to_outcome_with_argswith BACKGROUND native compilation (HOTSWAP §6): hot functions compile on a worker thread while the interpreter keeps running bytecode, then their chains are drained + published. Requires a process-installed tier (the worker needs a&'staticbackend); with none installed it runs pure bytecode. Drains outstanding compiles before returning so the native tier engages deterministically for the differential gates.- run_
to_ outcome_ with_ args run_to_outcomewith the program argument vector for theargs()system native (full argv; index 0 is the program name) and an optional caller-supplied native tier. ASome(tier)overrides the process-wide installed tier — differential suites use a private tier per program so its compile counters are isolated from every other test in the binary.