From 53852a7696f37c69f431b9a57a5e9683682e6f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Fri, 4 Sep 2026 13:34:09 +0000 Subject: [PATCH 1/5] fix(runtime): use hot TLS for arena right-sizing --- crates/perry-runtime/src/gc/arena_right_size.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/perry-runtime/src/gc/arena_right_size.rs b/crates/perry-runtime/src/gc/arena_right_size.rs index adcacd15c5..6b892dac61 100644 --- a/crates/perry-runtime/src/gc/arena_right_size.rs +++ b/crates/perry-runtime/src/gc/arena_right_size.rs @@ -82,7 +82,7 @@ struct ArenaRightSizeState { last_usage: ArenaUsage, } -thread_local! { +crate::perry_thread_local! { static STATE: RefCell = RefCell::new(ArenaRightSizeState::default()); #[cfg(test)] From 460ca39c37eb5762673c9df73549ac203b4333ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Fri, 4 Sep 2026 13:42:21 +0000 Subject: [PATCH 2/5] docs(changelog): correct workload units --- changelog.d/9731-arena-right-sizing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/changelog.d/9731-arena-right-sizing.md b/changelog.d/9731-arena-right-sizing.md index 78109a41f7..d902f8937e 100644 --- a/changelog.d/9731-arena-right-sizing.md +++ b/changelog.d/9731-arena-right-sizing.md @@ -14,7 +14,7 @@ stays disarmed until utilization reaches 70% or capacity grows materially into a periodic full-GC loop. On the compiled Claude Code 2.1.112 workload from the report, arena capacity -fell from 96.5 MiB before the episode to 36.7 MiB, then 35.7 MiB and 35.7 MiB -across a five-minute idle soak with about 23 MiB live. RSS fell from 401 MiB at -the first census to 132 MiB at the last, and exactly one idle full was attributed +fell from 96.5 MB before the episode to 36.7 MB, then 35.7 MB and 35.7 MB +across a five-minute idle soak with about 23 MB live. RSS fell from 401 MB at +the first census to 132 MB at the last, and exactly one idle full was attributed to arena right-sizing. From 5271e6f0834674ed32c731eff98fb309ab69677b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Fri, 4 Sep 2026 08:58:37 +0000 Subject: [PATCH 3/5] docs(changelog): add PR 9704 fragment --- changelog.d/9704-fresh-instance-prototype-replacement.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changelog.d/9704-fresh-instance-prototype-replacement.md diff --git a/changelog.d/9704-fresh-instance-prototype-replacement.md b/changelog.d/9704-fresh-instance-prototype-replacement.md new file mode 100644 index 0000000000..ef841ede48 --- /dev/null +++ b/changelog.d/9704-fresh-instance-prototype-replacement.md @@ -0,0 +1,6 @@ +### Fixed + +- Fresh instances now observe class prototype methods replaced after class + registration. The method inliner keeps runtime dispatch for prototype chains + exposed or mutated anywhere in the module, including helper functions and + closures. (#9239) From ba340e23e0dc46dcacc5b46567023ae551b89bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Fri, 4 Sep 2026 13:58:33 +0000 Subject: [PATCH 4/5] docs(changelog): record shape descriptor pruning --- changelog.d/9733-uncarried-shape-descriptors.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 changelog.d/9733-uncarried-shape-descriptors.md diff --git a/changelog.d/9733-uncarried-shape-descriptors.md b/changelog.d/9733-uncarried-shape-descriptors.md new file mode 100644 index 0000000000..3f57ae5025 --- /dev/null +++ b/changelog.d/9733-uncarried-shape-descriptors.md @@ -0,0 +1,7 @@ +**Full collections now retire shape descriptors that no live object or +restamping cache owns.** A full trace records every shaped receiver, and a +synchronous sweep prunes only records absent from that complete census. +Minor and budgeted cycles remain conservative. Generated-module ids and +shape/transition caches retain exact ownership, while unstable transition +entries validate their target before stamping. In the claude-code census, +uncarried descriptors without an owner fell from 34,501 to zero. From 3e8b890ff8bff1c2923f14dcf96692095969130b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Fri, 4 Sep 2026 13:36:49 +0200 Subject: [PATCH 5/5] test(gap): pin the self-recursive shapes the old scan ordering served The reordered initializer scan is a superset, not a replacement: a self-recursive arrow, a named function expression, and a binding whose initializer both creates a closure over it and is called immediately all passed before this change and must keep passing. Verified identical on both arms of the same-commit A/B. --- test-files/test_gap_9718_initializer_self_binding.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test-files/test_gap_9718_initializer_self_binding.ts b/test-files/test_gap_9718_initializer_self_binding.ts index 0caa1e3b20..ce7661c6e9 100644 --- a/test-files/test_gap_9718_initializer_self_binding.ts +++ b/test-files/test_gap_9718_initializer_self_binding.ts @@ -69,6 +69,16 @@ async function main(): Promise { report("nested-await", () => pending[6]!()); report("earlier-refs-later", h); + // The shapes the pre-pass's original ordering existed for. They passed + // before this fix and must keep passing: moving the initializer scan earlier + // is a superset, not a replacement. + const fact = (n: number): number => (n <= 1 ? 1 : n * fact(n - 1)); + const fib = function rec(n: number): number { return n < 2 ? n : rec(n - 1) + rec(n - 2); }; + const off = renderSync(() => off.u() + "/init-call-result"); + console.log("self-recursive-arrow=" + fact(5)); + console.log("named-fn-expr-recursion=" + fib(10)); + report("init-call-result", () => pending[7]!()); + // The declaration is complete by the time these run, so the direct calls // must agree with what the closures saw. report("direct-plain", () => a.u());