Skip to content

Merge train 210: CommonJS preamble cost cut by a third, copy-slot-hoists doc (v0.5.1588) - #10413

Merged
proggeramlug merged 5 commits into
mainfrom
train210r
Sep 17, 2026
Merged

proggeramlug merged 5 commits into
mainfrom
train210r

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

This train lands #10349 and #10402 as v0.5.1588, on e6dcb6274d. Three source commits, each verified to preserve its patch-id and authorship.

  • perf(cjs): cut the per-module CommonJS preamble cost by a third #10349 — the CommonJS wrapper preamble is emitted into every wrapped module, so its fixed cost is paid once per module in the dependency graph. Four changes cut it by a third on a 400-module fixture: 598,533 → 397,896 instructions per module. Chief among them, one createRequire instance per program instead of one per module.
  • docs(gc): the copy-slot-hoists tests cover one hoist, not two (#10388) #10402 — corrects the copy_slot_hoists module doc. It claimed the copying minor hoists two facts per traced object; it hoists one. The old-generation fact is deliberately not hoisted, and the doc now records why: no sabotage of that hoist could be made to fail, because sticky dirty-page coverage carries an old→young edge independently of the remembered-set re-insertion the fact controls. A future hoist needs its own witness first.

Train repair

#10349's changelog fragment was keyed to the wrong PR. It shipped as changelog.d/10307-cjs-preamble-cost.md, but 10307-global-alias-member-read.md is already on main from the real #10307 (train 200). Different slug, so no collision — but fragments are PR-keyed so release notes trace back to the change, and two unrelated PRs sharing a 10307- prefix defeats that. Re-keyed to 10349-.

Validation

Validated head a9efe708d5. Five-package release build pinned and hash-verified, and re-verified after the gap run so nothing rebuilt underneath the fixtures.

  • Crate suites: codegen 1571, runtime 3984, stdlib 139, hir 433, transform 137, cli 1139 — all green except main's one known runtime failure (gc::tests::heap_generation::a_free_or_move_outside_every_scope_is_caught_in_debug_builds).
  • All nine preflight gates pass, including both raw-handle ratchet invocations, the holders gate, and the unrooted-local-shape check against main.
  • Gap: filters require, cjs, module, import, weak, builtin. cjs and builtin are clean — cjs being the most direct filter for perf(cjs): cut the per-module CommonJS preamble cost by a third #10349.

Every red attributed

Six fixtures were A/B'd against main's own artifact set, and all six behave identically on both arms (node=1, main=0, train=0) with distinct build stamps asserted per arm, so neither can have fallen through to the wrong archives: test_issue_1723_require_stdlib_subnamespace, test_issue_764_state_at_module_init, test_issue_915_native_module_after_async_resume, test_perry_gc_module, test_dynamic_import_data_10104, test_issue_2656_weakref_finalization_gc. Perry is correct on both arms; node is what fails.

These were re-attributed from scratch rather than carried over from the previous train's identical verdicts. #10349 rewrites the per-module preamble, so every compiled program differs — a verdict measured on binaries that predate it says nothing about these. That distinction has already cost a re-run once in this queue.

The two remaining reds need no A/B: test_require is listed verbatim in run_parity_tests.sh's SKIP_TESTS on main (crypto.randomUUID() differs), and test_ramda_user_import is an ext-archive link refusal of the pinned five-package set, which is symmetric and environmental.

Note that --filter is a substring match over all fixtures, so these runs select test_issue_*/test_perry_* names that CI's gap suite (--filter test_gap_) never runs. Every test_gap_* fixture in scope passed.

Before merging, the pushed head and unchanged main are checked again. After merging, the rewritten commits are checked for preserved authorship and the main tree must match the validated train exactly.

Summary by CodeRabbit

  • Performance

    • Improved CommonJS module loading efficiency, reducing fixed overhead for applications with many modules.
    • Reused shared module-loading resources across modules.
  • Bug Fixes

    • Corrected builtin-module detection for certain node:-only module names.
  • Maintenance

    • Updated the project version to 0.5.1588.
    • Updated validation coverage for the streamlined CommonJS module wrapper.

Ralph Küpper and others added 5 commits September 17, 2026 09:12
Rebased onto v0.5.1580, which carries the #10356 fix (an un-imported export
must not shadow a global intrinsic). That fix looks like a prerequisite: the
preamble's error helper constructs new Error(...), OpenCode's graph exports
Error from packages/core twice, so any path reaching that helper met a
shadowed intrinsic and threw 'undefined is not a constructor'.
isBuiltin alone is stricter than the switch it replaced: sea, sqlite, test and
test/reporters are builtins only in their node: form. OpenCode's graph contains
a bare require of one - wrangler does DatabaseSync = __require("sqlite").
DatabaseSync then new DatabaseSync(...), which became new undefined() and threw
'undefined is not a constructor' at startup.

Two native calls reproduce the switch's semantics exactly while still removing
the ~120 interned string constants it emitted into every module. Whether Perry
should accept the bare spellings is a genuine question, but it is a semantic
one and does not belong in a performance change.
The module header claimed the copying minor hoists two per-parent facts,
each with a sabotaged twin. Only the weak-holder fact landed; the
old-generation fact was deliberately left out because no sabotage of it
could be made to fail. Say so instead of claiming coverage the file does
not have.
The fragment shipped as `10307-cjs-preamble-cost.md`, but #10307 is a
different landed PR (`10307-global-alias-member-read.md`, train 200) and
fragments are PR-keyed so release notes trace back to the change. This
work is #10349.
@proggeramlug
proggeramlug merged commit d83e041 into main Sep 17, 2026
21 of 22 checks passed
@proggeramlug
proggeramlug deleted the train210r branch September 17, 2026 08:15
@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 31754257-ba57-466e-bb17-6d67ee71f55e

📥 Commits

Reviewing files that changed from the base of the PR and between e6dcb62 and a9efe70.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • CLAUDE.md
  • Cargo.toml
  • changelog.d/10349-cjs-preamble-cost.md
  • crates/perry-codegen/src/collectors/cjs_scaffolding.rs
  • crates/perry-runtime/src/gc/tests/copy_slot_hoists.rs
  • crates/perry/src/commands/compile/cjs_wrap/preamble_canary_tests.rs
  • crates/perry/src/commands/compile/cjs_wrap/tests.rs
  • crates/perry/src/commands/compile/cjs_wrap/wrap.rs

📝 Walkthrough

Walkthrough

Changes

CommonJS preamble optimization

Layer / File(s) Summary
Preamble generation and recognition
crates/perry/src/commands/compile/cjs_wrap/wrap.rs, crates/perry-codegen/src/collectors/cjs_scaffolding.rs
The wrapper reuses a program-wide createRequire, uses isBuiltin, builds the module record as one object literal, removes redundant allocations, and recognizes the folded template.
Validation and release records
crates/perry/src/commands/compile/cjs_wrap/*, crates/perry-runtime/src/gc/tests/copy_slot_hoists.rs, changelog.d/10349-cjs-preamble-cost.md, CLAUDE.md, Cargo.toml
Tests match the reduced preamble output. Documentation, changelog text, and version metadata were updated.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor

Suggested reviewers: jdalton

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch train210r

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant