Problem
After #104 removed most generic VM fallback allocation, the dominant 8-lane shared object-churn cost moved into the GC cell backing. A fresh 10-second sample recorded:
- GcCellBacking.allocFn: 10,150 samples
- gc.allocObjectBatch: 6,955 samples
- heap.Heap.sweepPhaseLocked: 1,976 samples
- heap.Heap.headerForPayload: 1,406 samples
- generic Heap.create fallback: 1,055 samples
zig-gc createBatch publishes metadata once, but requests each of the 17 same-size slabs separately. GcCellBacking consequently acquires the same bucket lock 17 times.
Parent: #97 Depends on: zig-utils/zig-gc#18 Related: #102, #104
Direction
Implement the zig-gc optional batch-backing hook in GcCellBacking so one allocation batch acquires its size-class lock once, fills freed slots first, then fresh slots, and returns the successful prefix. Keep chunk growth, ownership indexes, reuse counters, teardown behavior, and allocator fallback exact.
Acceptance
- Focused tests prove one bucket-lock acquisition for an eligible batch.
- Reuse and fresh allocation can coexist in one batch without duplicate slots or incorrect counters.
- Short-prefix/OOM behavior preserves sequential recovery ordering.
- Focused regular and TSan shared-worker coverage passes.
- Exact A/B covers direct and shared 1/2/4/8 lanes with stable checksums.
- A retained material change refreshes README.md, docs/benchmarks.md, and the raw full benchmark publication before closure.
- Full zig build test runs once after the retained implementation is ready.