Internals

Architecture

NanoVM follows Fabrice Bellard’s approach to high-performance WASM interpreters: a dense, monolithic dispatch loop with almost no host boundary.

Design principles

  • Monolithic exec() — dense dispatch compiles to a WASM br_table (O(1) jump tables). Source is split across files with #[inline(always)]; fat LTO fuses everything into a single function.
  • #![no_std] Rust — no standard library, no heap allocation in the hot path, zero dependencies except libm.
  • Minimal host boundary — five WASM imports, ~30 exports; filesystem I/O goes through shared memory, not per-instruction callbacks.
  • Cooperative threading — clone / futex multithreading with context switching at syscall boundaries.

Execution model

The interpreter fetches and decodes one instruction at a time and dispatches through the br_table. It runs uninterrupted until it hits a syscall boundary, where control returns to the host only if the syscall needs it.

Memory

Guest memory is a flat region managed with brk and mmap. A bump allocator handles the VM’s own small allocations; the guest program manages its own heap exactly as it would on real Linux.

The VM struct

The whole machine state is a single #[repr(C)] struct — 12,680 bytes — holding registers, CSRs, the memory map, the thread table and FS state.

File
Responsibility
cpu.rs
RV64GC interpreter loop
decode.rs
instruction field extraction
syscall.rs
Linux syscall dispatch (~80)
mem.rs
guest memory read / write
elf.rs
ELF loader (segments, argv/envp/auxv)
types.rs
the 12,680-byte VM struct