Merge train 180: #10183 - #10195
Merged
Merged
Merge train 180: #10183#10195
Conversation
added 3 commits
September 13, 2026 11:56
…oss calls (#10166) A search per JavaScript call (an exec or test loop, matchAll's next(), search) bound its subject and program from scratch every time: binding a subject decodes the entire string and binding a program revalidates every word. A loop over one string therefore did O(n) binding work per call and O(n²) overall, and `.test()` paid a program validation per call. Perex 0.1.3 adds constant-work rebinding for what the host already validated: BoundSubject::new_counted(storage, utf16_len) and a ProgramWitness from BoundProgram::witness() that BoundProgram::new_witnessed checks against the program's length and header. Perry now keeps both, as plain data, with no allocation and nothing new traced: - Program: ProgramCell gains `witness: Option<ProgramWitness>` in its pointer-free prefix, beside the words it describes. The first validating bind records it; later binds use new_witnessed, falling back to validation (recording a fresh witness) if it does not match. A recompile emits a new cell that starts with none, so a witness can never describe other words. RegExpHeader stays 56 bytes. Debug builds assert no witness is written while a view of the cell's words is live. - Subject: StringHeader gains STRING_FLAG_WTF8_VALIDATED. Perry strings are not all valid WTF-8 (raw Buffer/FFI payloads reach regex operations), so nothing is assumed: the first bind decodes, and only if that succeeds and the decoded UTF-16 length equals the header's is the header marked; later binds use new_counted. A validated header is already shared, so its payload is never mutated in place. init_string_header strips the bit from every constructed string, and the in-place writers (js_string_append, js_string_append_chain) clear it, so it never reaches another string; concat's memo check ignores it. Deliberately excluded: a cross-call lastIndex position hint for non-ASCII exec loops. Recognising the same string across calls without a traced reference would need a heap generation counter bumped on every free and move path, and one missed path gives silent wrong answers. The remaining cost is one seek from the nearer end of the subject per call on non-ASCII subjects; it is charged but uncapped (#10176), so those loops finish, but are not linear. Tests: - string::tests_validated_flag: slice, substring, trim, concat, repeat, padStart, toUpperCase, join, string_copy_range and js_string_from_bytes_known_utf16 (passed the source's whole flags word) never inherit the bit; both in-place append paths clear it. - gc::tests::runtime_roots::perex_cross_call: a program cell records its witness on first bind and a recompiled program's new cell has none; a foreign equal-header witness (x(b) on x(a)) still answers with the cell's own words; a mismatched witness falls back and is replaced; a subject is marked only with an exact length, never with a corrupted utf16_len or malformed bytes; marks survive moving collections; a witness write under a live view is caught. - perex_reuse's accounting now expects one validation per program. Fault injection, each confirmed to fail its test: marking without the length check; never recording a witness; a mismatch without fallback; removing the view guard; keeping the whole flags word in init_string_header; keeping the bit in the in-place writers. Requires perex 0.1.3 (crates.io checksum 060b4682849d20ebcba05d68f9584a1bba20af4b7838c688cfb37af572f562f4), resolved once with CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow with the maintainer's approval; ordinary --locked builds use it without the override. Claude-Session: https://claude.ai/code/session_01Da12JXeG5XuVBma5yWp5C9
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (13)
📝 WalkthroughWalkthroughThe runtime now reuses validated RegExp programs and string subjects across calls. Program witnesses and string validation flags remain valid across moving GC. String mutations clear stale validation state. Tests cover rebinding, malformed input, reuse, and GC behavior. ChangesRegex cross-call binding
Estimated code review effort: 4 (Complex) | ~45 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant RegExpSearch
participant perex_api
participant GcProgram
participant RuntimeString
RegExpSearch->>perex_api: Bind program and subject
perex_api->>GcProgram: Reuse or record ProgramWitness
perex_api->>RuntimeString: Reuse or set validation flag
perex_api-->>RegExpSearch: Return bound program and subject
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Sep 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merge train 180: lands #10183 (bind a RegExp's program and subject in constant work across calls; #10166) at head
cf63ad155d, plus the workspace version bump to 0.5.1552.The two PR commits were cherry-picked onto
820cf76729(train 179) without conflicts and match bygit patch-id --stable. The validated tree was built on train 179's pre-landing head, which has the same tree as820cf76729. After re-parenting onto the landed commit, this branch's tree is byte-identical to the validated one (1d278c8b65).This lands perex 0.1.3, lock checksum
060b4682849d20ebcba05d68f9584a1bba20af4b7838c688cfb37af572f562f4. The publish-age override was approved for 0.1.2 and 0.1.3 only. It was not set in the validation environment; the version resolves from the lock.Local validation (perrymaster, Linux x86_64;
--locked, no publish-age override in the environment):cargo metadata --locked,cargo fmt --all -- --checkcargo check -p perry-runtime --no-default-features --features full --lib(regex feature off): 0 warningscargo check -p perry-runtime --lib --tests: no warnings outside the knownglobal_this_webassembly.rsdead code on maincargo test -p perry-runtime --lib -- --test-threads=1: 3709 passed, 1 failed. The failure isnative_stack::tests::stack_top_respects_custom_thread_stack_sizes, red on main.cargo clippy -p perry-runtime --lib --tests: the same 12approx_constanterrors as main, and no warnings added relative to train 179scripts/run_lint_gates.shscript tier: 76 of 77 pass. The failure is public benchmark evidence freshness, identical on main at5cec2fbbc9. The compile tier was not run.check_changeset_fragment.sh PerryTS/perry 10183: passBehavioural evidence is on #10183: the four fault injections (length check, witness never recorded, mismatch without fallback, view guard removed) each fail their tests. The measurements are there too. ASCII
exec/matchAll/testloops become linear, 40–60× faster at n = 40,000. Non-ASCII loops remain quadratic, which is the documented one-seek-per-call fallback. Short-string per-call instruction counts fall 2–4 %. GitHub runners are down, so this local replay is the gate. This completes the ordered set #10174, #10176, #10181, #10183.https://claude.ai/code/session_01Da12JXeG5XuVBma5yWp5C9
Summary by CodeRabbit
Performance
splitandreplaceoperations are less likely to hit work limits on linear inputs.Bug Fixes
Chores