Skip to content

gc-matrix: the collect-arm liveness predicate (cycles > 0) cannot tell a mid-program collection from a teardown one that frees nothing #7017

Description

@proggeramlug

Split out of #6978 (fixed in #7015). Filed by the author of that fix, because the fix makes the weakness visible rather than removing it.

scripts/gc_repsel_matrix.sh scores a collect-requirement arm as PASS when cycles > 0, counting [gc] cycle markers on stderr. After #7015 the shipped configuration does complete cycles on the small corpus files, and 171 cells moved UNVER → PASS. On the small files that cycle lands at the event-loop boundary after the program's last output, and it reclaims nothing:

45:8                                    <- last program output
[gc-safepoint] finishing a cycle parked across 2 host safepoints
[gc-step] pre_in_use=479816 post_in_use=483472 sweep_freed=0 block_reclaim=0 pct=0%
[gc] cycle

Everything allocated after the cycle armed was born black, so the sweep frees nothing. Compare PERRY_GC_INCREMENTAL=0 on the same file, which collects twice, mid-program, interleaved with the test's output.

Both shapes score identically under cycles > 0. So a cell that traverses only the retained graph at rest, at teardown, is indistinguishable from one that collected while the test's representation-selected locals were live — and the latter is the property the matrix was built to assert.

This is not fixable in the collector. With two allocation-trigger opportunities in the whole process and seven resumable cycle phases, a mid-program completion under incremental mode would have to be synchronous at the arming point — which is exactly what PERRY_GC_INCREMENTAL=0 already is. See #6978 for the per-call measurements.

Suggested direction (not prescriptive): make the collect predicate demand a productive cycle rather than any cycle. Candidates, cheapest first:

  1. require sweep_freed > 0 or block_reclaim > 0 on at least one cycle (already in the PERRY_GC_DIAG [gc-step] line the harness captures);
  2. require at least one cycle to complete before the program's last stdout line, which needs the harness to interleave the two streams for the liveness read while keeping stdout pure for the parity compare;
  3. introduce a third verdict between PASS and UNVER for "collected, but only at teardown" so the distinction stays visible instead of being folded either way.

Whatever the choice, the point of #6942 / #6946 / #6950 stands: a green cell from a collection that could not have observed the test's live data licenses the same false confidence as a green cell from no collection at all.

Refs #6978, #7015, #6950, #6946, #6942.

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