|
| 1 | +### Fixed |
| 2 | + |
| 3 | +- **The `typeof` string-cache rooting test drove six of the eight cache |
| 4 | + cells.** `scan_typeof_string_roots_mut` is eight hand-written `visit(...)` |
| 5 | + calls, one per interned `typeof` result, so `TYPEOF_BIGINT` and |
| 6 | + `TYPEOF_SYMBOL` could have lost theirs and no test would have noticed. |
| 7 | + `test_gap_gc_typeof_string_cache_rooting.ts` now drives all eight. |
| 8 | + |
| 9 | + Measured by unregistering the scanner and rebuilding, rather than assumed: |
| 10 | + |
| 11 | + | | default | `POLLS=1`, compiled *and* run with the flag | |
| 12 | + |---|---|---| |
| 13 | + | registered | `bad 0` | `bad 0` 5/5 | |
| 14 | + | unregistered | — | `bad 592` 5/5 | |
| 15 | + |
| 16 | + The six-cell version of this test reported `bad 444`, and |
| 17 | + `592 / 8 == 444 / 6 == 74` — the two added cells go bad at the same |
| 18 | + collection as the other six, which is what says they are really covered |
| 19 | + rather than decorative. |
| 20 | + |
| 21 | +### Added |
| 22 | + |
| 23 | +- **Rust-side mark, rewrite and registration tests for both interned-string |
| 24 | + root scanners** (`gc/tests/runtime_roots/interned_string_caches.rs`): |
| 25 | + `builtins::arithmetic::scan_typeof_string_roots_mut` and |
| 26 | + `json::raw_json::scan_raw_json_key_root_mut`. Neither had one; #7211 |
| 27 | + registered them and the `.ts` gap test covered only the `typeof` side, from |
| 28 | + one direction, at six cells. |
| 29 | + |
| 30 | + Marking and rewriting are asserted separately on purpose. Marking alone |
| 31 | + keeps the string alive but still hands out a pre-move address after a |
| 32 | + copying minor, which is the #7211 failure in full — the distinction |
| 33 | + `docs/src/internals/gc-rooting-invariant.md` keeps having to make. The |
| 34 | + registration test is separate again, because either scanner can be called |
| 35 | + directly from a test whether or not `gc_init` ever names it, and an |
| 36 | + unregistered scanner is a no-op in production. |
| 37 | + |
| 38 | + Sabotage-tested, per the project's own rule that a gate must be shown able |
| 39 | + to fail: |
| 40 | + |
| 41 | + | sabotage | result | |
| 42 | + |---|---| |
| 43 | + | drop `visit(&TYPEOF_BIGINT, visitor)` | mark and rewrite tests red, naming `cell 6` | |
| 44 | + | drop the `gc_init` registration of `scan_raw_json_key_root_mut` | registration test red | |
| 45 | + |
| 46 | +### Changed |
| 47 | + |
| 48 | +- **`reset_typeof_string_cache_for_test` was dead code.** It had no callers, |
| 49 | + and its doc comment described a shared arena-reset teardown that does not |
| 50 | + exist in this repo — every other `_for_test` helper in `perry-runtime` is |
| 51 | + called. It is now driven by the tests above, and its eight-cell list is |
| 52 | + shared with the new `populate_*` / `*_cells_for_test` helpers instead of |
| 53 | + being written out a second time. `json/raw_json.rs` gets the matching trio |
| 54 | + (`reset_`, `populate_`, `peek_`), which is what made the rawJSON scanner |
| 55 | + testable at all. |
| 56 | + |
| 57 | + All `#[cfg(test)]`; no runtime behavior changes. |
| 58 | + |
| 59 | +- **`CLAUDE.md`: the two #7226 entries are folded back toward the length of |
| 60 | + the entries around them**, 2006 → 1722 and 1358 → 903 characters, in a |
| 61 | + section whose other bullets run 242-355. The file's own opening note says |
| 62 | + to keep it concise and put detail in `changelog.d/`. Nothing operational |
| 63 | + was dropped: the incident narrative is already in |
| 64 | + `changelog.d/7219-registry-gc-unrooted-caches.md`, and the detector knobs |
| 65 | + the new bullet re-listed (`PERRY_GC_ZEAL`, `PERRY_GC_PROTECT_FROMSPACE`, |
| 66 | + `PERRY_GC_PROTECT_FROMSPACE_DEPTH`) are documented in full, with their |
| 67 | + exact gating, two sections above under "Rooting-bug instruments". |
| 68 | + |
| 69 | +- **`changelog.d/7214-closure-calln-stale-registers.md` line 117 opened with |
| 70 | + `#7161`**, which markdownlint reads as a malformed ATX heading (MD018). |
| 71 | + Rewrapped so the reference is not the first thing on the line. The |
| 72 | + rendered text is unchanged — CommonMark requires a space after `#`, so it |
| 73 | + was never a heading, and the line is a paragraph continuation besides. |
| 74 | + |
| 75 | +## Not changed, and why |
| 76 | + |
| 77 | +**`SYMBOL_ROOTS` in `scripts/gc_root_dominance_check.py` does not need the |
| 78 | +`crates/perry-ext-*` crates.** `--audit-alloc-re` is a liveness check on |
| 79 | +`ALLOC_RE`'s alternatives — it asks whether each alternative matches at least |
| 80 | +one real exported symbol — so widening the symbol corpus can only make it |
| 81 | +more permissive, never less. Measured: 3775 symbols under the current two |
| 82 | +roots, 394 more that exist only in the 38 ext crates, and the dead-alternative |
| 83 | +verdict is the empty list with or without them. No alternative is kept alive |
| 84 | +only by an ext symbol. The 26 ext-only allocating symbols already match |
| 85 | +`ALLOC_RE` through the `_new` / `_create` conventions, so what the checker |
| 86 | +detects is unchanged either way. |
| 87 | + |
| 88 | +A symbol that allocates and matches no alternative would be a real hole, but |
| 89 | +it is a hole in `ALLOC_RE` and this audit runs the other direction, so adding |
| 90 | +roots would not surface it. |
0 commit comments