size: gate keepalive anchors out of the classic link + opt-in size-optimized runtime rebuild (hello world 5.9→4.6 MB default, 2.3 MB size mode) - #6917
Conversation
… opt-level=z/s (cache-keyed)
…hors feature (bitcode-LTO only)
…-on; dropped in PERRY_SIZE_OPT rebuilds)
📝 WalkthroughWalkthroughThe PR adds environment-controlled size optimization and LTO settings, optional allocator selection, extra linker arguments, and feature-gated keepalive anchors across the runtime. Documentation, cache-key handling, allocator tests, and typed-feedback keepalive checks are updated. ChangesSize-optimized binary builds
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 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 |
|
Note on the red
|
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/perry-runtime/src/array/iter_methods.rs`:
- Around line 1044-1046: Qualify the keepalive-anchor comments at
crates/perry-runtime/src/array/iter_methods.rs:1044-1046 and
crates/perry-runtime/src/object/global_this/fetch_globals.rs:46-48 to state that
retention applies only when the keepalive-anchors feature is enabled for the
relevant link mode; remove wording implying survival across every link mode or
auto-optimized rebuild. No code changes are required.
In `@crates/perry-runtime/src/child_process/validate.rs`:
- Around line 91-95: Update the keepalive-anchor documentation near
project_auto_optimize_keepalive_3320 to state that the anchors are required only
for bitcode-LTO linking when PERRY_LLVM_BITCODE_LINK=1. Remove or revise the
claim that the default perry file.ts -o out link fails without them, while
preserving the explanation that generated object files reference the
#[no_mangle] entry points.
In `@crates/perry-runtime/src/promise/rejection.rs`:
- Around line 253-257: Update the comment above the keepalive anchor attribute
to scope the internalize/dead-strip failure specifically to bitcode-LTO builds.
Remove the claim that every native link fails, and preserve the documented
behavior that classic-link auto-optimized builds intentionally disable these
anchors while remaining valid.
In `@crates/perry-runtime/src/value/dyn_index.rs`:
- Around line 594-598: Align the keepalive comments with the feature and
link-mode contract: in crates/perry-runtime/src/value/dyn_index.rs lines
594-598, remove the claim that retention is guaranteed regardless of feature set
or link mode; in crates/perry-runtime/src/fs/validate.rs lines 372-377, limit
the failure claim to bitcode-LTO when the feature is disabled; in
crates/perry-runtime/src/gc/barrier.rs lines 1517-1522, remove the claim that
exports survive every link mode; and in crates/perry-runtime/src/url/abort.rs
lines 638-645, clarify that disabling keepalive anchors does not universally
make exports disappear. Do not change the #[cfg_attr(..., used)] implementation.
In `@crates/perry/src/commands/compile/link/build_and_run.rs`:
- Around line 1853-1861: Include PERRY_EXTRA_LINK_ARGS in the link-cache
decision by moving its environment-variable parsing and argument application
before prepare_link_cache_status(...), or otherwise invalidate the cache
whenever it is set. Ensure cache hits cannot bypass changes to these extra
linker arguments, while preserving their verbatim ordering in the final link
command.
In `@crates/perry/src/commands/compile/optimized_libs/driver.rs`:
- Around line 779-798: Propagate the size optimization and fat-LTO settings
configured in the main compile flow to the later emit_bc commands used when
PERRY_LLVM_BITCODE_LINK=1. Update the emit_bc RUSTFLAGS/environment construction
to include the value from size_opt_level() and the CARGO_PROFILE_RELEASE_LTO
override from size_lto_fat(), or explicitly reject this combination before
starting the bitcode build.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: c40c9a27-2008-4e7e-8f1c-1d490c621d5a
📒 Files selected for processing (93)
changelog.d/6917-size-optimized-binaries.mdcrates/perry-runtime/Cargo.tomlcrates/perry-runtime/src/array/from_concat.rscrates/perry-runtime/src/array/generic.rscrates/perry-runtime/src/array/header.rscrates/perry-runtime/src/array/indexing.rscrates/perry-runtime/src/array/iter_methods.rscrates/perry-runtime/src/array/push_pop.rscrates/perry-runtime/src/array/sort.rscrates/perry-runtime/src/bigint/convert.rscrates/perry-runtime/src/box.rscrates/perry-runtime/src/buffer/access.rscrates/perry-runtime/src/buffer/dataview.rscrates/perry-runtime/src/buffer/encode.rscrates/perry-runtime/src/buffer/query.rscrates/perry-runtime/src/buffer/u8_codec.rscrates/perry-runtime/src/builtins/arithmetic.rscrates/perry-runtime/src/child_process/validate.rscrates/perry-runtime/src/closure/alloc.rscrates/perry-runtime/src/closure/dispatch/bound.rscrates/perry-runtime/src/closure/registry.rscrates/perry-runtime/src/closure/unbox.rscrates/perry-runtime/src/collection_iter_object.rscrates/perry-runtime/src/date.rscrates/perry-runtime/src/disposable.rscrates/perry-runtime/src/embedded.rscrates/perry-runtime/src/error.rscrates/perry-runtime/src/event_target.rscrates/perry-runtime/src/fs/validate.rscrates/perry-runtime/src/gc/barrier.rscrates/perry-runtime/src/gc/mod.rscrates/perry-runtime/src/gc/tests/os_tag.rscrates/perry-runtime/src/iterator_helpers.rscrates/perry-runtime/src/json/parse_api.rscrates/perry-runtime/src/json/raw_json.rscrates/perry-runtime/src/lib.rscrates/perry-runtime/src/map.rscrates/perry-runtime/src/module_require.rscrates/perry-runtime/src/native_abi.rscrates/perry-runtime/src/node_sea.rscrates/perry-runtime/src/node_stream_keepalive.rscrates/perry-runtime/src/node_submodules/zlib.rscrates/perry-runtime/src/node_v8.rscrates/perry-runtime/src/object/alloc.rscrates/perry-runtime/src/object/class_constructors.rscrates/perry-runtime/src/object/class_registry/registration.rscrates/perry-runtime/src/object/descriptors.rscrates/perry-runtime/src/object/global_this/builtin_thunks.rscrates/perry-runtime/src/object/global_this/fetch_globals.rscrates/perry-runtime/src/object/groupby.rscrates/perry-runtime/src/object/native_module.rscrates/perry-runtime/src/object/native_this_alias.rscrates/perry-runtime/src/object/object_ops/has_own.rscrates/perry-runtime/src/object/this_binding.rscrates/perry-runtime/src/object/with_env.rscrates/perry-runtime/src/os.rscrates/perry-runtime/src/path.rscrates/perry-runtime/src/process/env_misc.rscrates/perry-runtime/src/promise/async_step.rscrates/perry-runtime/src/promise/combinators.rscrates/perry-runtime/src/promise/microtasks.rscrates/perry-runtime/src/promise/mod.rscrates/perry-runtime/src/promise/rejection.rscrates/perry-runtime/src/proxy.rscrates/perry-runtime/src/proxy/put_value.rscrates/perry-runtime/src/regex/escape.rscrates/perry-runtime/src/set.rscrates/perry-runtime/src/string/locale.rscrates/perry-runtime/src/string/pad.rscrates/perry-runtime/src/string/raw.rscrates/perry-runtime/src/string/slice_ops.rscrates/perry-runtime/src/symbol/constructors.rscrates/perry-runtime/src/symbol/iterator.rscrates/perry-runtime/src/text.rscrates/perry-runtime/src/tls.rscrates/perry-runtime/src/typed_feedback.rscrates/perry-runtime/src/typed_feedback/guards.rscrates/perry-runtime/src/typed_feedback/tests.rscrates/perry-runtime/src/typed_feedback/trace.rscrates/perry-runtime/src/typedarray/access.rscrates/perry-runtime/src/typedarray_props.rscrates/perry-runtime/src/url/abort.rscrates/perry-runtime/src/url/search_params.rscrates/perry-runtime/src/validators.rscrates/perry-runtime/src/value/dyn_index.rscrates/perry-runtime/src/value/dynamic_arith.rscrates/perry-runtime/src/value/nanbox.rscrates/perry-runtime/src/yoga.rscrates/perry/src/commands/compile/link/build_and_run.rscrates/perry/src/commands/compile/optimized_libs.rscrates/perry/src/commands/compile/optimized_libs/driver.rscrates/perry/src/commands/compile/optimized_libs/freshness.rsdocs/src/cli/flags.md
| // `undefined _js_array_join_value`. The `#[cfg_attr(feature = "keepalive-anchors", used)]` static pins the symbol so it | ||
| // survives every link mode. Same pattern as `node_stream_keepalive.rs`. | ||
| #[used] | ||
| #[cfg_attr(feature = "keepalive-anchors", used)] |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Qualify the keepalive-anchor comments.
#[cfg_attr(feature = "keepalive-anchors", used)] only applies #[used] when the feature is enabled, so these comments should distinguish feature-enabled bitcode-LTO retention from classic-link builds where the anchors are intentionally omitted.
crates/perry-runtime/src/array/iter_methods.rs#L1044-L1046: replace “survives every link mode” with wording that scopes retention to the enabled feature/build mode.crates/perry-runtime/src/object/global_this/fetch_globals.rs#L46-L48: clarify that the anchor is required only for the link mode that enableskeepalive-anchors, not every auto-optimized rebuild.
📍 Affects 2 files
crates/perry-runtime/src/array/iter_methods.rs#L1044-L1046(this comment)crates/perry-runtime/src/object/global_this/fetch_globals.rs#L46-L48
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/perry-runtime/src/array/iter_methods.rs` around lines 1044 - 1046,
Qualify the keepalive-anchor comments at
crates/perry-runtime/src/array/iter_methods.rs:1044-1046 and
crates/perry-runtime/src/object/global_this/fetch_globals.rs:46-48 to state that
retention applies only when the keepalive-anchors feature is enabled for the
relevant link mode; remove wording implying survival across every link mode or
auto-optimized rebuild. No code changes are required.
| // The `#[cfg_attr(feature = "keepalive-anchors", used)]` statics below take the address of each export, creating a | ||
| // retained reference edge that LTO and the linker's `-dead_strip` must | ||
| // honor (the entries land in `@llvm.used` / a `no_dead_strip` section). This | ||
| // guarantees the symbols survive auto-optimize regardless of feature set or | ||
| // link mode. Function-pointer types are `Sync`, so no wrapper is needed. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Align keepalive comments with the feature/link-mode contract.
The #[cfg_attr(..., used)] implementation is correct, but these comments imply unconditional retention or failure in every link mode. The anchors are intentionally omitted when the feature is disabled; classic linking relies on undefined references, while bitcode-LTO requires the feature-enabled anchors.
crates/perry-runtime/src/value/dyn_index.rs#L594-L598: remove “regardless of feature set or link mode.”crates/perry-runtime/src/fs/validate.rs#L372-L377: restrict the failure claim to bitcode-LTO without the feature.crates/perry-runtime/src/gc/barrier.rs#L1517-L1522: remove “survive every link mode.”crates/perry-runtime/src/url/abort.rs#L638-L645: clarify that disabling the feature does not universally make the exports disappear.
📍 Affects 4 files
crates/perry-runtime/src/value/dyn_index.rs#L594-L598(this comment)crates/perry-runtime/src/fs/validate.rs#L372-L377crates/perry-runtime/src/gc/barrier.rs#L1517-L1522crates/perry-runtime/src/url/abort.rs#L638-L645
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/perry-runtime/src/value/dyn_index.rs` around lines 594 - 598, Align
the keepalive comments with the feature and link-mode contract: in
crates/perry-runtime/src/value/dyn_index.rs lines 594-598, remove the claim that
retention is guaranteed regardless of feature set or link mode; in
crates/perry-runtime/src/fs/validate.rs lines 372-377, limit the failure claim
to bitcode-LTO when the feature is disabled; in
crates/perry-runtime/src/gc/barrier.rs lines 1517-1522, remove the claim that
exports survive every link mode; and in crates/perry-runtime/src/url/abort.rs
lines 638-645, clarify that disabling keepalive anchors does not universally
make exports disappear. Do not change the #[cfg_attr(..., used)] implementation.
| // PERRY_EXTRA_LINK_ARGS — space-separated args appended verbatim to the | ||
| // final link invocation. Diagnostic escape hatch (e.g. | ||
| // `-Wl,-why_live,_js_fs_open` to ask ld64 why a symbol survived | ||
| // dead-strip); not part of any documented stable surface. | ||
| if let Ok(extra) = std::env::var("PERRY_EXTRA_LINK_ARGS") { | ||
| for a in extra.split_whitespace() { | ||
| cmd.arg(a); | ||
| } | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Include PERRY_EXTRA_LINK_ARGS in the link-cache identity.
prepare_link_cache_status(...) runs before this block, and cache hits return before the environment variable is read. Changing PERRY_EXTRA_LINK_ARGS can therefore reuse an old executable without relinking. Apply these arguments before cache preparation, or force a cache miss whenever the variable is set.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/perry/src/commands/compile/link/build_and_run.rs` around lines 1853 -
1861, Include PERRY_EXTRA_LINK_ARGS in the link-cache decision by moving its
environment-variable parsing and argument application before
prepare_link_cache_status(...), or otherwise invalidate the cache whenever it is
set. Ensure cache hits cannot bypass changes to these extra linker arguments,
while preserving their verbatim ordering in the final link command.
| // PERRY_SIZE_OPT=z|s — rebuild the auto-optimized runtime/stdlib at | ||
| // `-C opt-level=z`/`s` instead of the profile's `3`. RUSTFLAGS is | ||
| // appended after cargo's profile-derived flags, and rustc takes the | ||
| // last `-C opt-level`, so this cleanly overrides the per-package | ||
| // `opt-level = 3` without a custom profile. Trades some runtime speed | ||
| // for a substantially smaller binary; keyed into the auto-opt cache | ||
| // dir hash (see `auto_optimized_cache_key`) so size-optimized and | ||
| // speed-optimized archives never serve each other's builds. | ||
| if let Some(level) = size_opt_level() { | ||
| rustflags.push(format!("-C opt-level={level}")); | ||
| } | ||
| // PERRY_SIZE_LTO=fat — whole-archive fat LTO on top of the size opt | ||
| // level. Must go through cargo's profile override (env form) rather | ||
| // than RUSTFLAGS: `-C lto` in RUSTFLAGS reaches every rlib dep too, | ||
| // and rustc rejects `-C lto` for rlib crate types. The env override | ||
| // lets cargo do it properly (deps keep embedding bitcode, only the | ||
| // leaf staticlib runs the fat-LTO pass). | ||
| if size_lto_fat() { | ||
| cargo_cmd.env("CARGO_PROFILE_RELEASE_LTO", "fat"); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Propagate size settings to the bitcode-emission build.
When PERRY_LLVM_BITCODE_LINK=1, the later emit_bc commands at Lines 961-995 use a new RUSTFLAGS value that omits -C opt-level=z|s and the LTO override. The final bitcode-based link can therefore fall back to normal release optimization and lose the advertised size-mode reduction. Share these settings with emit_bc, or explicitly reject this combination.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/perry/src/commands/compile/optimized_libs/driver.rs` around lines 779
- 798, Propagate the size optimization and fat-LTO settings configured in the
main compile flow to the later emit_bc commands used when
PERRY_LLVM_BITCODE_LINK=1. Update the emit_bc RUSTFLAGS/environment construction
to include the value from size_opt_level() and the CARGO_PROFILE_RELEASE_LTO
override from size_lto_fat(), or explicitly reject this combination before
starting the bitcode build.
…ifies heap bands — silent output loss); key PERRY_EXTRA_LINK_ARGS into link cache; mirror size opt-level into bitcode emission; correct anchor comments
|
Both CodeRabbit majors are addressed in 35540de:
The four flagged anchor comments are reworded to state the actual contract (anchors are for the bitcode-LTO link; the classic link keeps symbols via the program's own undefined references). One additional fix folded into the same commit, found by extending verification to a heavier program: the earlier revision dropped mimalloc in size-mode rebuilds, and those binaries were silently broken — |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/src/cli/flags.md (1)
121-136: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winDocument
PERRY_EXTRA_LINK_ARGSin the CLI reference.The PR introduces this user-facing environment variable, but the new section and environment-variable table omit it. Add its verbatim-pass-through behavior and diagnostic example so users can discover it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/src/cli/flags.md` around lines 121 - 136, Update the CLI reference’s environment-variable documentation to include PERRY_EXTRA_LINK_ARGS, describing that its contents are passed verbatim to the linker and adding a diagnostic usage example. Place it alongside the other user-facing build/link configuration variables and preserve the existing documentation style.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@docs/src/cli/flags.md`:
- Around line 121-136: Update the CLI reference’s environment-variable
documentation to include PERRY_EXTRA_LINK_ARGS, describing that its contents are
passed verbatim to the linker and adding a diagnostic usage example. Place it
alongside the other user-facing build/link configuration variables and preserve
the existing documentation style.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f85f7685-8505-4ba2-95b2-91517fc29936
📒 Files selected for processing (9)
changelog.d/6917-size-optimized-binaries.mdcrates/perry-runtime/src/array/iter_methods.rscrates/perry-runtime/src/child_process/validate.rscrates/perry-runtime/src/promise/rejection.rscrates/perry-runtime/src/value/dyn_index.rscrates/perry/src/commands/compile/link/link_cache.rscrates/perry/src/commands/compile/optimized_libs/driver.rscrates/perry/src/commands/compile/optimized_libs/freshness.rsdocs/src/cli/flags.md
🚧 Files skipped from review as they are similar to previous changes (5)
- crates/perry-runtime/src/value/dyn_index.rs
- crates/perry/src/commands/compile/optimized_libs/driver.rs
- crates/perry-runtime/src/child_process/validate.rs
- crates/perry-runtime/src/array/iter_methods.rs
- crates/perry-runtime/src/promise/rejection.rs
#8338) #6917 gated the ~490 #[used] keep-alive anchor statics behind the keepalive-anchors feature and only enabled it for the bitcode-LTO path (PERRY_LLVM_BITCODE_LINK=1). The assumption was that the classic link path "keeps every reachable runtime symbol via real undefined references from the program's objects." That assumption is wrong: #[no_mangle] pub extern "C" fn symbols that are only called from codegen (not from within the perry-runtime crate itself) are dead-code-eliminated by rustc during staticlib archive creation when no #[used] anchor pins them. The resulting libperry_runtime.a is missing core symbols — js_box_release, js_bool_box_release, js_closure_set_box_capture_ptr, js_link_path_module_parent — and programs whose codegen emits calls to them fail to link with "Undefined symbols for architecture arm64." This blocks sdxgen and any program whose codegen references these codegen-only entry points. Fix: always include perry-runtime/keepalive-anchors in the auto-optimize cross-feature set (not just when PERRY_LLVM_BITCODE_LINK=1). In a staticlib archive the linker only pulls in object files that resolve an undefined reference, so #[used] anchors only become -dead_strip roots when their object file is pulled in — the size cost is limited to the transitive callees of symbols the program actually uses, not the entire runtime surface. Also update the cache key's anchors field to always true (was PERRY_LLVM_BITCODE_LINK == "1") so old incomplete archives get new hash dirs and are never reused.
Summary
Binary-size campaign for small programs. A
console.loghello world on macOS arm64:PERRY_SIZE_OPT=zPERRY_SIZE_OPT=z PERRY_SIZE_LTO=fatStartup is unchanged (5.6 ms vs 5.5 ms, hyperfine).
The free win: gate the
#[used]keepalive anchorsThe ~490
#[used] static KEEP_*fn-pointer anchors in perry-runtime exist for the whole-program bitcode-LTO link (PERRY_LLVM_BITCODE_LINK=1), where the merged module could internalize + drop symbols only referenced from the user's separate.o. The classic link never needs them — every reachable runtime symbol is kept by a real undefined reference from the program's objects — but they unconditionally defeat-dead_strip.Post-#5256-devirt they had become the main retainer.
ld64 -why_liveon a hello world shows one chain pinning the entire node-module surface:All 487 anchors (the ohos
.init_arrayctor is untouched) are now#[cfg_attr(feature = "keepalive-anchors", used)]behind a new default-onkeepalive-anchorsfeature.cargo build/cargo test/prebuilt archives are unchanged (feature is indefault, andcfg_attr(feature-on, used)expands to exactly the old attribute). The auto-optimize rebuild omits the feature; requesting the bitcode link re-adds it. The source-audit test asserting the anchors' attribute form is updated for the gated spelling.Opt-in size mode
PERRY_SIZE_OPT=z|s— rebuild the auto-optimized runtime/stdlib at-C opt-level=z/s(RUSTFLAGS appended after cargo's profile flags, so it overrides the per-packageopt-level = 3).PERRY_SIZE_LTO=fat— whole-archive fat LTO on top, viaCARGO_PROFILE_RELEASE_LTO=faton the cargo invocation (RUSTFLAGS-C ltowould reach rlib deps and fail).alloc-mimallocfeature, force-added by EVERY auto-optimize rebuild (size mode included) — so nothing changes at runtime. An earlier revision dropped it in size mode for ~140 KB; that shipped silently-broken binaries:value/addr_class.rsaccepts heap addresses only in [2 TB, 128 TB), which encodes mimalloc's macOS mapping range, so system-malloc allocations are misclassified as non-pointers (no console output, spurious TypeErrors). The gate stays for a future audited system-allocator option. The macOS tools attribute Perry's heap to IOAccelerator (GPU) — mimalloc VM tag 100 collision #6882 VM-tag retag and its test ride the same cfg.Both knobs (plus the bitcode-anchors state) are keyed into the auto-opt cache dir hash so size-optimized and normal archives never serve each other's builds.
Also adds
PERRY_EXTRA_LINK_ARGS— a verbatim extra-link-args passthrough (diagnostic escape hatch; it's how the-why_livechains above were captured).Verification
import()of builtins,createRequire,process.getBuiltinModule, fs sync + promises,stream.Readable,child_process.execSync, unknown-importERR_MODULE_NOT_FOUNDrejection): byte-identical to Node on the anchor-less runtime.console.timewall-clock, Node deprecation warning on stderr, known Concurrency race: Next.js byte-stream pull runs before Flight state is ready (null.byteLength) #6477 tee tick cadence).cargo test -p perry --bin perry: 751 passed.cargo test -p perry-runtime --lib: 1471 passed; the 2 observed failures (gc::teardown::map_set_side_allocations_release_on_thread_exit,object::prop_plan::vtable_generation_bump_invalidates) are parallel-execution flakes that pass single-threaded and are feature-identical to main under default features.cargo fmt --all -- --checkclean.Remaining size floor (documented for follow-ups)
At 2.4 MB the map shows the next levers: Intl (219 KB, pinned via
toLocaleString/localeCompareproto thunks), node:stream (172 KB, pinned via the event pump's pipeline settling), node:fs (161 KB, pinned via microtask pump → diagnostics_channel → cross-thread FileHandle deserialize), URL/Buffer/submodules via eagerglobalThispopulation, and the std backtrace symbolizer (nightly-Zbuild-stdterritory). Hook-decoupling those (the existingjs_nm_enable_install_allarmed-pointer pattern) is the natural follow-up series.Summary by CodeRabbit
PERRY_SIZE_OPT(z/s) and optionalPERRY_SIZE_LTO=fatfor whole-archive fat LTO.PERRY_EXTRA_LINK_ARGSto append custom linker arguments for diagnostics.