Advanced & Internals
The deep end: JIT tracing, bytecode format, machine code generation, schema system, capability model, FFI, and reflection. For contributors, embedders, and people who want to understand how ilusm works from the inside.
JIT & tracing
How the tracing JIT identifies and compiles hot paths.
Bytecode (mcde)
ILBC format, instruction set, constant pool.
Machine code (mch)
Native code generation for x86-64 and ARM64.
Schema system (sch)
Runtime type validation and schema composition.
Capability model
sbx + pol deep dive: enforcement layers.
FFI & interop
Call native libraries, embed ilusm in C.
Reflection (rfl)
Runtime introspection and metaprogramming.
JIT & tracing
ilusm uses a tracing JIT: the interpreter runs normally until a loop or function call is executed frequently enough to cross a hotness threshold. At that point, the JIT records a trace - a linear sequence of operations - and compiles it to native code.
How tracing works
jit module API
Tuning
| Option | Default | Description |
|---|---|---|
jit.set_threshold(n) | 1000 | Iterations before a trace is compiled |
jit.set_max_trace(n) | 4096 | Maximum trace length (ops) |
jit.set_deopt_limit(n) | 10 | Deopts before a trace is abandoned |
jit.enable_type_spec(bool) | true | Enable type specialization (faster but more deopts) |
When the JIT helps and when it doesn't
Helps: tight numeric loops, string processing, list transforms over large collections, hot server request handlers.
Doesn't help: code that runs once, highly polymorphic code (many different value types in the same slot), code with frequent side effects that prevent optimization.
Bytecode - ILBC format
The mcde module encodes the compiler's instruction list into the ILBC binary format. ILBC is a compact, stack-based bytecode designed for fast loading and straightforward interpretation.
File format
Instruction set (selected opcodes)
| Opcode | Hex | Stack effect | Description |
|---|---|---|---|
| PUSH_CONST | 0x01 | ( -- val) | Push constant pool entry by index |
| PUSH_NIL | 0x02 | ( -- nil) | Push nil |
| PUSH_TRU | 0x03 | ( -- tru) | Push boolean true |
| PUSH_FLS | 0x04 | ( -- fls) | Push boolean false |
| LOAD_LOCAL | 0x10 | ( -- val) | Load local variable by slot index |
| STORE_LOCAL | 0x11 | (val -- ) | Store top of stack to local slot |
| LOAD_GLOBAL | 0x12 | ( -- val) | Load global by name index |
| STORE_GLOBAL | 0x13 | (val -- ) | Store to global |
| CALL | 0x20 | (fn a0..an -- ret) | Call function with N args |
| CALL_TAIL | 0x21 | (fn a0..an -- ret) | Tail call (reuses frame) |
| RET | 0x22 | (val -- ) | Return from function |
| JUMP | 0x30 | ( -- ) | Unconditional jump by signed offset |
| JUMP_IF | 0x31 | (cond -- ) | Jump if truthy |
| JUMP_UNLESS | 0x32 | (cond -- ) | Jump if falsy |
| ADD | 0x40 | (a b -- a+b) | Add (numbers or string concat) |
| SUB | 0x41 | (a b -- a-b) | Subtract |
| MUL | 0x42 | (a b -- a*b) | Multiply |
| DIV | 0x43 | (a b -- a/b) | Divide (float result) |
| MOD | 0x44 | (a b -- a%b) | Modulo |
| EQ | 0x50 | (a b -- bool) | Structural equality |
| NEQ | 0x51 | (a b -- bool) | Not equal |
| LT / GT / LE / GE | 0x52–55 | (a b -- bool) | Comparisons |
| MAKE_LIST | 0x60 | (a0..an -- list) | Construct list from N stack values |
| MAKE_OBJ | 0x61 | (k0 v0..kn vn -- obj) | Construct object from N key-value pairs |
| GET_IDX | 0x62 | (obj key -- val) | Index into list or object |
| SET_IDX | 0x63 | (obj key val -- obj) | Set index (returns new object) |
| MAKE_CLOSURE | 0x70 | ( -- fn) | Create closure capturing upvalues |
| SYSCALL | 0xF0 | (args -- result) | Host syscall by ID |
Disassembling bytecode
Machine code - mch module
The mch module is ilusm's native code backend. It takes the JIT's optimized IR and emits machine code for x86-64 (Linux/macOS) and ARM64 (Apple Silicon, Raspberry Pi). It can also be used directly to write assembly-level programs in ilusm.
Architecture
mch API - direct use
Supported targets
| Target | Status | Notes |
|---|---|---|
x86-64 | Partial | System V ABI (Linux/macOS). Integer ops, basic control flow. |
arm64 | Stub | AArch64 AAPCS. Planned for Apple Silicon + RPi. |
wasm32 | Stub | WebAssembly binary format. Planned. |
mcde - the encoder
mcde is the bytecode encoder (distinct from mch which generates native code). It sits at the end of the compile pipeline and serializes the instruction list into the ILBC binary format. You rarely interact with it directly - ilusm compile calls it for you.
Schema system - sch module
The sch module provides runtime schema validation. Schemas describe the shape of data - types, required fields, constraints - and can validate, coerce, or generate sample data.
Defining schemas
Schema composition
sch API
| Function | Description |
|---|---|
sch.obj(fields) | Object schema with named fields |
sch.str(opts) | String schema - min_len, max_len, pattern |
sch.int(opts) | Integer schema - min, max |
sch.num(opts) | Number schema - min, max |
sch.bool() | Boolean schema |
sch.list(item, opts) | List schema with item schema |
sch.one_of(values) | Enum - must be one of the listed values |
sch.union(schemas) | Union - must match one of the schemas |
sch.extend(base, extra) | Extend a schema with additional fields |
sch.validate(schema, data) | Validate data - returns {ok, errors} |
sch.coerce(schema, data) | Validate and coerce types (e.g. "42" → 42) |
sch.sample(schema) | Generate a sample value matching the schema |
sch.to_json_schema(schema) | Export as JSON Schema (draft-07) |
Integration with ORM
Capability model deep dive
ilusm's capability model has three enforcement layers. Understanding all three is important for building secure programs and for auditing whether a program's claimed capabilities match its actual behavior.
Layer 1 - Module-level declarations
Each stdlib module declares its required capabilities at the top of the .ilu file using a # @requires comment. The module loader checks these before executing the module body.
Layer 2 - Syscall contract
The __sys_* host functions check the active capability set before executing. This is enforced in the runtime, not the kernel - it can catch violations before they reach the OS.
Layer 3 - Kernel enforcement (seccomp/pledge)
After sbx.pledge(), the kernel installs a BPF seccomp filter. Any syscall not in the whitelist causes SIGKILL - the process is killed immediately, with no chance for the program to catch or bypass it.
Capability inheritance
Child processes spawned via proc.spawn inherit the parent's capability set by default. You can restrict them further:
Auditing a program's capabilities
FFI & interop
The ffi module lets ilusm call functions in native shared libraries (.so, .dylib, .dll) and embed ilusm as a scripting engine inside C programs.
ffi requires the ffi capability in your pledge. It is intentionally excluded from the default capability set because it bypasses all other safety guarantees.
Calling native libraries from ilusm
Embedding ilusm in C
ffi type mapping
| ilusm type | C type | ffi type string |
|---|---|---|
| num (integer) | int64_t | "i64" |
| num (float) | double | "f64" |
| str | const char* | "ptr" |
| nil | void | "void" |
| ffi.alloc(n) | void* | "ptr" |
| ffi.struct({…}) | struct | "struct" |
Reflection & metaprogramming
The rfl module provides runtime introspection: inspect values, functions, and modules at runtime. Combined with ast and iluc, it enables full metaprogramming - programs that generate and evaluate other programs.
Value inspection
Dynamic dispatch
Code generation with ast + iluc
Macros via ast transformation
rfl API reference
| Function | Description |
|---|---|
rfl.type(v) | Return type string: "str", "num", "bl", "nil", "lst", "obj", "fn" |
rfl.keys(obj) | List of keys in an object |
rfl.has(obj, key) | True if object has the key |
rfl.arity(fn) | Number of parameters a function takes |
rfl.is_fn(v) | True if value is callable |
rfl.upvals(fn) | List of captured variable names |
rfl.exports(mod) | List of exported names from a module |
rfl.call(fn, arg) | Call a function with a single argument |
rfl.apply(fn, args) | Call a function with a list of arguments |
rfl.src(fn) | Source location of a function (file, line) |
rfl.eq(a, b) | Deep structural equality check |
rfl.clone(v) | Deep clone of any value |