Skip to content

gc: gc_runtime_root_holders.py cannot see perry_thread_local! — 248 of ~881 holders invisible #8544

Description

@proggeramlug

Problem

scripts/gc_runtime_root_holders.py enumerates static / thread_local! /
lazy_static! declarations. It does not know about Perry's own TLS macro,
perry_thread_local! (crates/perry-runtime/src/tls_hot.rs), so every holder
declared through it is invisible to the gate.

Measured on 7c22189aa (main):

count
declarations the gate scans 633
declarations inside perry_thread_local! blocks, in the two core crates 248 (75 files)
gate script mentions of perry_thread_local 0

So the gate sees roughly 72% of the population it is written to guard.

Spot-checked, none of these is enumerated (--list has no row for any):

  • EXCEPTION_STATE: UnsafeCell<ExceptionState> (exception.rs)
  • TYPED_ARRAY_OWN_PROPS: RefCell<PtrHashMap<usize, Vec<TypedArrayOwnProp>>> (typedarray_props.rs)
  • YOGA_NODES: RefCell<Option<HashMap<u32, YogaNode>>> (yoga.rs)
  • PENDING_REQUIRE_PARENT, MODULE_PATH_REGISTRY, PATH_MODULE_INIT_ADDRS (module_require*)

A plain thread_local!/static in the same crates is enumerated, so this is
specifically the macro, not the file set.

Why it matters

The failure direction is toward green. A narrower match means fewer hits and
a passing gate, and nothing ever prompts the check. Concretely, today:

MODULE_PATH_REGISTRY holds NaN-boxed heap pointers and is correctly scanned
(scan_module_path_roots_mut, registered in gc/mod.rs). But because the gate
cannot see the declaration, deleting that reg_scanner! line would not turn
the gate red
— the exact scenario the gate exists to prevent.

This is the same class as #8207 and the #8163 hunt: a too-narrow symbol/declaration
regex silently removing holders from consideration.

Fix

Teach the enumerator to parse perry_thread_local! { ... } (and the
crate::perry_thread_local! spelling) the way it already parses thread_local!
blocks — the inner syntax is the same static NAME: TYPE = init;.

Budget for the unmasking. Making the gate see 248 more declarations will
surface holders that currently have no verdict, and the gate fails on an
unclassified holder by design. Expect it to go red until they are triaged; that
redness is the fix working, not a regression. Worth landing the enumerator change
and the triage together, or behind a temporary allowlist that can only shrink.

Please also report the population delta (633 -> N) in the PR: a scanner fix
without a stated blast radius is indistinguishable from one nobody measured.

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