Skip to content

gc-matrix: four of the six PR-gating arms run ZERO copying minors corpus-wide (default/verify_evac/cons_scan_off at copy-minor 0/49; header still claims 12/22) #7255

Closed

Description

@proggeramlug

scripts/gc_repsel_matrix.sh's PR_ARMS subset is what gc-stress runs on a pull request. Four of its six arms run zero copying minors across the entire corpus, so on a PR they can only ever produce UNVER.

Measured at origin/main = 64c1f56fb, --arms all --pressure 8, node 26.5.1, 49 corpus files — the run's own liveness summary:

default                  requires=scavenge  collected 24/49   moved-objects 0/49   copy-minor  0/49
verify_evac              requires=scavenge  collected 24/49   moved-objects 0/49   copy-minor  0/49
cons_scan_off            requires=scavenge  collected 24/49   moved-objects 0/49   copy-minor  0/49
cons_scan_off_force      requires=scavenge  collected 24/49   moved-objects 0/49   copy-minor  0/49
shipped_default          requires=none      collected  3/49   moved-objects 0/49   copy-minor  0/49
evac_minor               requires=move      collected 48/49   moved-objects 48/49  copy-minor 48/49
force_verify             requires=move      collected 48/49   moved-objects 48/49  copy-minor 48/49

PR_ARMS = default,evac_minor,verify_evac,force_verify,cons_scan_off,shipped_default.

Why this matters more than a stale comment

The script's header documents default as the arm that closed the per-PR hole, in the strongest terms it has:

THIS SUBSET CAN NOW REPRODUCE THE RELOCATING-MINOR DEFECT CLASS (#6993). Until #7024 it could not, and that was the hole … So the whole "raw reference held across a relocating collection" class — #6951, #6972, #6982, #6991, #6992 — was invisible per PR and could only go red after merge, on push.

and quotes the measurement that justified it:

arm            copy-minor before #7024   after
default              0/22                12/22

Today it is 0/49. The hole the header declares closed is open again, and the header is the reason nobody re-derived it: it reads as a settled fact with numbers attached.

Two further observations from the same measurement:

  • The --pressure knob does not move this. evac_minor on test_gap_repsel_p4a3_ptr_numarray reports cycles=1 scavenged=3585 identically at --pressure 8, 4, 2 and 1. Turning the pressure up does not turn the requires=scavenge arms on.
  • An all-UNVER table exits 0. gc_repsel_matrix.sh's exit status counts only FAIL. gc-moving-witnesses wraps its invocation in a checker that rejects UNVER as hard as FAIL — deliberately, and its workflow says why. gc-stress has no such step, so "the four arms went inert" is not a signal it can emit.

Probable cause, not verified

#7161 flipped the evacuating minor default-OFF pending #7154, which is also why the pinned gc-ratchet baseline currently reports minor_cycles=0 everywhere (noted in #7194). The requires=move arms carry %E% (PERRY_GC_INCREMENTAL=0 PERRY_CONSERVATIVE_STACK_SCAN=off) and still relocate; the requires=scavenge arms deliberately do not, which is the whole point of them — they are supposed to prove the shipped route relocates. Whether the 0/49 is entirely #7161 or also involves the --pressure/defer-cap interaction of #7024/#7025 is not established here.

What should not happen

Making gc-stress reject UNVER today would turn the job permanently red on four arms with no triage — the untriaged-permanent-red state #7194 was opened about. The order is: decide what the arms should be under the current default (revert #7161, re-tune, or re-declare the arms' requires= honestly), then add the assertion.

Related: #7194 (the red cell that prompted the measurement, now fixed), #7187 (lazy barrier arming / the #7161 revert timeline), #7024, #7025, #6993.

Activity

  1. proggeramlug commented on Aug 2, 2026

    @proggeramlug
    ContributorAuthor

    Independently reproduced on main = d4ac65f21 as part of the sweep in #7262, and it is blocking two other issues from being judged at all.

    Reproduction

    Five corpus binaries, each compiled with no compile-time GC env, each run under three arm definitions taken from scripts/gc_repsel_matrix.sh (default = %P% only; verify_evac = %P% PERRY_GC_VERIFY_EVACUATION=1; evac_minor = %P% %E%), counting [gc-copy-minor] ran under PERRY_GC_DIAG=1:

    file default verify_evac evac_minor
    test_gap_gc_spread_accessor_rooting 0 0 5
    test_gap_gc_method_receiver_rooting 0 0 5
    test_gap_gc_index_get_receiver_rooting 0 0 8
    test_gap_gc_symbol_local_rooting 0 0 88
    test_gap_repsel_p4a3_ptr_numarray 0 0 1

    Same binaries, same host, same moment. The requires=scavenge arms are inert and the requires=move arms are not, exactly as reported.

    The cost, which is larger than the stale header

    Two open crash reports cannot currently be judged in either direction because their arms are among the inert ones:

    Both have been left open with the measurement recorded rather than closed. That is two issues whose resolution is gated on this one — so this is not a reporting-hygiene bug, it is on the critical path.

    I agree with the issue's "what should not happen": making gc-stress reject UNVER today would just produce untriaged permanent red. The ordering it proposes — decide what the arms should be under the current default, then add the assertion — is the right one, and #7187/#7161's revert timeline is the decision it waits on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions