ReviewOS

zig-utils/zig-js

GC: release inline-object property locks before edge marking

#542
Closed chris opened this 8 days ago ·
8 days ago

Summary

Split from #532 after a post-change eight-lane CPU sample showed the remaining present-property waits are primarily mutators yielding while the concurrent marker holds Object.property_lock. traceObject currently retains that object-local lock while every captured slot/accessor edge enters the heap marker; those mark calls perform GC-header lookup and can wait on allocation metadata, unnecessarily extending the object critical section.

Parent collector work: #476. Related object-model scaling: #478 and #532.

Requirements

  • Snapshot only a representation whose complete edge set is bounded and stable while property_lock is held; release the lock before heap marking only after copying all values and the immutable Shape identity needed for diagnostics.
  • Keep external/growable slots, accessor maps, C-API custom-accessor maps, and all other mutable backing stores on their locked trace paths.
  • Preserve the concurrent-mark insertion-barrier invariant: writes after the snapshot must shade the new target.
  • Preserve moving-GC relocation and world-stopped tracing behavior.
  • Do not weaken locks globally, add benchmark recognition, or touch stacks, queues, jobs, Promise/microtask, or Worker lifecycle code.

Acceptance

  • Focused concurrent-mark witness proves inline named values remain live while peers update and transition objects.
  • No-GIL TSan and threadfuzz remain clean.
  • Full unit suite passes without leaks.
  • Exact invocation attribution retains frozen shape-transition checksums and shows reduced present-property lock waiting/contention under concurrent tracing.
  • Exact-parent Object/Array/Proxy test262 has zero regressions.
  • Any performance statement is backed by exact-parent stable evidence; diagnostic sampling alone is not a claim.
8 days ago

Rejected after implementation and measurement; no code landed.

The bounded inline-edge snapshot passed its focused concurrent marker/mutator witness normally and under TSan, but it did not reduce the measured hotspot. On the exact frozen 8-lane invocation, the parent recorded 347 incremental property-lock contentions / 1,496 spins and the candidate recorded 364 / 4,254 in one diagnostic pair (scheduling-dependent, not a regression claim). An amplified CPU sample still placed every worker yield under namedOwnPropertySnapshot; inspection showed the relevant shared holders have non-null accessor maps, so unrelated-name prototype probes bypass #532's null-map fast path and serialize before Shape absence can decide the descriptor.

The candidate and test were reverted. The next work stays in #532 and will use exact accessor-name publication; growable GC storage remains unchanged. This avoids landing a race-safe but causally ineffective workaround.

Sign in to comment on this issue.