Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8e55220
fix(trace_events): align descriptors and empty filters
Sep 6, 2026
72d33ee
chore: number changeset for PR 9884
Sep 6, 2026
fe6d5fb
fix(perf_hooks): separate default export namespace
Sep 6, 2026
bf6b756
chore: number changeset for PR 9885
Sep 6, 2026
d01e3e2
fix(hir): a later class accessor replaces an earlier one
Sep 6, 2026
dc25c64
fix(fs): preserve promises namespace identity
Sep 6, 2026
2e7fce7
chore: number changeset for PR 9887
Sep 6, 2026
1e15ad4
feat(codegen): match the Intl.Segmenter for-of, and count whether it …
Sep 6, 2026
b8b241d
style: cargo fmt the segment-view matcher and its tests
Sep 6, 2026
c3c8397
docs(changelog): add the segment-view matcher fragment
Sep 6, 2026
e038b88
docs: point the segment-view references at the issue that exists (#9843)
Sep 6, 2026
217cb97
fix(codegen): classify the folded StringCodePointAt node as a segment…
Sep 6, 2026
c9d846f
feat(codegen): lower a proven segment for-of to the runtime view mode…
Sep 6, 2026
06c1c36
diag(codegen): make the lowering report which entry point each site w…
Sep 6, 2026
d2e7842
feat(codegen): v2 — answer the segment's uses from the view, material…
Sep 6, 2026
11d71f7
fix(codegen): declare the segment-view runtime entry points
Sep 6, 2026
7a14f7e
fix(codegen): answer a statically-known RegExpTest from the view too
Sep 6, 2026
3898565
style: cargo fmt
Sep 6, 2026
98584ee
fix(train): split class_decl's member helpers out for the file cap
Sep 6, 2026
ac014d1
fix(train): drop the unused computed_member_name re-import
Sep 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions changelog.d/9843-segment-view-for-of-matcher.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
Compile-time matcher for the `Intl.Segmenter` `for…of` loop, with the counter
that decides whether it fires.

`for (let {segment: O} of X.segment(q))` is where claude-code spends most of a
turn: the allocation census ranks it 1/2/3 by count (172,032 segment records
plus 247,808 substrings per 400-character reply, 58 % of the top-30 allocation
count), and a `sample` puts 60–85 % of active main-thread CPU inside it, under
ink's `wrapText`. The loop reads one code point per grapheme and retains
nothing.

`collectors/segview.rs` joins `escape_news` / `escape_arrays` /
`escape_objects` as the family's fourth member. It proves one thing: the
segment RECORD never escapes, because every use of the synthetic
`__destruct_N` binding is one of the destructuring field reads the loop head
itself emits. Uses of the segment STRING are classified and counted but never
gate the proof — a use no view entry point can answer is served by
materialising the substring once, which is what the loop costs today.

The escape proof is taken with `perry_hir::collect_local_refs_stmt`, whose
descent bottoms out in the walker the compiler forces to be exhaustive, so a
new HIR variant embedding a `LocalGet` cannot silently hide a use of the
record.

No lowering yet: the fact is populated and unread until the runtime's
segment-view entry points exist. `PERRY_SEGVIEW_DIAG=1` reports every site
examined, its verdict and its per-use tally at the HIR-trace point, and is
excluded from the build-level cache so a report of zero is a measured zero
rather than a build that never lowered HIR.
1 change: 1 addition & 0 deletions changelog.d/9884-trace-events-descriptors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Aligned `node:trace_events` export descriptors and empty category filtering with Node.
3 changes: 3 additions & 0 deletions changelog.d/9885-perf-hooks-default-export-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Fixed

- Match Node's `node:perf_hooks` default-import keys while preserving namespace `default` and shared export identity.
3 changes: 3 additions & 0 deletions changelog.d/9887-fs-promises-namespace-identity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Fixed

- Reuse the canonical `fs/promises` and `stream/promises` namespace objects when their native-module references become values.
16 changes: 16 additions & 0 deletions crates/perry-codegen/src/collectors/hir_facts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ pub(crate) struct EscapeFacts {
pub fusible_uppercase_locals: HashSet<u32>,
pub non_escaping_object_literals: HashMap<u32, Vec<String>>,
pub non_escaping_object_literal_used_fields: HashMap<u32, HashSet<String>>,
/// #9843, the fourth member of this family: `for (let {segment: O} of
/// X.segment(q))` sites whose segment RECORD provably never escapes, so
/// the loop can drive a native cursor instead of materialising one record
/// per grapheme (census site 1 — 172,032 allocations per 400-character cc
/// reply, the largest single site by count).
///
/// Populated but not yet consumed: the lowering waits on the runtime's
/// view-mode entry points (`INTERFACE_segments_view.md` §9b). Same
/// in-progress shape as `PurityFacts` / `ShapeStabilityFacts` above.
#[allow(dead_code)]
pub segment_for_of_sites: Vec<super::segview::SegmentForOfSite>,
}

#[derive(Debug, Clone, Default)]
Expand Down Expand Up @@ -677,6 +688,10 @@ pub(crate) fn collect_type_facts(
stmts,
&non_escaping_object_literals,
);
// #9843: the segment-record member of the escape family. Cheap by
// construction — `collect_segment_for_of_sites` walks the region only
// when it holds a `for…of` whose subject is an `X.segment(q)` call.
let segment_for_of_sites = super::segview::collect_segment_for_of_sites(stmts);
let scalar_replaceable_object_locals = non_escaping_news
.keys()
.chain(non_escaping_object_literals.keys())
Expand Down Expand Up @@ -773,6 +788,7 @@ pub(crate) fn collect_type_facts(
fusible_uppercase_locals,
non_escaping_object_literals,
non_escaping_object_literal_used_fields,
segment_for_of_sites,
},
purity: PurityFacts {
pure_helper_function_ids: clamp_fn_ids.clone(),
Expand Down
3 changes: 3 additions & 0 deletions crates/perry-codegen/src/collectors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ mod repsel_benefit;
mod safepoint_sites;
mod scalar_method_dispatch;
mod scalar_methods;
pub mod segview;
#[cfg(test)]
mod segview_tests;
mod shadow_slots;
pub(crate) mod spec_abi_sites;
mod this_as_value;
Expand Down
Loading
Loading