CONSOLE_INSTANCES (crates/perry-runtime/src/builtins/console.rs) is keyed by the raw heap address of the console instance object (js_object_alloc(CONSOLE_INSTANCE_CLASS_ID, 0) as usize, console.rs:1037-1049) and its key is rekeyed by scan_console_log_singleton_roots_mut (console.rs:210, visit_metadata_usize_slot) — rewritten if the object moved, deliberately not marked.
Nothing tells the table when that object dies. It is absent from gc::dead_owner's DEAD_KEY_PRUNES fan-out and from gc_type_clear_dead_payload_side_tables; the only other uses are lookups at console.rs:960/1039.
That is the #8040 shape. A dead key is not merely a leak for a rekeyed table: the arena recycles the address, the recycled bytes are read as a GcHeader, and a coincidental GC_FLAG_FORWARDED byte makes the rewrite pass follow a garbage forwarding pointer. #8174 narrowed what can be followed out of such a header; it did not remove the dead key.
Fix: add a prune_dead_console_instance_owners and wire it into DEAD_KEY_PRUNES in crates/perry-runtime/src/gc/dead_owner.rs, with a dead_owner_side_tables.rs case.
Declared as open_gap in scripts/gc_rekeyed_key_tables.json; closing this must delete that entry, or the gate fails on the stale exemption.
Refs #8174, #8168, #8040.
CONSOLE_INSTANCES(crates/perry-runtime/src/builtins/console.rs) is keyed by the raw heap address of the console instance object (js_object_alloc(CONSOLE_INSTANCE_CLASS_ID, 0) as usize, console.rs:1037-1049) and its key is rekeyed byscan_console_log_singleton_roots_mut(console.rs:210,visit_metadata_usize_slot) — rewritten if the object moved, deliberately not marked.Nothing tells the table when that object dies. It is absent from
gc::dead_owner'sDEAD_KEY_PRUNESfan-out and fromgc_type_clear_dead_payload_side_tables; the only other uses are lookups at console.rs:960/1039.That is the #8040 shape. A dead key is not merely a leak for a rekeyed table: the arena recycles the address, the recycled bytes are read as a
GcHeader, and a coincidentalGC_FLAG_FORWARDEDbyte makes the rewrite pass follow a garbage forwarding pointer. #8174 narrowed what can be followed out of such a header; it did not remove the dead key.Fix: add a
prune_dead_console_instance_ownersand wire it intoDEAD_KEY_PRUNESincrates/perry-runtime/src/gc/dead_owner.rs, with adead_owner_side_tables.rscase.Declared as
open_gapinscripts/gc_rekeyed_key_tables.json; closing this must delete that entry, or the gate fails on the stale exemption.Refs #8174, #8168, #8040.