ReviewOS

zig-utils/zig-js

GC: route shared-heap cells to their allocating realm

#421
Closed chris opened this 9 days ago ·
9 days ago

Parent: #415 Depends on: #420 GC parent: #144 Roadmap: #134

Record allocation ownership outside zig-gc’s compact stable-ID header and use it for every realm-sensitive collector callback.

Acceptance:

  • Record a stable realm ID for each owned backing slot without per-cell heap allocation or header growth.
  • Preserve ownership across batch publication, sweep/unpublication, slot reuse, and relocation commit/rollback.
  • Route allocation recovery, weak pruning/cleanup, finalization counters, side-storage release, and deferred embedder callbacks to the owning live/retiring realm.
  • Reject or fail closed when an allocation has no active registered realm.
  • Add multi-realm weak, external-owner, relocation, slot-reuse, and TSan evidence.
9 days ago

Implemented the per-cell ownership foundation on main in c3cfb00.

What is now concrete:

  • stable u32 realm IDs (0 is fail-closed/unowned; the heap owner is 1; siblings receive monotonic IDs under the heap registry lock),
  • one realm-ID vector per GcCellBacking slab chunk, with no zig-gc header growth and no allocation per cell,
  • single and batch publication record the thread's active realm,
  • unpublication preserves ownership through finalization,
  • actual storage release clears ownership before reuse,
  • relocation rollback leaves the destination unowned, while commit atomically transfers old→new ownership,
  • an interior payload address can resolve its realm even after unpublication.

Focused evidence: all 27 GC cell backing Debug tests pass with zero leaks, plus the exact registry trace/relocate/retire test. The new tests cover batch publication, unpublication/finalization visibility, reuse under a different realm, relocation rollback/commit, and sibling-ID publication.

Still open: route allocation recovery, weak/finalization work, realm-local side storage, and deferred embedder callbacks through the recorded owner; then add the multi-realm TSan/relocation/reuse integration gate. No README benchmark scores changed because this commit did not rerun or invalidate the benchmark corpus.

9 days ago

Second #421 slice is on main in 138d203.

Realm-aware routing now covers:

  • allocation-failure recovery through the active registered realm (zero/unknown IDs fail closed),
  • heap-wide weak-work discovery across live and retiring realms,
  • per-cell after-weak work and finalization through the side-table owner,
  • object/string/generator side-storage allocation and accounting through the active realm,
  • deferred weak, external-buffer, external-string, and C-API finalizer callbacks for live and retiring realms, copied out before callbacks so no registry lock is held across arbitrary embedder code,
  • two-phase retirement: removal from roots first, callback routing retained until every attributed cell is finalized/freed, then explicit release,
  • nested Context and shared-thread entry state restores both heap and realm instead of collapsing to the heap owner,
  • Worker thread, postMessage, and receive structured-clone boundaries carry the Interpreter's owning realm.

The first exact CI run for c3cfb00 proved the fail-closed assertion was useful: both tsan-unit (shard 1/4) and tsan-threadfuzz-lifecycle found Worker structured-clone allocations with no active realm. Exact logs pointed to setCellPublishedLocked from Worker deserialize/serialize. 138d203 fixes those real entry boundaries.

Evidence after the fix:

  • Debug registry/retirement test: 3/3, zero leaks; includes sibling object + managed string finalization, weak callback, external-buffer callback, and release refusal while cells remain.
  • ReleaseSafe registry group: 4/4, zero leaks.
  • TSan registry/concurrent add-retire group: 4/4, zero leaks.
  • exact four-worker TSan unit reproduction: 3/3, zero leaks.
  • exact threadfuzz lifecycle TSan profile: 112 programs from seed 1, 0 failures (153481 ms).

#421 remains open until #420 wires the production precise sibling bootstrap/C-API entry path onto this machinery and the final integrated multi-realm gate is green. Benchmark scores and README were intentionally unchanged: no benchmark corpus was rerun or invalidated.

9 days ago

Completed by c3cfb00 and 138d203. Ownership, routing, live/retiring failure behavior, relocation/reuse, external/weak callbacks, ReleaseSafe, and TSan evidence are recorded above. Safe terminal destruction continues in #419.

Sign in to comment on this issue.