update
This commit is contained in:
82
docs/spec/gc.md
Normal file
82
docs/spec/gc.md
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
title: "Garbage Collection"
|
||||
description: "Cheney copying collector"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
ƿit uses a Cheney copying collector for automatic memory management. Each actor has its own independent heap — actors never share mutable memory, so garbage collection is per-actor with no global pauses.
|
||||
|
||||
## Algorithm
|
||||
|
||||
The Cheney algorithm is a two-space copying collector:
|
||||
|
||||
1. **Allocate new space** — a fresh memory block for the new heap
|
||||
2. **Copy roots** — copy all live root objects from old space to new space
|
||||
3. **Scan** — walk the new space, updating all internal references
|
||||
4. **Free old space** — the entire old heap is freed at once
|
||||
|
||||
### Copying and Forwarding
|
||||
|
||||
When an object is copied from old space to new space:
|
||||
|
||||
1. The object's data is copied to the next free position in new space
|
||||
2. The old object's header is overwritten with a **forwarding pointer** (`OBJ_FORWARD`) containing the new address
|
||||
3. Future references to the old address find the forwarding pointer and follow it to the new location
|
||||
|
||||
```
|
||||
Old space: New space:
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ OBJ_FORWARD ─┼────────> │ copied object│
|
||||
│ (new addr) │ │ │
|
||||
└──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### Scan Phase
|
||||
|
||||
After roots are copied, the collector scans new space linearly. For each object, it examines every JSValue field:
|
||||
|
||||
- If the field points to old space, copy the referenced object (or follow its forwarding pointer if already copied)
|
||||
- If the field points to stone memory, skip it (stone objects are permanent)
|
||||
- If the field is an immediate value (integer, boolean, null, immediate string), skip it
|
||||
|
||||
The scan continues until the scan pointer catches up with the allocation pointer — at that point, all live objects have been found and copied.
|
||||
|
||||
## Roots
|
||||
|
||||
The collector traces from these root sources:
|
||||
|
||||
- **Global object** — all global variables
|
||||
- **Class prototypes** — built-in type prototypes
|
||||
- **Exception** — the current exception value
|
||||
- **Value stack** — all values on the operand stack
|
||||
- **Frame stack** — all stack frames (bytecode and register VM)
|
||||
- **GC reference stack** — manually registered roots (via `JS_PUSH_VALUE` / `JS_POP_VALUE`)
|
||||
- **Parser constant pool** — during compilation, constants being built
|
||||
|
||||
## Per-Actor Heaps
|
||||
|
||||
Each actor maintains its own heap with independent collection:
|
||||
|
||||
- No stop-the-world pauses across actors
|
||||
- No synchronization between collectors
|
||||
- Each actor's GC runs at the end of a turn (between message deliveries)
|
||||
- Heap sizes adapt independently based on each actor's allocation patterns
|
||||
|
||||
## Heap Growth
|
||||
|
||||
The collector uses a buddy allocator for heap blocks. After each collection, if less than 20% of the heap was recovered, the next block size is doubled. The new space size is: `max(live_estimate + alloc_size, next_block_size)`.
|
||||
|
||||
All allocations within a heap block use bump allocation (advance a pointer), which is extremely fast.
|
||||
|
||||
## Alignment
|
||||
|
||||
All objects are aligned to 8-byte boundaries. Object sizes are rounded up to ensure this alignment, which guarantees that the low 3 bits of any heap pointer are always zero — available for JSValue tag bits.
|
||||
|
||||
## Interaction with Stone Memory
|
||||
|
||||
Stone memory objects (S bit set) are never copied by the collector. When the scanner encounters a pointer to stone memory, it leaves it unchanged. This means:
|
||||
|
||||
- Stone objects are effectively permanent GC roots
|
||||
- No overhead for tracing through immutable object graphs
|
||||
- Module return values and interned strings impose zero GC cost
|
||||
Reference in New Issue
Block a user