Separate from the precise-roots family: this one crashes with the conservative native-stack scan ON, so it is not an unrooted-temporary bug.
Repro
Release build, macOS arm64, origin/main + #6977 (the fix in #6977 is not on this path — PERRY_GC_INCREMENTAL=0 bypasses the budgeted stepper entirely, so this reproduces on plain main given the same escape hatch).
$ perry test-files/test_gap_repsel_gc_stress.ts -o gc_stress
$ for i in 1 2; do PERRY_GC_HEAP_LIMIT=8 PERRY_GC_INCREMENTAL=0 ./gc_stress >/dev/null; echo "rc=$?"; done
rc=139
rc=139
Intermittent — roughly 2 of 3 runs. With PERRY_GC_TRACE=1 PERRY_GC_DIAG=1 added:
run1 rc=139 output mismatch
run2 rc=0 output matches the Node oracle
run3 rc=139 output mismatch
PERRY_GC_INCREMENTAL=0 is a documented escape hatch, and it is what makes gc_check_trigger take the #5476 direct-collection arm instead of handing the trigger to the budgeted stepper. On this path the collection is a real copying minor: the passing runs report [gc-copy-minor] ran copied_objects=... in the thousands.
Why it is a distinct defect
Every other corpus file passes on this exact configuration while relocating thousands of objects (see the table in the precise-roots issue — 19/20 OK in the conservative-scan column). test_gap_repsel_gc_stress is the one corpus member deliberately built to be GC-live, i.e. the one that drives the collector hardest, and it is the only one that crashes with conservative pinning still in force. So this is not "precise roots lost a value"; something in the copying minor itself is unsound under sustained churn.
The nondeterminism (same binary, same env, different outcome per run) points at a timing/ordering window rather than a fixed miscompile.
Why nobody saw it
test_gap_repsel_gc_stress is green in the matrix's shipped-configuration arms because in the shipped configuration it never takes this path: with incremental mode on, the budgeted cycle handles the trigger. #6950 documents that the shipped automatic paths never produce a copying minor at all. So the only way to reach this crash is the escape hatch, and nothing was running the escape hatch against the corpus until #6977 added the arm.
Suggested next step
Bisect against the copying-minor phases with PERRY_GC_VERIFY_EVACUATION=1 and PERRY_GC_VERIFY_MARK=1, and check whether the crash survives PERRY_GC_FORCE_EVACUATE=0 — i.e. whether it needs actual relocation or only the copying-minor code path. A core dump / lldb backtrace on a repro run should localise it quickly given how reliably it fires.
Related: #6950, #6977, #6892 (minor-sweep finalization), #6910.
Separate from the precise-roots family: this one crashes with the conservative native-stack scan ON, so it is not an unrooted-temporary bug.
Repro
Release build, macOS arm64,
origin/main+ #6977 (the fix in #6977 is not on this path —PERRY_GC_INCREMENTAL=0bypasses the budgeted stepper entirely, so this reproduces on plainmaingiven the same escape hatch).Intermittent — roughly 2 of 3 runs. With
PERRY_GC_TRACE=1 PERRY_GC_DIAG=1added:PERRY_GC_INCREMENTAL=0is a documented escape hatch, and it is what makesgc_check_triggertake the #5476 direct-collection arm instead of handing the trigger to the budgeted stepper. On this path the collection is a real copying minor: the passing runs report[gc-copy-minor] ran copied_objects=...in the thousands.Why it is a distinct defect
Every other corpus file passes on this exact configuration while relocating thousands of objects (see the table in the precise-roots issue — 19/20 OK in the conservative-scan column).
test_gap_repsel_gc_stressis the one corpus member deliberately built to be GC-live, i.e. the one that drives the collector hardest, and it is the only one that crashes with conservative pinning still in force. So this is not "precise roots lost a value"; something in the copying minor itself is unsound under sustained churn.The nondeterminism (same binary, same env, different outcome per run) points at a timing/ordering window rather than a fixed miscompile.
Why nobody saw it
test_gap_repsel_gc_stressis green in the matrix's shipped-configuration arms because in the shipped configuration it never takes this path: with incremental mode on, the budgeted cycle handles the trigger. #6950 documents that the shipped automatic paths never produce a copying minor at all. So the only way to reach this crash is the escape hatch, and nothing was running the escape hatch against the corpus until #6977 added the arm.Suggested next step
Bisect against the copying-minor phases with
PERRY_GC_VERIFY_EVACUATION=1andPERRY_GC_VERIFY_MARK=1, and check whether the crash survivesPERRY_GC_FORCE_EVACUATE=0— i.e. whether it needs actual relocation or only the copying-minor code path. A core dump /lldbbacktrace on a repro run should localise it quickly given how reliably it fires.Related: #6950, #6977, #6892 (minor-sweep finalization), #6910.