Problem
The zig-js object_churn profile attributes substantial exclusive time to Heap.sweepPhaseLocked. Its reclaim loop currently updates live_cells, bytes_live, young_cells, and young_bytes on every dead cell, and updates the nursery counters again for each promoted survivor.
A completed full or minor sweep processes every young cell: survivors are promoted and dead young cells are reclaimed, so the nursery counters are always zero afterward. The live/reclaimed totals can likewise be accumulated locally while the existing allocation lock excludes mutations.
Proposed change
- snapshot the cycle young-byte total before the sweep
- accumulate reclaimed cell/byte totals in locals
- retain the existing per-cell finalization, unlink, magic clear, and backing free order
- commit live-byte/live-cell counters once after the loop
- zero nursery cell/byte counters once after the loop
- preserve per-cycle promoted/reclaimed statistics and collection thresholds exactly
Acceptance
- focused nursery, full-sweep, finalizer, and parallel collector tests pass
- zig-js focused GC/object-churn correctness tests pass with zero leaks
- exact-parent alternating
object_churnA/B shows a repeatable improvement - revert and close as not planned if timing evidence is neutral or regresses