|
| 1 | +# `doc/` — index |
| 2 | + |
| 3 | +Design records and implementation notes for monoruby's runtime. Start |
| 4 | +here; `CLAUDE.md` at the repository root covers the layout, the build and |
| 5 | +the conventions, and points back into this directory for anything deeper. |
| 6 | + |
| 7 | +Two things to know before reading: |
| 8 | + |
| 9 | +- **Language.** Some documents are written in Japanese and some in |
| 10 | + English; the table below says which. |
| 11 | +- **Kind.** A document is one of three things, and they age differently: |
| 12 | + - **reference** — describes what the code does now, and is kept in step |
| 13 | + with it. Trust it, and update it when you change the subsystem. |
| 14 | + - **design record** — why a subsystem is shaped the way it is, with the |
| 15 | + measurements and the rejected alternatives. Still true about the |
| 16 | + *reasoning* even where the code has moved on. |
| 17 | + - **plan / history** — a proposal or a snapshot in time. Read for |
| 18 | + context, not as a description of the present. |
| 19 | + |
| 20 | +--- |
| 21 | + |
| 22 | +## Execution core |
| 23 | + |
| 24 | +| Document | Lang | Kind | Answers | |
| 25 | +|---|---|---|---| |
| 26 | +| [`stack_frame.md`](stack_frame.md) | EN | reference | What a local frame looks like in memory: LFP / CFP offsets, where `self`, the block and the registers sit. | |
| 27 | +| [`method_args.md`](method_args.md) | JA | reference | What `pos_num`, `req_num`, `optional`, `rest` actually count, and what they exclude. | |
| 28 | +| [`native_func.md`](native_func.md) | EN | reference | How to declare a builtin that takes optional / rest / keyword parameters. | |
| 29 | +| [`super_resolution.md`](super_resolution.md) | JA | design record | The two non-obvious questions `super` has to answer — *which* name, and *which* position in the chain — and how monoruby answers them from the frame rather than from a method entry. | |
| 30 | +| [`exception_handling.md`](exception_handling.md) | EN | reference | Raise, unwind, catch and report, and where monoruby is deliberately lazier than CRuby (backtraces are not formatted until asked for). | |
| 31 | +| [`cref.md`](cref.md) | EN | reference | The lexical state that is not local variables: default definee, constant scopes, `Module.nesting`, visibility toggles. Contrasts CRuby's per-frame CREF with monoruby's stack. | |
| 32 | +| [`refinements.md`](refinements.md) | EN | design record | What refinements do to method resolution, why every cache in the tree was keyed without the caller's scope, and the interned-set design that adds them without costing a refinement-free program anything. | |
| 33 | + |
| 34 | +## Codegen and IR |
| 35 | + |
| 36 | +| Document | Lang | Kind | Answers | |
| 37 | +|---|---|---|---| |
| 38 | +| [`jit.md`](jit.md) | EN | reference | The stub a method starts life behind, and how it is rewritten as the method goes from cold to compiled. | |
| 39 | +| [`inline.md`](inline.md) | EN | reference | Inline asm builtins: emitting a method's body straight into the caller instead of dispatching, and trial-inlining. | |
| 40 | +| [`lir.md`](lir.md) | EN | design record | The arch-neutral machine-level IR between `AsmIR` and per-arch emission — the design and the migration log. | |
| 41 | +| [`regalloc_separation.md`](regalloc_separation.md) | EN | design record | Separating the abstract interpreter from register allocation. The largest document here; the structural groundwork the LIR work builds on. | |
| 42 | +| [`arch_difference.md`](arch_difference.md) | EN | reference | How the x86-64 and aarch64 backends differ, `AsmInst` by `AsmInst`. Read before touching either. | |
| 43 | +| [`arg_forwarding_jit.md`](arg_forwarding_jit.md) | JA | design record | JIT strategy for `def f(a, ...) g(...) end`, staged, with the deopt-safety argument. | |
| 44 | +| [`handoff_record_stream.md`](handoff_record_stream.md) | EN | plan / history | Handoff note for the record-driven lowering work; a summary of `regalloc_separation.md` §12–21 as of that branch. | |
| 45 | + |
| 46 | +## Runtime services |
| 47 | + |
| 48 | +| Document | Lang | Kind | Answers | |
| 49 | +|---|---|---|---| |
| 50 | +| [`safepoint.md`](safepoint.md) | JA | reference | The one mechanism GC, preemption and signal delivery all go through. Read this before any of the three below. | |
| 51 | +| [`gc.md`](gc.md) | JA | reference | The collector as it actually is — non-moving, single-threaded, stop-the-world, generational — plus the `GC` module's real numbers. | |
| 52 | +| [`signal.md`](signal.md) | JA | reference | Deferred signal delivery: set a flag, convert it to a Ruby exception or a `Signal.trap` handler at the next safepoint. | |
| 53 | +| [`threads.md`](threads.md) | JA | reference | M:1 green threads, Fibers, non-blocking IO and time-slice preemption. | |
| 54 | +| [`scheduler_state_diagram.md`](scheduler_state_diagram.md) | JA | reference | `ThreadState` and `FiberState` transitions — the companion diagrams to `threads.md`. | |
| 55 | + |
| 56 | +Diagrams referenced by the above: [`fiber_state_diagram.svg`](fiber_state_diagram.svg), |
| 57 | +[`thread_state_diagram.svg`](thread_state_diagram.svg), |
| 58 | +[`gc_state_transitions.svg`](gc_state_transitions.svg), |
| 59 | +[`gc_write_barrier.svg`](gc_write_barrier.svg). |
| 60 | + |
| 61 | +## Strings and encodings |
| 62 | + |
| 63 | +| Document | Lang | Kind | Answers | |
| 64 | +|---|---|---|---| |
| 65 | +| [`encoding_char_iteration_design.md`](encoding_char_iteration_design.md) | EN | plan | Removing the "every String is UTF-8" assumption via a per-encoding character-boundary layer. Marked *proposed*. | |
| 66 | + |
| 67 | +## Compatibility and performance |
| 68 | + |
| 69 | +| Document | Lang | Kind | Answers | |
| 70 | +|---|---|---|---| |
| 71 | +| [`ruby_spec_skip_tags.md`](ruby_spec_skip_tags.md) | JA | reference | How the ruby/spec suite avoids hangs, and the audit that cut a coarse file-level skip list down to the handful that genuinely cannot run. | |
| 72 | +| [`optcarrot_opt_profile.md`](optcarrot_opt_profile.md) | JA | design record | Where `bin/optcarrot --opt` spends its time, measured with `perf` and `--features profile`, and the optimizations that came out of it. | |
| 73 | + |
| 74 | +## Plans and history |
| 75 | + |
| 76 | +| Document | Lang | Kind | Answers | |
| 77 | +|---|---|---|---| |
| 78 | +| [`c_extention.md`](c_extention.md) | JA | plan | Design study for loading CRuby C extensions (`.so`). | |
| 79 | +| [`plan-activerecord.md`](plan-activerecord.md) | JA | plan | Staged plan for running ActiveRecord, and what it depends on. | |
| 80 | +| [`progress_2025-2026.md`](progress_2025-2026.md) | EN | history | What changed over ~500 commits, April 2025 to April 2026. | |
| 81 | + |
| 82 | +Images: [`benchmark.png`](benchmark.png), [`chart.png`](chart.png), |
| 83 | +[`optcarrot_benchmark.png`](optcarrot_benchmark.png), |
| 84 | +[`optcarrot_fps_history.png`](optcarrot_fps_history.png), |
| 85 | +[`optcarrot_fps_history_opt.png`](optcarrot_fps_history_opt.png). |
| 86 | + |
| 87 | +--- |
| 88 | + |
| 89 | +## Where to start |
| 90 | + |
| 91 | +- **Adding a builtin** → `native_func.md`, then `method_args.md`. |
| 92 | +- **Changing method dispatch** → `cref.md` and `refinements.md` for what |
| 93 | + resolution depends on; `super_resolution.md` if `super` is involved. |
| 94 | +- **Touching the JIT** → `jit.md` for the entry states, `arch_difference.md` |
| 95 | + before anything arch-specific, `lir.md` and `regalloc_separation.md` for |
| 96 | + the layering. |
| 97 | +- **Anything asynchronous** (GC, signals, threads) → `safepoint.md` first. |
| 98 | +- **A ruby/spec failure that hangs** → `ruby_spec_skip_tags.md`. |
| 99 | + |
| 100 | +## Adding a document |
| 101 | + |
| 102 | +Put it here, add a row above, and say which of the three kinds it is. A |
| 103 | +design record earns its place by recording the *rejected* options and the |
| 104 | +measurements, not just the chosen one — that is what makes it still |
| 105 | +useful once the code has moved. |
0 commit comments