mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
143959b94b
Co-authored-by: Claude <noreply@anthropic.com>
183 lines
7.8 KiB
Markdown
183 lines
7.8 KiB
Markdown
<!-- summary: About mruby Architecture -->
|
|
|
|
# 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).
|