# mruby Architecture This document provides a map of mruby's internals for developers who want to understand, debug, or contribute to the codebase. ## Overview mruby's execution pipeline: ```text Ruby source → Parser → AST → Code Generator → Bytecode (irep) ↓ VM → Result ``` The design priority is **memory > performance > readability**. ## Object Model All heap-allocated Ruby objects share a common header (`MRB_OBJECT_HEADER`): ```text struct RBasic (8 bytes on 64-bit) ┌──────────────┬─────┬──────────┬────────┬───────┐ │ RClass *c │ tt │ gc_color │ frozen │ flags │ │ (class ptr) │ 8b │ 3b │ 1b │ 20b │ └──────────────┴─────┴──────────┴────────┴───────┘ ``` All object structs embed this header via `MRB_OBJECT_HEADER`: | Struct | Ruby Type | Extra Fields | | ------------ | ---------------- | ---------------------------------- | | `RObject` | Object instances | `iv` (instance variables) | | `RClass` | Class/Module | `iv`, `mt` (method table), `super` | | `RString` | String | embedded or heap buffer, length | | `RArray` | Array | embedded or heap buffer, length | | `RHash` | Hash | hash table or k-v array | | `RProc` | Proc/Lambda | `irep` or C function, environment | | `RData` | C data wrapper | `void *data`, `mrb_data_type` | | `RFiber` | Fiber | `mrb_context` | | `RException` | Exception | `iv` | Immediate values (Integer, Symbol, `true`, `false`, `nil`) are encoded directly in `mrb_value` without heap allocation. The encoding depends on the boxing mode (see [boxing.md](boxing.md)). Objects must fit within 5 words (`mrb_static_assert_object_size`). ## Virtual Machine The VM is register-based, using two stacks: a **value stack** for registers (locals, temporaries, arguments) and a **call info stack** for tracking method/block call frames. Each method call pushes a `mrb_callinfo` frame with the method symbol, proc, PC, and argument counts. The dispatch loop in `mrb_vm_run()` decodes opcodes and operates on registers. Method dispatch looks up the receiver's class method table (with a per-state method cache), then either calls a C function directly or pushes a new call frame for Ruby methods. Exception handling uses `setjmp`/`longjmp` (or C++ exceptions if configured). Rescue/ensure handler tables are stored in each irep and searched during stack unwinding. See [vm.md](vm.md) for detailed VM internals, [opcode.md](opcode.md) for the full instruction set. ## Garbage Collector The GC uses **tri-color incremental mark-and-sweep** with an optional **generational mode**. Objects are colored white (unmarked), gray (marked, children pending), black (fully marked), or red (static/ROM). The three-phase cycle (root scan, incremental marking, sweep) runs in small steps between VM instructions to avoid long pauses. Write barriers (`mrb_field_write_barrier`, `mrb_write_barrier`) maintain correctness during incremental marking. The GC arena protects newly created objects in C code. Heap regions (`mrb_gc_add_region`) support embedded systems with fixed memory banks. See [gc.md](gc.md) for detailed GC internals, [../guides/gc-arena-howto.md](../guides/gc-arena-howto.md) for arena usage patterns, [../guides/memory.md](../guides/memory.md) for memory management. ## Compiler Pipeline The compiler transforms Ruby source code through three stages: 1. **Parser** (`parse.y`): Lrama/Bison grammar produces an AST of `mrb_ast_node` structures, tracking lexer state and local scopes. 2. **Code Generator** (`codegen.c`): walks the AST and emits bytecode into `mrb_irep` structures (instruction sequence, literal pool, symbol table, child ireps). 3. **Execution**: the irep is wrapped in an `RProc` and executed by the VM, or serialized to `.mrb` binary format. Alternative loading paths include `mrb_load_string()` (compile and run), `mrb_load_irep()` (load precompiled bytecode), and `mrbc` (ahead-of-time compilation). See [compiler.md](compiler.md) for detailed compiler internals, [opcode.md](opcode.md) for the instruction set. ## Source File Map ### Core (`src/`) | File | Responsibility | | ------------- | ---------------------------------------------- | | `vm.c` | Bytecode dispatch loop, method invocation | | `state.c` | `mrb_state` init/close, irep management | | `gc.c` | Garbage collector (mark-sweep, incremental) | | `class.c` | Class/module definition, method tables | | `object.c` | Core object operations | | `variable.c` | Instance/class/global variables, object shapes | | `proc.c` | Proc/Lambda/closure handling | | `array.c` | Array implementation | | `string.c` | String implementation (embedded, shared, heap) | | `hash.c` | Hash implementation (open addressing) | | `numeric.c` | Integer/Float arithmetic | | `symbol.c` | Symbol table and interning | | `range.c` | Range implementation | | `error.c` | Exception creation, raise, backtrace | | `kernel.c` | Kernel module methods | | `load.c` | `.mrb` bytecode loading | | `dump.c` | Bytecode serialization (write `.mrb`) | | `print.c` | Print/puts/p output | | `backtrace.c` | Stack trace generation | ### Compiler (`mrbgems/mruby-compiler/core/`) | File | Responsibility | | ----------- | ------------------------------- | | `parse.y` | Yacc grammar → AST | | `y.tab.c` | Generated parser (from parse.y) | | `codegen.c` | AST → bytecode (irep) | | `node.h` | AST node type definitions | ### Key Headers (`include/mruby/`) | Header | Contents | | ------------ | ------------------------------------- | | `mruby.h` | `mrb_state`, core API declarations | | `value.h` | `mrb_value`, type enums, value macros | | `object.h` | `RBasic`, `RObject`, object header | | `class.h` | `RClass`, method table types | | `string.h` | `RString`, string macros | | `array.h` | `RArray`, array macros | | `hash.h` | `RHash`, hash API | | `data.h` | `RData`, C data wrapping | | `irep.h` | `mrb_irep`, bytecode structures | | `compile.h` | Compiler context, `mrb_load_string` | | `boxing_*.h` | Value boxing implementations | ## mrbgems System Gems are the module system for mruby. Each gem lives in `mrbgems/mruby-*/` and contains: ```text mruby-example/ ├── mrbgem.rake gem specification (name, deps, bins) ├── src/ C source files ├── mrblib/ Ruby source files (compiled to bytecode) ├── include/ C headers ├── test/ mrbtest test files └── bintest/ binary test files (CRuby) ``` At build time, gem Ruby files are compiled with `mrbc` and linked into `libmruby.a`. Gem initialization runs in dependency order via `gem_init.c` (auto-generated). GemBoxes (`mrbgems/*.gembox`) define named collections of gems (e.g., `default.gembox` includes `stdlib`, `stdlib-ext`, `stdlib-io`, `math`, `metaprog`, and binary tools).