Parent: #1
Goal
Make the GC-backed threaded runtime competitive for allocation-heavy and create/destroy-heavy embedders without weakening no-GIL correctness.
Current baseline
- GC cells use size-class slabs with lazy bump allocation, freelist reuse, per-size-class fast-path locks, tail-slab trimming, exact bucket counters, and slab-owned bulk teardown.
- New cells enter a non-moving, one-cycle nursery. Demand-driven quiescent minor collection traces young roots plus remembered old owners, reclaims dead young cells, and immediately tenures survivors.
- Owner-aware strong barriers cover Object, Environment, Promise, collection, prototype, generator-request, and native synchronization side-record stores. Broad maybe-managed root/barrier inputs use exact live-payload membership instead of candidate-header peeks, with zig-gc's payload index keeping that safety off the O(live-cells) path. Weak-container barriers preserve WeakRef, WeakMap/WeakSet, and FinalizationRegistry semantics. Mutable type-erased side-cell kinds are conservatively rescanned.
- Remembered-set allocation failure falls back to the existing precise full collector. Explicit
collectGarbage()remains full-heap; no-GIL mid-script collection remains the abort-safe full concurrent protocol. gc-profileseparates lifecycle, allocation, backing, churn, finalizer, and nursery attribution. Focused cases are available with-Dgc-profile-case='<exact table name>'so nursery and lifecycle rows can be checked without paying for the full profile matrix.- Nursery rows now include object-only and array/object allocation shapes, young/reclaimed/promoted counts and bytes, survival/reclamation percentages, the computed next nursery threshold, and repeated-cycle threshold drift. Sizing policy can be judged from pause, survival, reclamation, allocation shape, and threshold trajectory together.
zig-gcrecords last-minor young/reclaimed/promoted byte totals, uses gradual threshold decay after low-survival cycles, caps upward threshold growth to the observed young batch size, trims oversized empty collector scratch after post-spike collections, and serializes allocation metadata for single-mutator concurrent marking without opting that mode into the multi-mutator parallel-GC protocol.- Long-lived context reuse remains materially cheaper than create-per-task use; the supported guidance is a bounded pool per isolation domain, one task at a time per context unless the host intentionally shares a realm, and quiescent
collectGarbage()at measured task boundaries.
Milestones
- Design and implement a nursery/young-generation policy with remembered-set coverage.
- Add promotion/tenuring and full-heap fallback invariants.
- Prove write-barrier coverage for old-to-young references under no-GIL mutation.
- Reduce intrinsic context bootstrap and teardown work further, or document a supported pooling/reuse pattern with measured bounds.
- Add allocation/collection pause, promotion, byte-pressure, survival-rate, allocation-shape, and next-threshold metrics to
gc-profile. - Add focused GC profile filters so small nursery/lifecycle checks do not require the full matrix.
- Tune first-pass nursery threshold policy: gradual decay after low-survival cycles and capped growth after high-survival fixed-size bursts.
- Trim oversized empty collector scratch so pooled contexts do not retain arbitrary one-off spike capacity.
- Add focused unit, TSan, concurrent-GC regression, corpus, weak/finalization, and churn/fuzzer coverage for the policy.
Remaining work
- Tune nursery sizing and pause/throughput policy across more workload shapes using the focused profile rows.
- Decide from measurements whether multi-age, copying/moving, or parallel minor collection earns its complexity.
- Continue Context lifecycle reductions where profile evidence shows a bottleneck; keep the pooling guidance current as those costs move.
- Keep old-to-young barrier coverage, exact maybe-managed safety, scratch-lifetime behavior, and weak semantics regression-gated as mutable engine state evolves.
Acceptance criteria
- No regression in full unit, PR-249, suppression-witness, test262-parallel, or concurrent fuzzer gates.
- Allocation and lifecycle changes have before/after profile evidence.
- The implementation docs distinguish slab allocation, nursery policy, full/concurrent collection, and embedder lifecycle guidance.