Parent: #493 Related: #474, #480, #482, #495, #884, #885, #888
Problem
The realm-local unhandled- and handled-rejection queues are growable arrays, and each host checkpoint removes index zero with orderedRemove(0). The private ABI drains those functions in a loop, so N JavaScript-created rejection notifications copy Θ(N²) Promise pointers while repeatedly holding realm_lock. Rejection fanout is script-controlled, making this an avoidable latency and contention surface.
The same growable-array append is the fallible publication boundary tracked by #884. A cursor would fix front shifting but retain that boundary; the final design should solve both issues without adding a second queue representation.
Required implementation
- Replace array front-removal with one allocation-free realm-owned FIFO: Context head/tail roots plus a single intrusive successor per queued Promise.
- Keep append and dequeue O(1), clear every removed successor immediately, and reset head/tail/length exactly at exhaustion.
- Enforce single membership: a Promise may enter the handled queue only after leaving the unhandled queue, and may never be linked twice.
- Trace every pending intrusive node under
realm_lock; relocate both Context endpoints and every Promise successor while mutators are stopped. - Preserve early-handled skipping, one-time notification state, and reentrant ordering: callbacks may enqueue more notifications, which follow the pending suffix and drain in the same checkpoint.
- Keep Promise in its existing 256-byte GC allocation class.
- Do not reverse events, use unordered removal, cap valid fanout, defer required notifications, weaken locking, add an emergency allocation pool, or recognize particular workloads.
Acceptance
- A deterministic 4,096-entry witness proves allocation-free O(1) FIFO append/pop, length-bounded iteration, cleared links, reentrant tail insertion, exact exhaustion reset, and reuse.
- Unhandled and later-handled notifications retain FIFO order, early-handled entries are skipped, and reentrant enqueues follow pending entries.
- Precise tracing and moving relocation cover all pending nodes and rewrite both endpoints/successors without retaining consumed nodes.
- Promise allocation density, empty/repeated behavior, teardown, and publication invariants remain exact.
- Focused Promise/private-ABI tests pass in Debug, ReleaseSafe, and suppression-free TSan; relevant threadfuzz and the full unit suite have zero failures/leaks.
- Exact affected Test262 Promise coverage has zero regressions; documentation states the allocation-free FIFO contract without unsupported throughput claims.