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) 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. 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. 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)] 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());