merge train: land #10070, #10071, #10072, #10074, and #10081 - #10095
Merged
Conversation
added 12 commits
September 12, 2026 05:12
(cherry picked from commit 0b4f0f8)
(cherry picked from commit 3919bcf)
(cherry picked from commit 6b01d1c)
(cherry picked from commit 37dea1f)
(cherry picked from commit 3238919)
(cherry picked from commit ebab2bd)
(cherry picked from commit 11c7a85)
(cherry picked from commit c062d0d)
(cherry picked from commit 2eb66a8)
(cherry picked from commit 93a9b89)
The workspace version moved to 0.5.1536 with #10074's release-metadata commit, but Cargo.lock still pinned perry-native-registration at 0.5.1535. Regenerated the lock so the member's inherited version matches the workspace; no dependency resolution changed. Claude-Session: https://claude.ai/code/session_017grKysEP6NBPpCiTSBjSZR
The local `lint` tier failed two ratchets that the individual PRs did not run against post-#10064 `main`: raw-handle debt: 962 (baseline 945), 4 per-module violations string payload-access baseline stale (perry-runtime 352 -> 351) The debt is real, not a ceiling question. `--no-raise-vs <merge-base>` refuses a ceiling on a file that was absent at the base and refuses any per-module raise, so `concat_reverse.rs` (0 -> 5) and the new `wide_object_membership_tests.rs` (0 -> 9) could not be listed, and `iterator.rs` (31 -> 32) / `push_pop.rs` (12 -> 14) could not be raised. Converted all 17 sites to the shape the ratchet exists to enforce: - `array/concat_reverse.rs`: both `push(...src)` element loops now read the source inside `with_const_ptr`, so no address survives the `js_array_push_f64` that can move it. The grow path reads the source through `across_const` around a `with_mut_ptr` grow, which is where the post-allocation re-read belongs. - `array/iterator.rs` and `array/push_pop.rs`: `js_array_spread_append` and the generic spread-push take the destination from `across_mut` around the iterator materialization instead of reading it afterwards. - `object/wide_object_membership_tests.rs`: every probe re-reads the rooted receiver. The old shape bound `object.get_raw_mut_ptr()` once and then called `key()` — which allocates a string — repeatedly against that stale address. Debt is back to exactly the recorded 945 with every module inside its ceiling, so neither ratchet file needs an edit. The string payload-access baseline moves the other way: #10070's rewrite of `own_key_present` removed one open-coded `size_of::<StringHeader>()` offset in `object_ops/keys_array.rs`, and that inventory requires recorded progress. One line, 352 -> 351. Claude-Session: https://claude.ai/code/session_017grKysEP6NBPpCiTSBjSZR
|
Important Review skippedToo many files! This PR contains 750 files, which is 450 over the limit of 300. To get a review, reduce the PR to 300 files or fewer by splitting it into smaller PRs or changing its base branch. Usage-priced reviews support at most 300 files. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (847)
📒 Files selected for processing (750)
You can disable this status message by setting the |
This was referenced Sep 12, 2026
Closed
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 landing #10070, #10071, #10072, #10074 and #10081 on top of
mainc58c1fae5(train161).The individual PRs merge as their own branch, so GitHub's close keywords do not
fire — each original is closed with a pointer comment after this lands, and the
issues it names are swept by hand.
Composition
0b4f0f8e5,3919bcf1f6b01d1cdf,37dea1fbd323891948,ebab2bd5911c7a85c6,c062d0d7a2eb66a84a,93a9b898eAuthor commits are preserved (rebase-merge). #10074 was stacked on
already-landed JSON work:
b70652ee4,9bfc8f216,b90b0dfd6,45a29217c,cd87b5cf9,54a36eb3dand the #10050 batch below them are onmainalready(train161 for #10064, earlier trains for #10050/#10052), so only its own two
commits were taken. No cherry-pick conflicts; no shared commits between any
open pair in the queue.
Audit notes
#10074's diffstat is 1511 files / +134759 for a title about integer
remainder. Checked: the real change is 66 lines in
crates/perry-runtime/src/value/dynamic_arith.rsplus a 20-line gap test. Therest is the PR's own new
benchmarks/json_performance/INTEGER_REMAINDER_R32.mdand
results/integer-remainder-r32-*bundle — all 1505 paths are new, noneexists on
main, and the benchmark portion is purely additive (+134590/-0), soit is not overwriting or reverting an earlier report. The
js_dynamic_modfastpath was checked against the exceptional cases:
-0.0is excluded by theis_sign_negativeguard and keepsfmod;NaN,±inf,2^32and fractionaloperands all fail the
x as u32 as f64 == xround trip; a negative or zerodivisor saturates to
0and is rejected bydivisor != 0.#10070 removes the 65,536-key ceiling on own-key lookup by routing both
membership helpers through the pre-existing
keys_find_slot_by_key_ptr/shape_slot_lookup_verdict. The correctness contract is preserved:Foundis ahit,
Absentis authoritative only for a complete index(
indexed_len == key_count), andUnindexedstill falls through to the dense-slotlinear scan. The
wide_key_index_lookuppath it stopped using is still live fromget_field_by_name_tail.rs, so nothing became dead code.#10072 repoints codegen from
js_array_concattojs_array_spread_append.That symbol is pre-existing,
#[no_mangle] pub extern "C", notcfg-gated, andalready declared in
runtime_decls/arrays.rsas(I64, DOUBLE) -> I64, whichboth new call sites match.
#10081 adds a thread-local cache of 65 raw heap pointers
(
ARGUMENTS_KEYS). Per CLAUDE.md that is a GC root the static checker cannotsee. It is visited by the already-registered
scan_arguments_object_roots_mutand stored through
runtime_store_root_raw_mut_ptr_slot, so nogc_runtime_root_holders.jsonentry is required; arities above 64 build withoutcaching.
#10071 flips
GC_TYPE_BUFFERtopointer_free: falsewith a newGcRewriteDescriptorKind::Buffertracing the backing and ArrayBuffer-alias slotsout of side metadata. The flag change is conservative — its other consumer is the
write-barrier early-out, which now takes the barrier instead of skipping it — and
the payload keeps
GcLayoutSlotKind::None, so no byte range is scanned aspointers. The large-object threshold is explicitly pinned back for buffers.
Maintainer fix commits
Two, both from gates the individual PRs had not run against post-#10064
main:fix(runtime): keep train162 array spread reads in scoped custody— theraw-handle ratchet went 945 → 962 with 4 per-module violations. Ceilings
were not available:
--no-raise-vs <merge-base>refuses a ceiling on a fileabsent at the base (
wide_object_membership_tests.rs, 0 → 9) and refuses anyper-module raise (
concat_reverse.rs0 → 5,iterator.rs31 → 32,push_pop.rs12 → 14). All 17 sites were converted towith_const_ptr/with_mut_ptr/across_mut. One was a latent defect rather than style: thenew membership test bound
object.get_raw_mut_ptr()once and then called thestring-allocating
key()against that address repeatedly. Debt is back toexactly the recorded 945, every module inside its ceiling, and neither
ratchet file is edited. The same commit records the string payload-access
inventory's required progress — fix(object): remove wide-key cutoff and quadratic assign scans #10070's rewrite removed one open-coded
size_of::<StringHeader>()offset inobject_ops/keys_array.rs, 352 → 351.fix(release): synchronize native registration lock version— perf(runtime): speed up integer index remainder #10074'srelease-metadata commit moved the workspace to 0.5.1536 but
Cargo.lockstillpinned
perry-native-registration(aversion.workspace = truemember) at0.5.1535. One line.
Validation
Run from the train worktree with
CARGO_TARGET_DIRpinned.6363 tests, zero failures. Exit codes are captured from each command itself, not
from a pipeline.
The three lint failures are the known set and all three were attributed:
mainsince2026-07-29; regenerating the artifact is a multi-hour bench run and is
scoped out by tooling(lint): run_lint_gates.sh fails loudly when a lint step yields no command — it silently dropped the public-baseline step #9969.
an artifact of running under
CARGO_TARGET_DIR, becausescripts/regen_api_docs.shhardcodes$ROOT/target/release/perry. Re-runthrough the documented symlink, both pass with zero drift
(
regen_rc=0 drift_rc=0); the temporary symlink and directories were removedafterwards and the worktree is clean.
native_stack::tests::stack_top_respects_custom_thread_stack_sizes, which thecargo-testjob fails on this branch, fails identically onmainat thistrain's base and its module does not exist on macOS at all — it is a
platform-specific pre-existing failure, not a train regression. The
lint,gap-suite (3)andgap-suite (6)reds are likewise all present onmain's ownrun at the base commit.
Validated at head
810144bf228bb09fb8c86a696adc717d0e5feb84.https://claude.ai/code/session_017grKysEP6NBPpCiTSBjSZR
New gap tests
This train adds three
test_gap_*files, which none of the arms above cover, sothey were run directly against the pinned Node 26.5.1 (
.node-version, whichthis machine matches exactly):
The first attempt reported
test_gap_buffer_subarray_shared_storageas aCOMPILE_FAIL. That was the stale-archive trap from CLAUDE.md, not a defect:
PERRY_SKIP_BUILD=1reuseslibperry_{runtime,stdlib}.afrom the target pool,and those were still train161's (21:19 the previous evening) because
cargo build -p perrydoes not produce them — they come from theperry-runtime-static/perry-stdlib-staticwrappers. Rebuilt with-p perry -p perry-runtime-static -p perry-stdlib-static, confirmed the archivemtimes moved past the last commit, and all three pass.