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
A deleted GC write barrier passes every runtime probe we have
Found while validating #8183. A release build with the write barrier deleted from the dynamic-key IC's new reference-store arm passes the entire behavioural matrix:
PERRY_GC_ZEAL=1 + from-space protection at depth 400
Byte-identical output, exit 0, on both the gap fixture and a larger adversarial one. The static IR test was the only thing that said no.
Why this matters more than one PR
CLAUDE.md's rooting-invariant guidance says the runtime instruments are the detector for the class the static checker cannot see (a runtime-side cache of a heap pointer). This is the mirror image and it is not written down anywhere: for a missing write barrier, the runtime instruments are the ones that cannot see it, and the static IR assertion is the only detector.
The reason is structural. A missing barrier does not corrupt anything at the moment of the store. It leaves a remembered-set entry unwritten, so a later minor collection fails to trace an old→young edge and drops a live object. Whether that happens depends on the object surviving to old-gen, the child staying young, and a minor landing in that window — none of which a short fixture reliably produces, and FORCE_EVACUATE/VERIFY_EVACUATION do not manufacture it either because they verify rewriting, not remembering.
This is the same shape as CLAUDE.md's hazard 4 — "the gate runs but its subject never did" — except the subject here is a negative: the absence of a barrier cannot be observed by running the program.
A green GC-canary run is not evidence a barrier is present. Several PRs in this campaign have cited FORCE_EVACUATE + VERIFY_EVACUATION as barrier evidence. That inference is invalid — it is evidence about rewriting, which is a different property.
Worth checking whether scripts/gc_store_site_inventory.py can be extended to assert barrier presence per store site, rather than only inventorying the sites. If it can, this becomes a gate instead of a review convention.
Provenance
Sabotage arms run against #8183, all four caught by its two IR tests: drop the write barrier; drop the layout note + string addref; route reference values back to put.dynic.slow; leak a barrier into the scalar arm. The third initially passed — the arm became dead IR — which is why that PR added a br i1-into-the-arm assertion. That near-miss is the same lesson twice in one PR: presence of code is not proof it is reached, and absence of a crash is not proof a barrier exists.
A deleted GC write barrier passes every runtime probe we have
Found while validating #8183. A release build with the write barrier deleted from the dynamic-key IC's new reference-store arm passes the entire behavioural matrix:
PERRY_GC_FORCE_EVACUATE=1 PERRY_GC_VERIFY_EVACUATION=1PERRY_GEN_GC=0PERRY_GC_ZEAL=1+ from-space protection at depth 400Byte-identical output, exit 0, on both the gap fixture and a larger adversarial one. The static IR test was the only thing that said no.
Why this matters more than one PR
CLAUDE.md's rooting-invariant guidance says the runtime instruments are the detector for the class the static checker cannot see (a runtime-side cache of a heap pointer). This is the mirror image and it is not written down anywhere: for a missing write barrier, the runtime instruments are the ones that cannot see it, and the static IR assertion is the only detector.
The reason is structural. A missing barrier does not corrupt anything at the moment of the store. It leaves a remembered-set entry unwritten, so a later minor collection fails to trace an old→young edge and drops a live object. Whether that happens depends on the object surviving to old-gen, the child staying young, and a minor landing in that window — none of which a short fixture reliably produces, and
FORCE_EVACUATE/VERIFY_EVACUATIONdo not manufacture it either because they verify rewriting, not remembering.This is the same shape as CLAUDE.md's hazard 4 — "the gate runs but its subject never did" — except the subject here is a negative: the absence of a barrier cannot be observed by running the program.
Consequences worth acting on
br i1into the arm, plus barrier/layout-note/addref presence); it should be the template.FORCE_EVACUATE + VERIFY_EVACUATIONas barrier evidence. That inference is invalid — it is evidence about rewriting, which is a different property.scripts/gc_store_site_inventory.pycan be extended to assert barrier presence per store site, rather than only inventorying the sites. If it can, this becomes a gate instead of a review convention.Provenance
Sabotage arms run against #8183, all four caught by its two IR tests: drop the write barrier; drop the layout note + string addref; route reference values back to
put.dynic.slow; leak a barrier into the scalar arm. The third initially passed — the arm became dead IR — which is why that PR added abr i1-into-the-arm assertion. That near-miss is the same lesson twice in one PR: presence of code is not proof it is reached, and absence of a crash is not proof a barrier exists.Refs #8183, #7511, #7154.