You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Define and implement the safe recovery policy for GC-backed generator / iterator-helper side-store allocation pressure under live no-GIL peers.
Why this is separate
#30 has proven no-GIL emergency recovery for GC-cell slabs and safepoint-owned ArrayBuffer byte slabs, while trace-sensitive Object / Promise / Environment / async-generator request critical sections intentionally fail closed.
Generator and iterator-helper side stores are a different seam: the parallel tracer defers their mutable storage to the world-stopped finish path because a running generator's exec stack, async-generator request state, resumable handler buffers, and iterator-helper backing state are not sound to trace directly while mutators run. The allocation-failure collector refuses to sweep while those deferred edges remain, so treating these as an ordinary side-store retry class would either fail to reclaim or risk weakening the tracing invariant.
Current status
The negative/fail-closed policy is now executable for the deferred generator/iterator family:
Suspended generator stack / execution storage fails closed while no-GIL peers are live.
Resumable generator handler buffers fail closed while no-GIL peers are live.
Pending async-generator request buffers fail closed while no-GIL peers are live.
Iterator-helper backing state fails closed while no-GIL peers are live.
Deferred-cell aborts are reported separately as gc_par_deferred_aborts / def-abort, while still preserving the existing round-limit abort accounting identity.
docs/threads/limits.md and docs/threads/testing.md distinguish trace-sensitive locks from deferred generator/iterator tracing.
The current design evidence points to a conservative rule: deferred generator/iterator state should not be recovered by the live no-GIL allocation-failure collector unless a future allocation site can prove no deferred edges remain, or the collector can finish through a sound world-stopped path. No positive recoverable generator/iterator class has been proven yet.
Closure policy
Decision after the combined main gate for d0092f5e passed (https://github.com/zig-utils/zig-js/actions/runs/29201642565): no current generator/iterator side-store allocation class is sound to recover under live no-GIL peers. The implemented policy is intentionally all-fail-closed while deferred generator/iterator edges remain pending.
This preserves the tracer invariant: a parallel allocation-failure collector may not claim a sweep while suspended generator stacks, resumable handler buffers, async-generator request buffers, or iterator-helper backing state have been deferred to the world-stopped finish path.
Future work should reopen this tracker or file a narrower follow-up only if a specific allocation site can prove either that no deferred edges remain or that recovery can finish through a sound world-stopped path. Any such positive class needs a focused witness plus the existing negative fail-closed coverage.
Acceptance criteria
No-GIL TSan and semantic gates remain suppression-free.
Every newly recoverable generator/iterator allocation class has a bounded focused test.
Deferred generator/iterator tracing still prevents unsafe parallel sweep; no generic side-store retry bypasses that invariant.
Parent: #30
Goal
Define and implement the safe recovery policy for GC-backed generator / iterator-helper side-store allocation pressure under live no-GIL peers.
Why this is separate
#30 has proven no-GIL emergency recovery for GC-cell slabs and safepoint-owned
ArrayBufferbyte slabs, while trace-sensitive Object / Promise / Environment / async-generator request critical sections intentionally fail closed.Generator and iterator-helper side stores are a different seam: the parallel tracer defers their mutable storage to the world-stopped finish path because a running generator's
execstack, async-generator request state, resumable handler buffers, and iterator-helper backing state are not sound to trace directly while mutators run. The allocation-failure collector refuses to sweep while those deferred edges remain, so treating these as an ordinary side-store retry class would either fail to reclaim or risk weakening the tracing invariant.Current status
The negative/fail-closed policy is now executable for the deferred generator/iterator family:
gc_par_deferred_aborts/def-abort, while still preserving the existing round-limit abort accounting identity.docs/threads/limits.mdanddocs/threads/testing.mddistinguish trace-sensitive locks from deferred generator/iterator tracing.The current design evidence points to a conservative rule: deferred generator/iterator state should not be recovered by the live no-GIL allocation-failure collector unless a future allocation site can prove no deferred edges remain, or the collector can finish through a sound world-stopped path. No positive recoverable generator/iterator class has been proven yet.
Closure policy
Decision after the combined
maingate ford0092f5epassed (https://github.com/zig-utils/zig-js/actions/runs/29201642565): no current generator/iterator side-store allocation class is sound to recover under live no-GIL peers. The implemented policy is intentionally all-fail-closed while deferred generator/iterator edges remain pending.This preserves the tracer invariant: a parallel allocation-failure collector may not claim a sweep while suspended generator stacks, resumable handler buffers, async-generator request buffers, or iterator-helper backing state have been deferred to the world-stopped finish path.
Future work should reopen this tracker or file a narrower follow-up only if a specific allocation site can prove either that no deferred edges remain or that recovery can finish through a sound world-stopped path. Any such positive class needs a focused witness plus the existing negative fail-closed coverage.
Acceptance criteria