ReviewOS

zig-utils/zig-js

GC: adapt the final cell slab to bounded-heap headroom

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

Problem

GcCellBacking.addChunk requests a fixed 64 KiB chunk for the 128-byte Object size class while holding its internal allocator lock. That lock correctly blocks recursive allocation-failure collection, but under a 4 MiB Context limit it can leave usable headroom stranded: the exact dev.1818 recovery witness has 24,084 bytes remaining while every post-recovery Object allocation asks for 65,536 bytes and fails.

Fresh Linux evidence: CI unit shard 0 reaches the bounded-heap torn-object witness and fails after the pressure catch. Local allocation diagnostics reproduce fixed 65,536-byte denials with 22.9-24.7 KiB remaining. Moving Environment key allocation out of its trace-sensitive lock lets the script reach and catch these Object OOMs, but cannot make the fixed slab fit.

Required implementation

  • Keep the normal 64/256/384 KiB size-class chunks for throughput when they fit.
  • If the preferred chunk allocation fails, halve the slot count until the first smaller slot-aligned chunk fits, down to one cell. This bounded geometric search avoids an unbounded O(number-of-slots) OOM-probe loop while selecting the largest successful subdivision it probes.
  • Allocate matching realm metadata transactionally; a failed chunk/metadata pair must publish nothing and leak nothing.
  • Preserve exact ownership classification, free/published bitmaps, address ordering, relocation, trimming, batch allocation, and parallel locking for variable-length chunks.
  • Do not raise the heap limit, delegate managed cells around GcCellBacking, or special-case the test.

Acceptance

  • A focused bounded allocator test proves preferred 64 KiB failure falls back to a smaller owned chunk and accounts/frees it exactly.
  • Context heap_limit_bytes never publishes a torn object under recovery pressure validates at least one complete post-recovery object under exact dev.1818, normal and TSan.
  • Cell-backing unit filters, full unit shard 0, and dependency audit pass without leaks.

Parent: #480 Related: #628, #634, #636, #100

9 days ago

Design clarification: the allocator API cannot report remaining headroom. Exhaustively decrementing thousands of size-class slots while recovery is blocked would turn one OOM into an unbounded probe loop. The implementation therefore preserves the preferred throughput slab and uses a bounded halving sequence, transactionally testing chunk bytes plus realm metadata at each size.

9 days ago

3decd2e1 lands the bounded geometric cell-slab fallback. Cell backing passes 27/27 normal and TSan, the exact 4 MiB post-recovery object witness passes normal and TSan, and exact shard 0 passes 436/436 with zero leaks. Fresh Linux CI is pending.

9 days ago

Fresh Linux run 32388315489 passed the normal recovery witness, but TSan unit shard 2 exhausted every one of the 500 post-recovery attempts (made == 0) under competing shard load. There was no torn publication and no leak, but this does not satisfy the unchanged acceptance oracle, so I am keeping the issue open. The exact unchanged TSan witness passes locally 3/3 at 12.5–13.9 s on current main. Fresh Linux validation for c6dcbe6d is pending; the 4 MiB cap and success requirements remain unchanged.

9 days ago

Acceptance is complete. The adaptive final-slab implementation in 3decd2e1 retains exact ownership/accounting coverage, while #655 returns already-empty tails under quota pressure. The corrected unchanged-pressure oracle passes fresh Linux normal shard 3 and TSan shard 3, zero leaks.

Sign in to comment on this issue.