Skip to content

perf: this is a parameter of every JS body; the implicit-this cell is gone (perry-ffi 0.6 typed bodies) - #11637

Merged
proggeramlug merged 22 commits into
mainfrom
perf-this-as-parameter
Sep 29, 2026
Merged

proggeramlug merged 22 commits into
mainfrom
perf-this-as-parameter

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

What

this becomes an ordinary parameter of every JS function body: double body(i64 callee, i64 this, double args...). Previously it went through a per-thread "implicit this" cell. Every method call saved the cell, wrote the receiver into it, called, and restored it, with the saved value held as a GC root across the call. That cell, its save/restore traffic and its root are gone.

Commits (reviewable one stage at a time):

Stage What it does
0 One funnel per side for every call of a JS body (runtime closure/body_call.rs, codegen expr/body_call.rs), plus the gate check_js_body_call_funnel.py, so no call site bypasses it. Flat on tsc and Zod.
1 Every body takes the receiver as a parameter and every caller passes it. Bodies still read the cell, so behavior is unchanged. A witness build checked parameter == cell at every body entry: 0 mismatches across 54,707 gap-suite checks and 13,164 on tsc.
1b perry-ffi 0.6: a single typed body ABI (JsBody), and the native→JS call entries take a receiver. An addon function with the wrong signature is now a compile error on every platform, instead of silently mis-reading its arguments on Win64. Pre-1.0, so there are no compatibility shims, and every in-tree ext crate is updated.
2 Bodies read their receiver parameter.
3 The implicit-this cell and every write and restore of it are deleted.

A merge commit brings in main (#11565's generated GC call-effects table, regenerated with scripts/gc_call_effects/regen.sh), plus two follow-ups: a file-size split of child_process/reactor.rs, and one codegen test updated to the new wrapper ABI.

Evidence

tsc and Zod, measured on a 48-thread EPYC host, n=5 interleaved, instructions:u, each arm linking its own runtime, output identical to node on every run:

Workload main this PR Δ
tsc 101.71–101.88G 97.89–98.28G −3.6% (build-to-build noise ±2.7%)
Zod −0.3%

Call fixtures (instructions per call):

Fixture main this PR
p7 (closure call) 145 46
p7b 160 59
p1 223 120
p3 214 110
p0 99 79

Tests:

  • Suites on the final tree, both arms at the same base: runtime 4698/0 on both; codegen 1786/1 on both (the failure is on main too). The ext crates, stdlib and perry-ffi pass. On the merged tree: runtime 4706/0, this_param_abi 2/2, method_site 9/9.
  • Gap suite: 1060 vs 1061. The one change is test_gap_6287_timer_batch_order, which also flips on main under load (3 different orders in 5 runs).
  • Sabotage: 6/6 mutations go red: the method site passes undefined, the funnel passes undefined, witness emission off, a wrapper with the old signature, and two for stage 3.
  • gc-root-dominance: findings identical to base.
  • Checks: the all-features check of runtime, stdlib, codegen and ffi is clean, fmt is clean, and the lint gates show the same environmental failures as main.

GC call-effects tables: the Linux table was regenerated locally. The macOS and Windows tables will be refreshed from this PR's gc-call-effects CI artifacts.

Follow-up (separate PR, in progress)

The function-pointer-keyed closure body registry (arity, rest, arrow, trusted clones) becomes one static immutable JsFunctionInfo per body, pointed to by the function object. That deletes three thread-local tables, about 50 registration entry points and their call sites.

Ralph Küpper added 9 commits September 28, 2026 02:21
…his-as-a-parameter, stage 0)

No behaviour change. Every place that turns a function body's code pointer
into a call now goes through one funnel, so the body ABI can change (stage 1:
the receiver becomes a parameter) in one place, with the compiler finding
every caller.

Runtime: `closure/body_call.rs` owns the body types and the only transmutes to
them: `js_body_fn_ty!` / `js_body_fn!` / `js_body_call!` /
`js_body_call_unwind!` for closure-ABI bodies `(callee, a0..)`,
`js_method_body_fn!` / `js_method_body_call!` for class method, constructor and
accessor bodies `(this, a0..)`, and `js_bare_body_fn!` for static methods,
static accessors and the lifted well-known hooks `(a0..)`. Routed through it:
the 17 direct arms of `js_closure_call0..16`, `dispatch_with_arity` (33 arms),
`dispatch_rest_bundled` (16 arms, now one macro), the wide ladder,
`DirectCall1..4`, the captureless `some` callback, the async-step microtask,
five `thread.rs` workers, 31 class accessor / static / hook calls, and the
`then(this, ..)` thenable call. The 57 typed native-body type positions
(install helpers, erasure casts) use `js_body_fn_ty!`. Production
(`panic = "abort"`) signatures are unchanged; in unwinding test builds rest
arms 1-6 now use the unwind-capable pointer type arms 0 and 7-15 already used.

Codegen: `expr/body_call.rs::emit_js_body_call` is the only builder of body
calls: the method-site hit, the versioned-loop and resolved-arrow indirect
calls, the known-closure and `$generic` direct calls, imported-object method
bodies and the public typed trampoline's generic fallback.

perry-abi: `JS_BODY_CALLEE_PARAM` / `JS_BODY_FIRST_ARG_PARAM`,
`JS_CLOSURE_CALL_ENTRIES` (the codegen `js_closure_call{N}` declarations are
generated from it; a runtime test checks each entry names the function taking
that many JS arguments) and `JS_CALL_ENTRIES`, from which
`gc_root_dominance_check.py` now reads its JS-call poll-capable set. That adds
`js_closure_call1_receiverless`, which the hand list lacked.

Gate: `scripts/check_js_body_call_funnel.py` (+ `--self-test`, wired into the
lint job) refuses a transmute to a body type outside the runtime funnel and an
indirect call built outside the codegen funnel. Native Rust helpers with a
body-shaped type carry `NOT-A-JS-BODY:`.

Also: delete `js_closure_unbind_this`, which was dead (no caller) and wrong (it
cleared capture slot 0; `this` lives in the LAST slot), and correct four
comments that stated false facts: `CAPTURES_THIS_FLAG` (last slot, not slot
0), the bind-result capture layout (5 slots, not 3), the `js_closure_alloc`
flag note, and the `new.rs` claim that a throw leaves `new.target` set (the
catch savepoint replays it at the nearest `try`).
…as a parameter

Every JS body — a compiled closure body, a function's value wrapper, a class
method's value wrapper, the namespace/no-op/unknown-function wrappers and
every native builtin installed as a function object — is now

    double body(i64 callee, i64 this, double a0, ...)

(perry_abi::JS_BODY_THIS_PARAM = 1, FIRST_ARG = 2). The receiver is NaN-boxed
bits in an integer register (owner decision D1). Behavior-neutral by
construction: every caller passes exactly the receiver the implicit-`this`
cell holds for the call, and bodies still read the cell.

Runtime: closure::JsThis (repr(transparent) u64). The body-call funnel
macros take the receiver; funnel callers pass JsThis::current(), read at the
call through the per-agent pointer block (PERRY_AGENT_PTRS slot 1), or the
receiver they know (js_closure_call1_receiverless). DirectCallN's fallback is
a body-typed adapter over js_closure_callN (call ENTRIES keep their
(callee, args) signature in this stage). 1,923 native body definitions
declare `_this: JsThis`; 137 direct Rust calls of native bodies pass the
cell's receiver. perry-ffi exports an ABI-identical JsThis.

Codegen: expr::body_call owns js_body_params / js_body_param_types /
emit_js_body_call(this_bits) / current_this_bits. The method-site hit passes
its receiver; arrow-only direct calls pass undefined; the closure-direct call
passes undefined when it bound the cell to undefined, else the cell's bits;
imported-object and Atomics direct calls pass the cell's bits. Stage-0 miss
closed: the inline `some` loop called its captureless callback directly.

Witness: PERRY_THIS_WITNESS=1 (compile time, in the object-cache key) emits
js_this_param_witness(%js_this, name) at the entry of every body that reads
the cell and reports `PERRY_THIS_WITNESS checks=N mismatches=M` at exit.

Gate: check_js_body_call_funnel.py refuses a body-shaped extern fn without the
receiver and a direct closure-allocator install of one (20 self-test cases).

Tests: closure/receiver_param_tests.rs (exact, padded, rest, wide, hoisted
routes; witness counts a disagreement); perry tests/this_param_abi.rs (route
fixture == node with checks >= 3000 and 0 mismatches; every installed body
defined with the ABI in the IR).

Five runtime/stdlib files pushed over the 2,000-line gate by the added
parameter are split (pipe listeners, Error user props, prototype-method
lookups, a test module, termios impls).
…his-as-a-parameter stage 1b)

The JS body type (`JsThis`, `js_body_fn_ty!`, `JsBody0`..`JsBody16`) is
defined once in perry-abi and shared by perry-runtime and perry-ffi 0.6.0.
perry-ffi's `alloc_closure` / `register_closure_arity` / new
`register_closure_rest` take a typed body instead of `*const u8`, so a body
with the wrong signature does not compile (compile_fail doctests).

Every call entry takes the receiver after the function:
js_closure_call{0..16}(closure, this, ..), js_native_call_value(func, this,
args, len), js_closure_call_array(closure, this, args, len) and
js_closure_call_apply_with_spread(box, this, ..). js_closure_call1_receiverless
is gone; V8's receiverless trampoline gets its own adapter,
js_closure_v8_callback(env, args, len). `DirectCallN::call` takes the
receiver. The ext/UI/audio crates pass receivers instead of saving and
restoring the implicit-`this` cell themselves.

Stage-1 semantics are unchanged: bodies still read the implicit-`this` cell.
An entry handed a receiver other than the cell's value binds the cell to it
for the call (an ImplicitThisScope, which roots the displaced value), except
for an arrow callee; a receiver equal to the cell binds nothing. Runtime and
stdlib plain calls pass `plain_call_receiver()`, which in stage 1 is the
cell's current value, and codegen's plain closure calls pass the cell bits,
so plain calls keep running with whatever the cell holds.

check_js_body_call_funnel.py now also refuses an entry declaration without
the receiver, a closure registrar declared outside runtime/stdlib/perry-ffi,
and a perry-ffi registration function taking `*const u8`.
A body that reads its dynamic `this` now reads its receiver parameter
instead of the thread-local implicit-`this` cell: function expressions and
object-literal methods store `%js_this` into their rooted entry `this` slot
(sloppy bodies apply OrdinaryCallBindThis once), top-level functions that
read `this` compile to `perry_fn_X$this` behind a receiver-less public
forwarder, `__perry_wrap_<method>` forwards its receiver, and the runtime's
native bodies read their `this` parameter.

The cell is still written by every caller, so this stage can be measured
on its own; stage 3 deletes it.

Instructions per call against stage 1 (LTO-off build, same host): an
object-literal method reading `this` 227 -> 143, an ES5 prototype method
217 -> 134, `forEach` with a `thisArg` 828 -> 744.
A body's `this` parameter is now the only way it learns its receiver, so no
caller saves, sets or restores an ambient `this` around a call.

- Deleted: the per-agent IMPLICIT_THIS cell, js_implicit_this_get /
  _get_sloppy / _set, ImplicitThisScope, its exception savepoint, its HotTls
  field and agent-pointer slot, the codegen save/restore funnel
  (rooting::implicit_this_*), and the stage-1 witness (PERRY_THIS_WITNESS).
- The receiver-taking entries (js_closure_call{N}, js_native_call_value,
  js_closure_call_array, js_closure_call_apply_with_spread) pass their
  receiver and bind nothing; a plain call passes undefined
  (plain_call_receiver()).
- Every runtime, stdlib and ext route that carried a receiver through the
  cell passes it: listeners get their emitter, util.promisify / callbackify /
  deprecate call the original with the wrapper's receiver, the legacy
  Intl.NumberFormat / DateTimeFormat chain sees its receiver, N-API
  napi_call_function passes recv. An accessor on an arguments object now
  runs with it as `this` (it never had it).
- Async and generator function expressions bind their receiver at entry;
  module top-level `this` is undefined (strict) / globalThis (sloppy).
- A method's entry-resolved callback target
  (js_closure_resolve_plain_direct_call) admits ordinary functions too.

Instructions per call (LTO-off build, same host), main -> this change:
closure value call 145 -> 46, two-argument closure call 160 -> 59,
object-literal method-site hit 99 -> 79, object-literal method reading
`this` 223 -> 120, ES5 prototype method 214 -> 110.
…o its own module

reactor.rs was 2010 lines, over the 2000-line cap enforced by
scripts/check_file_size.sh. Move the async exec/execFile section
(cp_exec_async, cp_exec_accumulate, cp_exec_fire_close,
cp_defer_exec_callback, cp_exec_cb_thunk) into a sibling
reactor/exec_async.rs, the same way stdin.rs and streams.rs were
already split out of this file. Pure code move, no behavior change.
…rameter wrapper ABI

The this-as-a-parameter ABI now passes the JS receiver as a second
i64 parameter (i64 %this_closure, i64 %js_this) into every installed
body, so the wrapper's forwarding call must include %js_this
alongside %this_closure. Update the expected call shape; the test
still asserts what it always asserted -- function identity through
the $-export alias resolves by ID, not by the exported spelling.
@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 777 files, which is 477 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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: ed32bcff-3251-41a5-9e18-f2a00a67e2fe

📥 Commits

Reviewing files that changed from the base of the PR and between b0bf0ae and a33fcfb.

⛔ Files ignored due to path filters (5)
  • Cargo.lock is excluded by !**/*.lock
  • crates/perry-codegen/src/gc_effects/linux-x86_64.tsv is excluded by !**/*.tsv
  • crates/perry-codegen/src/gc_effects/macos-aarch64.tsv is excluded by !**/*.tsv
  • crates/perry-codegen/src/gc_effects/windows-x86_64.tsv is excluded by !**/*.tsv
  • crates/perry-codegen/src/wasm32/runtime_abi.tsv is excluded by !**/*.tsv
📒 Files selected for processing (777)
  • .github/workflows/test.yml
  • Cargo.toml
  • changelog.d/11637-perry-ffi-0.6-typed-js-bodies.md
  • changelog.d/11637-this-as-a-parameter-stage-1.md
  • changelog.d/11637-this-as-a-parameter-stage-2.md
  • changelog.d/11637-this-as-a-parameter-stage-3.md
  • crates/perry-abi/src/lib.rs
  • crates/perry-audio-miniaudio/src/lib.rs
  • crates/perry-codegen/src/codegen/artifacts.rs
  • crates/perry-codegen/src/codegen/closure.rs
  • crates/perry-codegen/src/codegen/entry.rs
  • crates/perry-codegen/src/codegen/export_value_wrappers.rs
  • crates/perry-codegen/src/codegen/function.rs
  • crates/perry-codegen/src/codegen/helpers.rs
  • crates/perry-codegen/src/codegen/hoisted_callback_method_tests.rs
  • crates/perry-codegen/src/codegen/literal_method_this_tests.rs
  • crates/perry-codegen/src/codegen/method.rs
  • crates/perry-codegen/src/codegen/method_static.rs
  • crates/perry-codegen/src/codegen/mod.rs
  • crates/perry-codegen/src/codegen/namespace_value_getters.rs
  • crates/perry-codegen/src/codegen/opts.rs
  • crates/perry-codegen/src/collectors/hoisted_callback_calls.rs
  • crates/perry-codegen/src/expr/array_callback_shape_tests.rs
  • crates/perry-codegen/src/expr/arrays_finds.rs
  • crates/perry-codegen/src/expr/body_call.rs
  • crates/perry-codegen/src/expr/call_spread.rs
  • crates/perry-codegen/src/expr/closure.rs
  • crates/perry-codegen/src/expr/dyn_extern_i18n.rs
  • crates/perry-codegen/src/expr/hot_tls.rs
  • crates/perry-codegen/src/expr/js_runtime.rs
  • crates/perry-codegen/src/expr/logical_collections.rs
  • crates/perry-codegen/src/expr/method_site.rs
  • crates/perry-codegen/src/expr/mod.rs
  • crates/perry-codegen/src/expr/object_literal.rs
  • crates/perry-codegen/src/expr/property_get.rs
  • crates/perry-codegen/src/expr/super_method.rs
  • crates/perry-codegen/src/expr/this_super_call.rs
  • crates/perry-codegen/src/gc_call_effects.rs
  • crates/perry-codegen/src/lower_call/atomics.rs
  • crates/perry-codegen/src/lower_call/console_promise.rs
  • crates/perry-codegen/src/lower_call/early_branches.rs
  • crates/perry-codegen/src/lower_call/func_ref.rs
  • crates/perry-codegen/src/lower_call/method_override.rs
  • crates/perry-codegen/src/lower_call/mod.rs
  • crates/perry-codegen/src/lower_call/new.rs
  • crates/perry-codegen/src/lower_call/pipeline_call_tests.rs
  • crates/perry-codegen/src/lower_call/property_get/dynamic_dispatch.rs
  • crates/perry-codegen/src/lower_call/property_get/imported_object.rs
  • crates/perry-codegen/src/lower_call/property_get/static_dispatch.rs
  • crates/perry-codegen/src/rooting/group.rs
  • crates/perry-codegen/src/rooting/ledger.rs
  • crates/perry-codegen/src/rooting/mod.rs
  • crates/perry-codegen/src/rooting/temp_root.rs
  • crates/perry-codegen/src/runtime_decls/objects.rs
  • crates/perry-codegen/src/runtime_decls/stdlib_ffi/language_core.rs
  • crates/perry-codegen/src/runtime_decls/strings.rs
  • crates/perry-codegen/src/runtime_decls/strings_part2.rs
  • crates/perry-codegen/src/stubs.rs
  • crates/perry-codegen/src/wasm32/closure_abi.rs
  • crates/perry-codegen/tests/export_function_alias_identity.rs
  • crates/perry-ext-events/src/dispatch_ext.rs
  • crates/perry-ext-events/src/lib.rs
  • crates/perry-ext-events/src/max_listeners.rs
  • crates/perry-ext-events/src/module_iterators.rs
  • crates/perry-ext-events/src/module_on.rs
  • crates/perry-ext-events/src/tests.rs
  • crates/perry-ext-http/src/agent.rs
  • crates/perry-ext-http/src/client_abort.rs
  • crates/perry-ext-http/src/client_events.rs
  • crates/perry-ext-http/src/client_request_surface.rs
  • crates/perry-ext-http/src/lib.rs
  • crates/perry-ext-http/src/server/bun_server.rs
  • crates/perry-ext-http/src/server/http2_server.rs
  • crates/perry-ext-http/src/server/http2_server/pump.rs
  • crates/perry-ext-http/src/server/https_server.rs
  • crates/perry-ext-http/src/server/request.rs
  • crates/perry-ext-http/src/server/response.rs
  • crates/perry-ext-http/src/server/response_end.rs
  • crates/perry-ext-http/src/server/server.rs
  • crates/perry-ext-http/src/server/server/deferred_events.rs
  • crates/perry-ext-http/src/server/server/upgrade_tests.rs
  • crates/perry-ext-http/src/server/types.rs
  • crates/perry-ext-http/src/server/upgrade.rs
  • crates/perry-ext-http/src/tls_client.rs
  • crates/perry-ext-net/src/bun_tcp.rs
  • crates/perry-ext-net/src/dispatch.rs
  • crates/perry-ext-net/src/lifecycle.rs
  • crates/perry-ext-net/src/pipe.rs
  • crates/perry-ext-net/src/socket_emit.rs
  • crates/perry-ext-net/src/socket_events.rs
  • crates/perry-ext-parcel-watcher/src/lib.rs
  • crates/perry-ext-streams/src/lib.rs
  • crates/perry-ext-typescript/src/bun.rs
  • crates/perry-ext-ws/src/lib.rs
  • crates/perry-ext-ws/src/server.rs
  • crates/perry-ext-ws/src/tests.rs
  • crates/perry-ext-zlib/src/lib.rs
  • crates/perry-ext-zlib/src/stream.rs
  • crates/perry-ffi/Cargo.toml
  • crates/perry-ffi/src/closure.rs
  • crates/perry-ffi/src/lib.rs
  • crates/perry-runtime/src/agent_ptrs.rs
  • crates/perry-runtime/src/arkts_callbacks.rs
  • crates/perry-runtime/src/array/collection_tag_tests.rs
  • crates/perry-runtime/src/array/flat_clone.rs
  • crates/perry-runtime/src/array/generic.rs
  • crates/perry-runtime/src/array/generic_object.rs
  • crates/perry-runtime/src/array/iter_methods.rs
  • crates/perry-runtime/src/array/iter_object.rs
  • crates/perry-runtime/src/array/iterator.rs
  • crates/perry-runtime/src/array/reduce_right.rs
  • crates/perry-runtime/src/array/sort.rs
  • crates/perry-runtime/src/array/tests.rs
  • crates/perry-runtime/src/array/typed_array_receiver_tests.rs
  • crates/perry-runtime/src/async_hooks.rs
  • crates/perry-runtime/src/async_hooks/context_snapshots.rs
  • crates/perry-runtime/src/async_hooks/provider_ffi.rs
  • crates/perry-runtime/src/async_hooks/test_support.rs
  • crates/perry-runtime/src/atomics.rs
  • crates/perry-runtime/src/buffer/mod.rs
  • crates/perry-runtime/src/builtins/console.rs
  • crates/perry-runtime/src/builtins/formatting.rs
  • crates/perry-runtime/src/builtins/globals.rs
  • crates/perry-runtime/src/bun_compat/cli_utils.rs
  • crates/perry-runtime/src/bun_compat/glob.rs
  • crates/perry-runtime/src/bun_compat/mod.rs
  • crates/perry-runtime/src/bun_compat/plugin.rs
  • crates/perry-runtime/src/bun_compat/self_global.rs
  • crates/perry-runtime/src/bun_compat/spawn.rs
  • crates/perry-runtime/src/bun_ffi/callback.rs
  • crates/perry-runtime/src/bun_ffi/dlopen.rs
  • crates/perry-runtime/src/bun_ffi/read.rs
  • crates/perry-runtime/src/child_process/builder.rs
  • crates/perry-runtime/src/child_process/emitter.rs
  • crates/perry-runtime/src/child_process/emitter/relocation_tests.rs
  • crates/perry-runtime/src/child_process/exec.rs
  • crates/perry-runtime/src/child_process/failed_spawn.rs
  • crates/perry-runtime/src/child_process/reactor.rs
  • crates/perry-runtime/src/child_process/reactor/exec_async.rs
  • crates/perry-runtime/src/child_process/reactor/lifecycle_tests.rs
  • crates/perry-runtime/src/child_process/reactor/stdin_drain.rs
  • crates/perry-runtime/src/child_process/value_util.rs
  • crates/perry-runtime/src/closure/alloc.rs
  • crates/perry-runtime/src/closure/body_call.rs
  • crates/perry-runtime/src/closure/dispatch.rs
  • crates/perry-runtime/src/closure/dispatch/bound.rs
  • crates/perry-runtime/src/closure/dispatch/bound/function_method_value_tests.rs
  • crates/perry-runtime/src/closure/dispatch/calln.rs
  • crates/perry-runtime/src/closure/dispatch/direct.rs
  • crates/perry-runtime/src/closure/dispatch/validate.rs
  • crates/perry-runtime/src/closure/dispatch/value_call.rs
  • crates/perry-runtime/src/closure/dynamic_props.rs
  • crates/perry-runtime/src/closure/mod.rs
  • crates/perry-runtime/src/closure/receiver_param_tests.rs
  • crates/perry-runtime/src/closure/registry.rs
  • crates/perry-runtime/src/closure/shape.rs
  • crates/perry-runtime/src/closure/tests.rs
  • crates/perry-runtime/src/closure/unbox.rs
  • crates/perry-runtime/src/closure/wide_call.rs
  • crates/perry-runtime/src/cluster.rs
  • crates/perry-runtime/src/collection_iter.rs
  • crates/perry-runtime/src/dgram.rs
  • crates/perry-runtime/src/dgram/net.rs
  • crates/perry-runtime/src/dgram/ops.rs
  • crates/perry-runtime/src/dgram/thunks.rs
  • crates/perry-runtime/src/disposable.rs
  • crates/perry-runtime/src/dns.rs
  • crates/perry-runtime/src/dyn_eval/bench.rs
  • crates/perry-runtime/src/dyn_eval/bridge.rs
  • crates/perry-runtime/src/dyn_eval/interp.rs
  • crates/perry-runtime/src/dyn_eval/registry_lifetime_tests.rs
  • crates/perry-runtime/src/dyn_eval/tests.rs
  • crates/perry-runtime/src/error.rs
  • crates/perry-runtime/src/error_subclass_stack.rs
  • crates/perry-runtime/src/event_target.rs
  • crates/perry-runtime/src/exception.rs
  • crates/perry-runtime/src/exception/savepoints.rs
  • crates/perry-runtime/src/exception/savepoints/tests.rs
  • crates/perry-runtime/src/ffi/perry_wasi_sig.c
  • crates/perry-runtime/src/frame.rs
  • crates/perry-runtime/src/fs/cp.rs
  • crates/perry-runtime/src/fs/deferred.rs
  • crates/perry-runtime/src/fs/dir_glob_watch/glob.rs
  • crates/perry-runtime/src/fs/dir_glob_watch/watch.rs
  • crates/perry-runtime/src/fs/fd_ops.rs
  • crates/perry-runtime/src/fs/filehandle.rs
  • crates/perry-runtime/src/fs/mkdtemp_disposable.rs
  • crates/perry-runtime/src/fs/stats.rs
  • crates/perry-runtime/src/fs/stream.rs
  • crates/perry-runtime/src/fs/stream/read_turn.rs
  • crates/perry-runtime/src/fs/stream/utf8_stream.rs
  • crates/perry-runtime/src/fs/stream/write_file_input.rs
  • crates/perry-runtime/src/fs/stream/write_turn.rs
  • crates/perry-runtime/src/gc/mod.rs
  • crates/perry-runtime/src/gc/tests/array_pointer_slot_enumeration.rs
  • crates/perry-runtime/src/gc/tests/copying/pointer_publish_7154.rs
  • crates/perry-runtime/src/gc/tests/copying/weak_holder_registry.rs
  • crates/perry-runtime/src/gc/tests/copying/weak_semantics.rs
  • crates/perry-runtime/src/gc/tests/layout_trace/object_closure_slots.rs
  • crates/perry-runtime/src/gc/tests/pinned_roots.rs
  • crates/perry-runtime/src/gc/tests/rooted_container_values.rs
  • crates/perry-runtime/src/gc/tests/rooted_define_property.rs
  • crates/perry-runtime/src/gc/tests/rooted_for_in.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/arraylike_callbacks.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/call_argument_lists.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/callback_scanners.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/generator_attach_prototype.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/hook_dispatch_handles.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/implicit_this_scope.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/json_record_output.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/perex_construction.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/perex_dispatch.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/perex_glob.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/perex_match_all.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/perex_match_search.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/perex_public.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/perex_replace.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/perex_replace_direct.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/perex_split.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/regexp_last_index.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/side_table_scanners.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/sort_collection.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/string_normalize_form.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/thenable_assimilation.rs
  • crates/perry-runtime/src/gc/tests/runtime_roots/transient_handles.rs
  • crates/perry-runtime/src/gc/tests/step_bounds.rs
  • crates/perry-runtime/src/gc/tests/support.rs
  • crates/perry-runtime/src/geisterhand_registry.rs
  • crates/perry-runtime/src/intl.rs
  • crates/perry-runtime/src/intl/constructor_thunks.rs
  • crates/perry-runtime/src/intl/ctor_guard.rs
  • crates/perry-runtime/src/intl/date_collator.rs
  • crates/perry-runtime/src/intl/date_collator/range.rs
  • crates/perry-runtime/src/intl/display_names.rs
  • crates/perry-runtime/src/intl/duration_format.rs
  • crates/perry-runtime/src/intl/list_relative_plural.rs
  • crates/perry-runtime/src/intl/locale.rs
  • crates/perry-runtime/src/intl/locales.rs
  • crates/perry-runtime/src/intl/number_format.rs
  • crates/perry-runtime/src/intl/segmenter.rs
  • crates/perry-runtime/src/intl/segments_view.rs
  • crates/perry-runtime/src/intl/subclass.rs
  • crates/perry-runtime/src/iterator_helpers.rs
  • crates/perry-runtime/src/iterator_helpers/tests.rs
  • crates/perry-runtime/src/json/replacer.rs
  • crates/perry-runtime/src/json/replacer_hidden_fields_tests.rs
  • crates/perry-runtime/src/json/reviver.rs
  • crates/perry-runtime/src/json/stringify.rs
  • crates/perry-runtime/src/json/stringify_scalars.rs
  • crates/perry-runtime/src/json_tape/cached_read.rs
  • crates/perry-runtime/src/jsx.rs
  • crates/perry-runtime/src/lib.rs
  • crates/perry-runtime/src/map.rs
  • crates/perry-runtime/src/map_tombstone_tests.rs
  • crates/perry-runtime/src/media_playback.rs
  • crates/perry-runtime/src/messaging.rs
  • crates/perry-runtime/src/module_require.rs
  • crates/perry-runtime/src/module_require/import_meta_resolve.rs
  • crates/perry-runtime/src/node_api_host/functions.rs
  • crates/perry-runtime/src/node_api_host/v10_tests.rs
  • crates/perry-runtime/src/node_inspector.rs
  • crates/perry-runtime/src/node_repl.rs
  • crates/perry-runtime/src/node_stream.rs
  • crates/perry-runtime/src/node_stream/async_iterator.rs
  • crates/perry-runtime/src/node_stream/async_iterator/foreign_eof_tests.rs
  • crates/perry-runtime/src/node_stream/pipe_listeners.rs
  • crates/perry-runtime/src/node_stream/readable_from_promises.rs
  • crates/perry-runtime/src/node_stream_constructors/builders.rs
  • crates/perry-runtime/src/node_stream_constructors/pipeline.rs
  • crates/perry-runtime/src/node_stream_constructors/web_adapter.rs
  • crates/perry-runtime/src/node_stream_destroy_state.rs
  • crates/perry-runtime/src/node_stream_dispatch.rs
  • crates/perry-runtime/src/node_stream_event_emitter.rs
  • crates/perry-runtime/src/node_stream_iter_helpers.rs
  • crates/perry-runtime/src/node_stream_pipeline.rs
  • crates/perry-runtime/src/node_stream_readwrite.rs
  • crates/perry-runtime/src/node_stream_state_view.rs
  • crates/perry-runtime/src/node_stream_tests.rs
  • crates/perry-runtime/src/node_stream_tests_extra.rs
  • crates/perry-runtime/src/node_submodules/blob.rs
  • crates/perry-runtime/src/node_submodules/consumers.rs
  • crates/perry-runtime/src/node_submodules/diagnostics.rs
  • crates/perry-runtime/src/node_submodules/diagnostics/user_props.rs
  • crates/perry-runtime/src/node_submodules/diagnostics_tail.rs
  • crates/perry-runtime/src/node_submodules/fs_promises.rs
  • crates/perry-runtime/src/node_submodules/hono_jsx.rs
  • crates/perry-runtime/src/node_submodules/mod.rs
  • crates/perry-runtime/src/node_submodules/stream_promises.rs
  • crates/perry-runtime/src/node_submodules/test.rs
  • crates/perry-runtime/src/node_submodules/test_metadata_unit_tests.rs
  • crates/perry-runtime/src/node_submodules/test_once_unit_tests.rs
  • crates/perry-runtime/src/node_submodules/test_property.rs
  • crates/perry-runtime/src/node_submodules/test_reporters.rs
  • crates/perry-runtime/src/node_submodules/test_runner.rs
  • crates/perry-runtime/src/node_submodules/test_snapshot.rs
  • crates/perry-runtime/src/node_submodules/test_unit_tests.rs
  • crates/perry-runtime/src/node_submodules/tests.rs
  • crates/perry-runtime/src/node_submodules/timers.rs
  • crates/perry-runtime/src/node_submodules/trace_events.rs
  • crates/perry-runtime/src/node_test.rs
  • crates/perry-runtime/src/node_v8.rs
  • crates/perry-runtime/src/node_vm.rs
  • crates/perry-runtime/src/node_vm/modules.rs
  • crates/perry-runtime/src/object/accessor_pair_tests.rs
  • crates/perry-runtime/src/object/arguments.rs
  • crates/perry-runtime/src/object/assert.rs
  • crates/perry-runtime/src/object/async_generator_queue.rs
  • crates/perry-runtime/src/object/bound_method_receiver_tests.rs
  • crates/perry-runtime/src/object/class_constructors.rs
  • crates/perry-runtime/src/object/class_gc_roots.rs
  • crates/perry-runtime/src/object/class_registry/construct.rs
  • crates/perry-runtime/src/object/class_registry/construct/prototype_methods.rs
  • crates/perry-runtime/src/object/class_registry/construct/rooted_arguments.rs
  • crates/perry-runtime/src/object/class_registry/decl_accessors.rs
  • crates/perry-runtime/src/object/class_registry/parent_static.rs
  • crates/perry-runtime/src/object/class_registry/parent_static/private_and_dynamic.rs
  • crates/perry-runtime/src/object/class_registry/parent_static/static_accessor_call.rs
  • crates/perry-runtime/src/object/class_registry/prototype_objects.rs
  • crates/perry-runtime/src/object/class_registry/registration.rs
  • crates/perry-runtime/src/object/class_registry/state.rs
  • crates/perry-runtime/src/object/class_value.rs
  • crates/perry-runtime/src/object/collection_proto_thunks.rs
  • crates/perry-runtime/src/object/collection_proto_thunks/subclass_tests.rs
  • crates/perry-runtime/src/object/dataview_proto_thunks.rs
  • crates/perry-runtime/src/object/date_proto_thunks.rs
  • crates/perry-runtime/src/object/descriptor_state.rs
  • crates/perry-runtime/src/object/disposable_proto_thunks.rs
  • crates/perry-runtime/src/object/field_get_set/accessors.rs
  • crates/perry-runtime/src/object/field_get_set/class_object_props.rs
  • crates/perry-runtime/src/object/field_get_set/field_ops.rs
  • crates/perry-runtime/src/object/field_get_set/get_field_by_name.rs
  • crates/perry-runtime/src/object/field_get_set/has_property/function_presence_tests.rs
  • crates/perry-runtime/src/object/field_set_by_name/tail.rs
  • crates/perry-runtime/src/object/global_fetch.rs
  • crates/perry-runtime/src/object/global_this/array_error.rs
  • crates/perry-runtime/src/object/global_this/array_error/apply_args_tests.rs
  • crates/perry-runtime/src/object/global_this/bigint_promise.rs
  • crates/perry-runtime/src/object/global_this/builtin_thunks.rs
  • crates/perry-runtime/src/object/global_this/ctor_thunks.rs
  • crates/perry-runtime/src/object/global_this/fetch_globals.rs
  • crates/perry-runtime/src/object/global_this/generator.rs
  • crates/perry-runtime/src/object/global_this/install_static.rs
  • crates/perry-runtime/src/object/global_this/math_temporal.rs
  • crates/perry-runtime/src/object/global_this/populate.rs
  • crates/perry-runtime/src/object/global_this/proto_methods.rs
  • crates/perry-runtime/src/object/global_this/typed_array.rs
  • crates/perry-runtime/src/object/global_this_tables.rs
  • crates/perry-runtime/src/object/global_this_webassembly.rs
  • crates/perry-runtime/src/object/groupby.rs
  • crates/perry-runtime/src/object/handle_expando.rs
  • crates/perry-runtime/src/object/inherited_read_cache.rs
  • crates/perry-runtime/src/object/inherited_read_cache_tests.rs
  • crates/perry-runtime/src/object/instanceof.rs
  • crates/perry-runtime/src/object/instanceof/proxy_rhs.rs
  • crates/perry-runtime/src/object/instanceof/static_dispatch.rs
  • crates/perry-runtime/src/object/iterator_prototypes.rs
  • crates/perry-runtime/src/object/literal_constructor.rs
  • crates/perry-runtime/src/object/mod.rs
  • crates/perry-runtime/src/object/native_call_method.rs
  • crates/perry-runtime/src/object/native_call_method/closure_override_tests.rs
  • crates/perry-runtime/src/object/native_call_method/code_point_at_dispatch_tests.rs
  • crates/perry-runtime/src/object/native_call_method/collection_methods.rs
  • crates/perry-runtime/src/object/native_call_method/common_methods.rs
  • crates/perry-runtime/src/object/native_call_method/dispatch_arg_coercion_tests.rs
  • crates/perry-runtime/src/object/native_call_method/disposal.rs
  • crates/perry-runtime/src/object/native_call_method/function_shape.rs
  • crates/perry-runtime/src/object/native_call_method/handle_methods.rs
  • crates/perry-runtime/src/object/native_call_method/namespace_override.rs
  • crates/perry-runtime/src/object/native_call_method/object_proto.rs
  • crates/perry-runtime/src/object/native_call_method/patched_proto.rs
  • crates/perry-runtime/src/object/native_call_method/primitive_methods.rs
  • crates/perry-runtime/src/object/native_call_method/proto_dispatch.rs
  • crates/perry-runtime/src/object/native_call_method/to_locale_string_tests.rs
  • crates/perry-runtime/src/object/native_get/tests.rs
  • crates/perry-runtime/src/object/native_module.rs
  • crates/perry-runtime/src/object/native_module/async_hooks_exports.rs
  • crates/perry-runtime/src/object/native_module/buffer_pool_size_tests.rs
  • crates/perry-runtime/src/object/native_module/callable_exports.rs
  • crates/perry-runtime/src/object/native_module/callable_exports/buffer_species.rs
  • crates/perry-runtime/src/object/native_module/callable_exports/module_cjs.rs
  • crates/perry-runtime/src/object/native_module/class_method_bind.rs
  • crates/perry-runtime/src/object/native_module/namespace_builders.rs
  • crates/perry-runtime/src/object/native_module/web_locks.rs
  • crates/perry-runtime/src/object/native_module_registry.rs
  • crates/perry-runtime/src/object/native_module_stream.rs
  • crates/perry-runtime/src/object/native_this_alias.rs
  • crates/perry-runtime/src/object/nm_namespace_hooks.rs
  • crates/perry-runtime/src/object/own_override.rs
  • crates/perry-runtime/src/object/own_override_push_tests.rs
  • crates/perry-runtime/src/object/primitive_proto_thunks.rs
  • crates/perry-runtime/src/object/property_key.rs
  • crates/perry-runtime/src/object/prototype_chain.rs
  • crates/perry-runtime/src/object/regex_proto_thunks.rs
  • crates/perry-runtime/src/object/reserved_floor.rs
  • crates/perry-runtime/src/object/restricted_function_store_tests.rs
  • crates/perry-runtime/src/object/string_proto_thunks.rs
  • crates/perry-runtime/src/object/temporal_proto.rs
  • crates/perry-runtime/src/object/tests.rs
  • crates/perry-runtime/src/object/this_binding.rs
  • crates/perry-runtime/src/object/to_string_tag.rs
  • crates/perry-runtime/src/object/typed_array_proto_thunks.rs
  • crates/perry-runtime/src/object/util_types.rs
  • crates/perry-runtime/src/object/view_brand_tests.rs
  • crates/perry-runtime/src/object/weakref_proto_thunks.rs
  • crates/perry-runtime/src/os/os_process_emitter.rs
  • crates/perry-runtime/src/os_process_streams.rs
  • crates/perry-runtime/src/os_process_streams/reader_lifecycle_tests.rs
  • crates/perry-runtime/src/perf_hooks.rs
  • crates/perry-runtime/src/perf_hooks/prototypes.rs
  • crates/perry-runtime/src/perf_hooks/prototypes/performance_methods.rs
  • crates/perry-runtime/src/perf_hooks/timerify.rs
  • crates/perry-runtime/src/plugin.rs
  • crates/perry-runtime/src/process.rs
  • crates/perry-runtime/src/process/env_misc.rs
  • crates/perry-runtime/src/process/finalization.rs
  • crates/perry-runtime/src/process/ipc.rs
  • crates/perry-runtime/src/process/node_module.rs
  • crates/perry-runtime/src/process/node_module/source_map.rs
  • crates/perry-runtime/src/process/permission.rs
  • crates/perry-runtime/src/process/report.rs
  • crates/perry-runtime/src/promise/assimilate.rs
  • crates/perry-runtime/src/promise/async_step.rs
  • crates/perry-runtime/src/promise/checked_dispatch.rs
  • crates/perry-runtime/src/promise/combinators.rs
  • crates/perry-runtime/src/promise/combinators_tests.rs
  • crates/perry-runtime/src/promise/microtasks.rs
  • crates/perry-runtime/src/promise/microtasks/empty.rs
  • crates/perry-runtime/src/promise/mod.rs
  • crates/perry-runtime/src/promise/rejection_loop_tests.rs
  • crates/perry-runtime/src/promise/resolving_function_kind_tests.rs
  • crates/perry-runtime/src/promise/scanners.rs
  • crates/perry-runtime/src/promise/spec_combinators.rs
  • crates/perry-runtime/src/promise/subclass.rs
  • crates/perry-runtime/src/promise/then.rs
  • crates/perry-runtime/src/proxy.rs
  • crates/perry-runtime/src/proxy/apply_construct.rs
  • crates/perry-runtime/src/proxy/get.rs
  • crates/perry-runtime/src/proxy/json.rs
  • crates/perry-runtime/src/proxy/reflect.rs
  • crates/perry-runtime/src/proxy/reflect_misc.rs
  • crates/perry-runtime/src/pty/mod.rs
  • crates/perry-runtime/src/pty/tests.rs
  • crates/perry-runtime/src/readline_helpers.rs
  • crates/perry-runtime/src/regex/match_all.rs
  • crates/perry-runtime/src/regex/perex_dispatch.rs
  • crates/perry-runtime/src/regex/perex_match_search.rs
  • crates/perry-runtime/src/regex/perex_replace.rs
  • crates/perry-runtime/src/regex/perex_replace_storage.rs
  • crates/perry-runtime/src/regex/perex_split.rs
  • crates/perry-runtime/src/regex/perex_substitution.rs
  • crates/perry-runtime/src/regex/replace_fn.rs
  • crates/perry-runtime/src/regex/site_test.rs
  • crates/perry-runtime/src/set.rs
  • crates/perry-runtime/src/set_tombstone_tests.rs
  • crates/perry-runtime/src/symbol/accessors.rs
  • crates/perry-runtime/src/symbol/inherited_accessor_tests.rs
  • crates/perry-runtime/src/symbol/iterator.rs
  • crates/perry-runtime/src/text.rs
  • crates/perry-runtime/src/thread.rs
  • crates/perry-runtime/src/timer.rs
  • crates/perry-runtime/src/timer/handle_object.rs
  • crates/perry-runtime/src/timer/tests_inline.rs
  • crates/perry-runtime/src/tls.rs
  • crates/perry-runtime/src/tls_hot.rs
  • crates/perry-runtime/src/tty.rs
  • crates/perry-runtime/src/tui/handle_object.rs
  • crates/perry-runtime/src/tui/hooks.rs
  • crates/perry-runtime/src/tui/input.rs
  • crates/perry-runtime/src/tui/run.rs
  • crates/perry-runtime/src/typed_feedback/tests.rs
  • crates/perry-runtime/src/typedarray/construct.rs
  • crates/perry-runtime/src/typedarray/iterate.rs
  • crates/perry-runtime/src/typedarray/species.rs
  • crates/perry-runtime/src/typedarray/transform.rs
  • crates/perry-runtime/src/typedarray_props.rs
  • crates/perry-runtime/src/url/abort.rs
  • crates/perry-runtime/src/url/prototype.rs
  • crates/perry-runtime/src/url/search_params.rs
  • crates/perry-runtime/src/util_abort.rs
  • crates/perry-runtime/src/util_debuglog.rs
  • crates/perry-runtime/src/util_promisify.rs
  • crates/perry-runtime/src/v8.rs
  • crates/perry-runtime/src/value/dynamic_array.rs
  • crates/perry-runtime/src/value/to_string_array.rs
  • crates/perry-runtime/src/value/to_string_class_ref.rs
  • crates/perry-runtime/src/value/to_string_primitive.rs
  • crates/perry-runtime/src/wasi.rs
  • crates/perry-runtime/src/weakref/test_support.rs
  • crates/perry-runtime/src/web_storage.rs
  • crates/perry-runtime/src/webassembly.rs
  • crates/perry-runtime/src/webassembly_calls.rs
  • crates/perry-runtime/src/webassembly_table.rs
  • crates/perry-runtime/src/yoga.rs
  • crates/perry-stdlib/src/async_local_storage.rs
  • crates/perry-stdlib/src/bun_sql.rs
  • crates/perry-stdlib/src/common/dispatch/emitter_als.rs
  • crates/perry-stdlib/src/common/net_method_values.rs
  • crates/perry-stdlib/src/crypto/hash_handles.rs
  • crates/perry-stdlib/src/crypto/keys.rs
  • crates/perry-stdlib/src/crypto/random.rs
  • crates/perry-stdlib/src/domain.rs
  • crates/perry-stdlib/src/events.rs
  • crates/perry-stdlib/src/events/events_on.rs
  • crates/perry-stdlib/src/events/module_helpers.rs
  • crates/perry-stdlib/src/events/once_helpers.rs
  • crates/perry-stdlib/src/events/warnings.rs
  • crates/perry-stdlib/src/fetch/body_metadata.rs
  • crates/perry-stdlib/src/fetch/headers.rs
  • crates/perry-stdlib/src/querystring.rs
  • crates/perry-stdlib/src/readline/mod.rs
  • crates/perry-stdlib/src/readline/pump.rs
  • crates/perry-stdlib/src/readline/termios_unix.rs
  • crates/perry-stdlib/src/readline/termios_windows.rs
  • crates/perry-stdlib/src/readline/test_support.rs
  • crates/perry-stdlib/src/runtime_thread_exit_tests.rs
  • crates/perry-stdlib/src/runtime_thread_exit_tests/listeners_tests.rs
  • crates/perry-stdlib/src/runtime_thread_exit_tests/stdlib_misc_tests.rs
  • crates/perry-stdlib/src/runtime_thread_exit_tests/streams_tests.rs
  • crates/perry-stdlib/src/runtime_thread_exit_tests/symbols_tests.rs
  • crates/perry-stdlib/src/runtime_thread_exit_tests/ui_tests.rs
  • crates/perry-stdlib/src/sqlite/backup.rs
  • crates/perry-stdlib/src/sqlite/better.rs
  • crates/perry-stdlib/src/sqlite/bind.rs
  • crates/perry-stdlib/src/sqlite/bun.rs
  • crates/perry-stdlib/src/sqlite/dispatch.rs
  • crates/perry-stdlib/src/sqlite/node_stmt_session.rs
  • crates/perry-stdlib/src/streams.rs
  • crates/perry-stdlib/src/streams/byob.rs
  • crates/perry-stdlib/src/streams/pipe.rs
  • crates/perry-stdlib/src/streams/strategy.rs
  • crates/perry-stdlib/src/streams/tee.rs
  • crates/perry-stdlib/src/streams/tests.rs
  • crates/perry-stdlib/src/streams/transform.rs
  • crates/perry-stdlib/src/streams/writable.rs
  • crates/perry-stdlib/src/string_decoder.rs
  • crates/perry-stdlib/src/tls.rs
  • crates/perry-stdlib/src/tls/event_pump.rs
  • crates/perry-stdlib/src/webcrypto/digest.rs
  • crates/perry-stdlib/src/worker_threads.rs
  • crates/perry-stdlib/src/worker_threads/broadcast_channel.rs
  • crates/perry-stdlib/src/worker_threads/message_port.rs
  • crates/perry-stdlib/src/worker_threads/parent_port.rs
  • crates/perry-stdlib/src/worker_threads/worker_pump.rs
  • crates/perry-stdlib/src/worker_threads/worker_surface.rs
  • crates/perry-stdlib/src/zlib.rs
  • crates/perry-ui-android/src/app.rs
  • crates/perry-ui-android/src/callback.rs
  • crates/perry-ui-android/src/dialog.rs
  • crates/perry-ui-android/src/drag_drop.rs
  • crates/perry-ui-android/src/media_playback.rs
  • crates/perry-ui-android/src/pointer.rs
  • crates/perry-ui-android/src/state.rs
  • crates/perry-ui-android/src/widgets/lazyvstack.rs
  • crates/perry-ui-android/src/widgets/table.rs
  • crates/perry-ui-android/src/widgets/webview.rs
  • crates/perry-ui-gtk4/src/app.rs
  • crates/perry-ui-gtk4/src/audio.rs
  • crates/perry-ui-gtk4/src/camera.rs
  • crates/perry-ui-gtk4/src/dialog.rs
  • crates/perry-ui-gtk4/src/drag_drop.rs
  • crates/perry-ui-gtk4/src/file_dialog.rs
  • crates/perry-ui-gtk4/src/issue_552_stub.rs
  • crates/perry-ui-gtk4/src/location.rs
  • crates/perry-ui-gtk4/src/media_playback.rs
  • crates/perry-ui-gtk4/src/menu.rs
  • crates/perry-ui-gtk4/src/network_stub.rs
  • crates/perry-ui-gtk4/src/state.rs
  • crates/perry-ui-gtk4/src/toolbar.rs
  • crates/perry-ui-gtk4/src/tray.rs
  • crates/perry-ui-gtk4/src/widgets/bottom_nav.rs
  • crates/perry-ui-gtk4/src/widgets/button.rs
  • crates/perry-ui-gtk4/src/widgets/calendar.rs
  • crates/perry-ui-gtk4/src/widgets/combobox.rs
  • crates/perry-ui-gtk4/src/widgets/command_palette.rs
  • crates/perry-ui-gtk4/src/widgets/date_picker.rs
  • crates/perry-ui-gtk4/src/widgets/image_gallery.rs
  • crates/perry-ui-gtk4/src/widgets/lazyvstack.rs
  • crates/perry-ui-gtk4/src/widgets/mod.rs
  • crates/perry-ui-gtk4/src/widgets/picker.rs
  • crates/perry-ui-gtk4/src/widgets/rich_text.rs
  • crates/perry-ui-gtk4/src/widgets/scrollview.rs
  • crates/perry-ui-gtk4/src/widgets/securefield.rs
  • crates/perry-ui-gtk4/src/widgets/slider.rs
  • crates/perry-ui-gtk4/src/widgets/textarea.rs
  • crates/perry-ui-gtk4/src/widgets/textfield.rs
  • crates/perry-ui-gtk4/src/widgets/toggle.rs
  • crates/perry-ui-gtk4/src/widgets/tree_view.rs
  • crates/perry-ui-gtk4/src/widgets/webview.rs
  • crates/perry-ui-gtk4/src/window.rs
  • crates/perry-ui-ios/src/adaptive_layout.rs
  • crates/perry-ui-ios/src/app.rs
  • crates/perry-ui-ios/src/audio_playback.rs
  • crates/perry-ui-ios/src/background.rs
  • crates/perry-ui-ios/src/camera.rs
  • crates/perry-ui-ios/src/deeplinks.rs
  • crates/perry-ui-ios/src/drag_drop.rs
  • crates/perry-ui-ios/src/file_dialog.rs
  • crates/perry-ui-ios/src/geolocation.rs
  • crates/perry-ui-ios/src/image_picker.rs
  • crates/perry-ui-ios/src/location.rs
  • crates/perry-ui-ios/src/media_playback.rs
  • crates/perry-ui-ios/src/menu.rs
  • crates/perry-ui-ios/src/network.rs
  • crates/perry-ui-ios/src/notifications.rs
  • crates/perry-ui-ios/src/pointer.rs
  • crates/perry-ui-ios/src/state.rs
  • crates/perry-ui-ios/src/widgets/alert.rs
  • crates/perry-ui-ios/src/widgets/bottom_nav.rs
  • crates/perry-ui-ios/src/widgets/button.rs
  • crates/perry-ui-ios/src/widgets/calendar.rs
  • crates/perry-ui-ios/src/widgets/combobox.rs
  • crates/perry-ui-ios/src/widgets/date_picker.rs
  • crates/perry-ui-ios/src/widgets/image_gallery.rs
  • crates/perry-ui-ios/src/widgets/mod.rs
  • crates/perry-ui-ios/src/widgets/picker.rs
  • crates/perry-ui-ios/src/widgets/rich_text.rs
  • crates/perry-ui-ios/src/widgets/scrollview.rs
  • crates/perry-ui-ios/src/widgets/securefield.rs
  • crates/perry-ui-ios/src/widgets/slider.rs
  • crates/perry-ui-ios/src/widgets/tabbar.rs
  • crates/perry-ui-ios/src/widgets/textarea.rs
  • crates/perry-ui-ios/src/widgets/textfield.rs
  • crates/perry-ui-ios/src/widgets/toggle.rs
  • crates/perry-ui-ios/src/widgets/tree_view.rs
  • crates/perry-ui-ios/src/widgets/webview.rs
  • crates/perry-ui-ios/src/widgets/wheel_picker.rs
  • crates/perry-ui-macos/src/app.rs
  • crates/perry-ui-macos/src/audio_playback.rs
  • crates/perry-ui-macos/src/background.rs
  • crates/perry-ui-macos/src/deeplinks.rs
  • crates/perry-ui-macos/src/drag_drop.rs
  • crates/perry-ui-macos/src/file_dialog.rs
  • crates/perry-ui-macos/src/geolocation.rs
  • crates/perry-ui-macos/src/image_picker.rs
  • crates/perry-ui-macos/src/location.rs
  • crates/perry-ui-macos/src/media_playback.rs
  • crates/perry-ui-macos/src/menu.rs
  • crates/perry-ui-macos/src/network.rs
  • crates/perry-ui-macos/src/notifications.rs
  • crates/perry-ui-macos/src/pointer.rs
  • crates/perry-ui-macos/src/state.rs
  • crates/perry-ui-macos/src/tray.rs
  • crates/perry-ui-macos/src/widgets/alert.rs
  • crates/perry-ui-macos/src/widgets/bottom_nav.rs
  • crates/perry-ui-macos/src/widgets/button.rs
  • crates/perry-ui-macos/src/widgets/calendar.rs
  • crates/perry-ui-macos/src/widgets/combobox.rs
  • crates/perry-ui-macos/src/widgets/command_palette.rs
  • crates/perry-ui-macos/src/widgets/date_picker.rs
  • crates/perry-ui-macos/src/widgets/foreach_registry.rs
  • crates/perry-ui-macos/src/widgets/image_gallery.rs
  • crates/perry-ui-macos/src/widgets/lazyvstack.rs
  • crates/perry-ui-macos/src/widgets/mod.rs
  • crates/perry-ui-macos/src/widgets/picker.rs
  • crates/perry-ui-macos/src/widgets/rich_text.rs
  • crates/perry-ui-macos/src/widgets/scrollview.rs
  • crates/perry-ui-macos/src/widgets/securefield.rs
  • crates/perry-ui-macos/src/widgets/slider.rs
  • crates/perry-ui-macos/src/widgets/table.rs
  • crates/perry-ui-macos/src/widgets/textarea.rs
  • crates/perry-ui-macos/src/widgets/textfield.rs
  • crates/perry-ui-macos/src/widgets/toggle.rs
  • crates/perry-ui-macos/src/widgets/toolbar.rs
  • crates/perry-ui-macos/src/widgets/tree_view.rs
  • crates/perry-ui-macos/src/widgets/webview.rs
  • crates/perry-ui-tvos/src/app.rs
  • crates/perry-ui-tvos/src/audio_playback.rs
  • crates/perry-ui-tvos/src/background.rs
  • crates/perry-ui-tvos/src/file_dialog.rs
  • crates/perry-ui-tvos/src/issue_552_stub.rs
  • crates/perry-ui-tvos/src/location.rs
  • crates/perry-ui-tvos/src/media_playback.rs
  • crates/perry-ui-tvos/src/menu.rs
  • crates/perry-ui-tvos/src/network_stub.rs
  • crates/perry-ui-tvos/src/pointer.rs
  • crates/perry-ui-tvos/src/state.rs
  • crates/perry-ui-tvos/src/widgets/alert.rs
  • crates/perry-ui-tvos/src/widgets/bottom_nav.rs
  • crates/perry-ui-tvos/src/widgets/button.rs
  • crates/perry-ui-tvos/src/widgets/mod.rs
  • crates/perry-ui-tvos/src/widgets/scrollview.rs
  • crates/perry-ui-tvos/src/widgets/securefield.rs
  • crates/perry-ui-tvos/src/widgets/slider.rs
  • crates/perry-ui-tvos/src/widgets/tabbar.rs
  • crates/perry-ui-tvos/src/widgets/textarea.rs
  • crates/perry-ui-tvos/src/widgets/textfield.rs
  • crates/perry-ui-tvos/src/widgets/toggle.rs
  • crates/perry-ui-visionos/src/app.rs
  • crates/perry-ui-visionos/src/audio_playback.rs
  • crates/perry-ui-visionos/src/background.rs
  • crates/perry-ui-visionos/src/camera.rs
  • crates/perry-ui-visionos/src/drag_drop.rs
  • crates/perry-ui-visionos/src/file_dialog.rs
  • crates/perry-ui-visionos/src/issue_552_stub.rs
  • crates/perry-ui-visionos/src/location.rs
  • crates/perry-ui-visionos/src/media_playback.rs
  • crates/perry-ui-visionos/src/menu.rs
  • crates/perry-ui-visionos/src/network_stub.rs
  • crates/perry-ui-visionos/src/pointer.rs
  • crates/perry-ui-visionos/src/state.rs
  • crates/perry-ui-visionos/src/widgets/alert.rs
  • crates/perry-ui-visionos/src/widgets/bottom_nav.rs
  • crates/perry-ui-visionos/src/widgets/button.rs
  • crates/perry-ui-visionos/src/widgets/calendar.rs
  • crates/perry-ui-visionos/src/widgets/combobox.rs
  • crates/perry-ui-visionos/src/widgets/date_picker.rs
  • crates/perry-ui-visionos/src/widgets/mod.rs
  • crates/perry-ui-visionos/src/widgets/rich_text.rs
  • crates/perry-ui-visionos/src/widgets/scrollview.rs
  • crates/perry-ui-visionos/src/widgets/securefield.rs
  • crates/perry-ui-visionos/src/widgets/slider.rs
  • crates/perry-ui-visionos/src/widgets/tabbar.rs
  • crates/perry-ui-visionos/src/widgets/textarea.rs
  • crates/perry-ui-visionos/src/widgets/textfield.rs
  • crates/perry-ui-visionos/src/widgets/tree_view.rs
  • crates/perry-ui-visionos/src/widgets/webview.rs
  • crates/perry-ui-visionos/src/widgets/wheel_picker.rs
  • crates/perry-ui-watchos/src/audio_playback.rs
  • crates/perry-ui-watchos/src/background.rs
  • crates/perry-ui-watchos/src/issue_552_stub.rs
  • crates/perry-ui-watchos/src/media_playback.rs
  • crates/perry-ui-watchos/src/network_stub.rs
  • crates/perry-ui-watchos/src/notifications.rs
  • crates/perry-ui-watchos/src/state.rs
  • crates/perry-ui-watchos/src/tree.rs
  • crates/perry-ui-windows-winui/src/app.rs
  • crates/perry-ui-windows-winui/src/widgets.rs
  • crates/perry-ui-windows/src/app.rs
  • crates/perry-ui-windows/src/dialog.rs
  • crates/perry-ui-windows/src/drag_drop.rs
  • crates/perry-ui-windows/src/file_dialog.rs
  • crates/perry-ui-windows/src/folder_dialog.rs
  • crates/perry-ui-windows/src/issue_552_stub.rs
  • crates/perry-ui-windows/src/media_playback.rs
  • crates/perry-ui-windows/src/menu.rs
  • crates/perry-ui-windows/src/network_stub.rs
  • crates/perry-ui-windows/src/pointer.rs
  • crates/perry-ui-windows/src/state.rs
  • crates/perry-ui-windows/src/toolbar.rs
  • crates/perry-ui-windows/src/tray.rs
  • crates/perry-ui-windows/src/widgets/bottom_nav.rs
  • crates/perry-ui-windows/src/widgets/button.rs
  • crates/perry-ui-windows/src/widgets/calendar.rs
  • crates/perry-ui-windows/src/widgets/combobox.rs
  • crates/perry-ui-windows/src/widgets/command_palette.rs
  • crates/perry-ui-windows/src/widgets/date_picker.rs
  • crates/perry-ui-windows/src/widgets/foreach_registry.rs
  • crates/perry-ui-windows/src/widgets/image_gallery.rs
  • crates/perry-ui-windows/src/widgets/lazyvstack.rs
  • crates/perry-ui-windows/src/widgets/mod.rs
  • crates/perry-ui-windows/src/widgets/picker.rs
  • crates/perry-ui-windows/src/widgets/rich_text.rs
  • crates/perry-ui-windows/src/widgets/scrollview.rs
  • crates/perry-ui-windows/src/widgets/securefield.rs
  • crates/perry-ui-windows/src/widgets/slider.rs
  • crates/perry-ui-windows/src/widgets/table.rs
  • crates/perry-ui-windows/src/widgets/textarea.rs
  • crates/perry-ui-windows/src/widgets/textfield.rs
  • crates/perry-ui-windows/src/widgets/toggle.rs
  • crates/perry-ui-windows/src/widgets/tree_view.rs
  • crates/perry-ui-windows/src/widgets/webview.rs
  • crates/perry-ui/src/key_dispatch.rs
  • crates/perry/tests/fixtures/this_param_routes.ts
  • crates/perry/tests/source_graph_export_regressions.rs
  • crates/perry/tests/this_param_abi.rs
  • scripts/check_js_body_call_funnel.py
  • scripts/check_runtime_symbols.sh
  • scripts/gc_root_dominance_check.py
  • scripts/gc_runtime_root_holders.json
  • scripts/local_binding_type_allowlist.json
  • scripts/publish_perry_ffi.sh
  • scripts/raw_handle_debt_files.txt
  • scripts/thread_exit_address_globals.json
  • scripts/unrooted_local_shape_baseline.json
  • test-files/test_compat_buffers_typed.ts
  • test-files/test_gap_this_param_receiver_routes.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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.

@proggeramlug proggeramlug added the run-extended-tests Opt PR into compile-smoke/parity/doc-tests/drizzle-mysql-smoke label Sep 28, 2026
Ralph Küpper added 4 commits September 28, 2026 17:16
…eceiver parameter

perry_wasi_sig.c ref.test candidate types (double (closure, f64 x k)) predate this-as-a-parameter: every real JS body now takes (closure, this: u64, f64 x k) on wasm32. None of the candidates ever match any more, so wasi_body_params always returns None and dispatch falls back to the caller arity instead of the body real one, under-supplying a body that declares more parameters than its call site -- an indirect-call type mismatch that traps under wasmtime (repro: scripts/wasi_smoke iterators.ts, gen().map(fn) through the shared IteratorPrototype[Symbol.iterator] thunk). Add the missing unsigned long long receiver parameter to every perry_body_N candidate typedef and update the doc comment.
# Conflicts:
#	crates/perry-runtime/src/timer.rs
Ralph Küpper added 3 commits September 29, 2026 00:08
…t made stale

Moving cp_exec_async into reactor/exec_async.rs took the only allocating
function that names CP_NEXT_LIVE_ID out of reactor.rs, so rule B no longer
makes the counter a candidate in its declaring file and the inventory entry
matches no holder. The static is still a scalar AtomicU64 id counter; the
ChildProcess values it keys live in CP_LIVE, which cp_reactor_scan_roots_mut
visits.
…ot an inlined dispatcher

native_call_value_this was #[inline(always)] over the whole value-call
dispatcher, and the this-as-a-parameter funnel routes ~130 runtime callers
through it, so every one of them carried its own copy (Function.prototype
call/apply thunks, forEach/replace callbacks, each arm_trap_and_run closure).
It grew every linked program by ~190 KB on linux-x64 (loop fixture
7,563,048 -> 7,755,560 stripped).

The dispatcher body now lives only in the two js_native_call_value
definitions; native_call_value_this is a thin call to the export. loop is
7,497,512 with this change, below main.
…install

736782e made Function.prototype.call/.apply run the node:stream
subclass-init shim for Readable.call(this, opts) by calling
js_node_stream_*_subclass_init directly. That path is linked into every
program, so it pinned all of node_stream (and the promise, timer and
process-stream code behind it) into programs that never import stream:
+554 KB stripped on the linux-x64 loop fixture (7,009,384 -> 7,563,048),
and the darwin-arm64 small-program budget over by 6-10%.

The shim is now registered by js_nm_install_stream, which codegen emits only
when a program imports stream; a stream base callee cannot exist otherwise.
The store is black_boxed like js_nm_enable_install_all, since the slot has a
single writer and whole-program optimization otherwise devirtualizes the load
back into a direct call. The dynamic super() path shares the same entry.

loop fixture: 7,497,512 -> 6,952,040 stripped. The #10448/#10449/#10454/
#10544/#10798 and stdio-writable gap tests still match node.
proggeramlug pushed a commit that referenced this pull request Sep 29, 2026
Ralph Küpper and others added 6 commits September 29, 2026 06:03
…erdict

nm_stream_subclass_init reassigned its load only under cfg(test), so a
non-test build saw an unused `mut` and failed the -D warnings job. Shadow
the binding in the test-only branch instead.

NM_STREAM_SUBCLASS_INIT holds only the node_stream_subclass_init fn
pointer (its one store is in js_nm_install_stream): a code address, never
an arena address. Record that no_heap_address verdict for the #11471
thread-exit custody gate, like its NM_CTOR/NM_ATTACH sibling registries.
Main moved class static accessors onto the class function object (#11651)
and made a class value its function object (#11609). Under the
this-as-a-parameter ABI:
- static accessor getters/setters (class_value, static_accessor_call) are
  bare bodies, called through js_bare_body_fn!;
- js_class_constructor_called, the [[Call]] body of every class function
  object, declares its receiver;
- the static data-property method call in class_receiver_arm passes the
  class as the receiver argument instead of setting the deleted
  implicit-this cell;
- the pinned-roots promise test callbacks declare the receiver.
Regenerated the linux gc_call_effects table and the wasm32 runtime ABI
table; the gc/mod.rs holder pin covers both sides' edits.
…pped

The PASS1_MARKED entry's audit trail took main's side in the merge and
lost this branch's note for the implicit-this scanner registration
(`scan_dispatch_binding_roots_mut`). Restore it after main's notes.
@proggeramlug
proggeramlug merged commit 4bc2690 into main Sep 29, 2026
22 of 27 checks passed
@proggeramlug
proggeramlug deleted the perf-this-as-parameter branch September 29, 2026 15:54
proggeramlug added a commit that referenced this pull request Sep 29, 2026
…losure-body registry (#11654)

* refactor: one funnel per side for every call of a JS function body (this-as-a-parameter, stage 0)

No behaviour change. Every place that turns a function body's code pointer
into a call now goes through one funnel, so the body ABI can change (stage 1:
the receiver becomes a parameter) in one place, with the compiler finding
every caller.

Runtime: `closure/body_call.rs` owns the body types and the only transmutes to
them: `js_body_fn_ty!` / `js_body_fn!` / `js_body_call!` /
`js_body_call_unwind!` for closure-ABI bodies `(callee, a0..)`,
`js_method_body_fn!` / `js_method_body_call!` for class method, constructor and
accessor bodies `(this, a0..)`, and `js_bare_body_fn!` for static methods,
static accessors and the lifted well-known hooks `(a0..)`. Routed through it:
the 17 direct arms of `js_closure_call0..16`, `dispatch_with_arity` (33 arms),
`dispatch_rest_bundled` (16 arms, now one macro), the wide ladder,
`DirectCall1..4`, the captureless `some` callback, the async-step microtask,
five `thread.rs` workers, 31 class accessor / static / hook calls, and the
`then(this, ..)` thenable call. The 57 typed native-body type positions
(install helpers, erasure casts) use `js_body_fn_ty!`. Production
(`panic = "abort"`) signatures are unchanged; in unwinding test builds rest
arms 1-6 now use the unwind-capable pointer type arms 0 and 7-15 already used.

Codegen: `expr/body_call.rs::emit_js_body_call` is the only builder of body
calls: the method-site hit, the versioned-loop and resolved-arrow indirect
calls, the known-closure and `$generic` direct calls, imported-object method
bodies and the public typed trampoline's generic fallback.

perry-abi: `JS_BODY_CALLEE_PARAM` / `JS_BODY_FIRST_ARG_PARAM`,
`JS_CLOSURE_CALL_ENTRIES` (the codegen `js_closure_call{N}` declarations are
generated from it; a runtime test checks each entry names the function taking
that many JS arguments) and `JS_CALL_ENTRIES`, from which
`gc_root_dominance_check.py` now reads its JS-call poll-capable set. That adds
`js_closure_call1_receiverless`, which the hand list lacked.

Gate: `scripts/check_js_body_call_funnel.py` (+ `--self-test`, wired into the
lint job) refuses a transmute to a body type outside the runtime funnel and an
indirect call built outside the codegen funnel. Native Rust helpers with a
body-shaped type carry `NOT-A-JS-BODY:`.

Also: delete `js_closure_unbind_this`, which was dead (no caller) and wrong (it
cleared capture slot 0; `this` lives in the LAST slot), and correct four
comments that stated false facts: `CAPTURES_THIS_FLAG` (last slot, not slot
0), the bind-result capture layout (5 slots, not 3), the `js_closure_alloc`
flag note, and the `new.rs` claim that a throw leaves `new.target` set (the
catch savepoint replays it at the nearest `try`).

* perf: this-as-a-parameter stage 1 — every JS body takes its receiver as a parameter

Every JS body — a compiled closure body, a function's value wrapper, a class
method's value wrapper, the namespace/no-op/unknown-function wrappers and
every native builtin installed as a function object — is now

    double body(i64 callee, i64 this, double a0, ...)

(perry_abi::JS_BODY_THIS_PARAM = 1, FIRST_ARG = 2). The receiver is NaN-boxed
bits in an integer register (owner decision D1). Behavior-neutral by
construction: every caller passes exactly the receiver the implicit-`this`
cell holds for the call, and bodies still read the cell.

Runtime: closure::JsThis (repr(transparent) u64). The body-call funnel
macros take the receiver; funnel callers pass JsThis::current(), read at the
call through the per-agent pointer block (PERRY_AGENT_PTRS slot 1), or the
receiver they know (js_closure_call1_receiverless). DirectCallN's fallback is
a body-typed adapter over js_closure_callN (call ENTRIES keep their
(callee, args) signature in this stage). 1,923 native body definitions
declare `_this: JsThis`; 137 direct Rust calls of native bodies pass the
cell's receiver. perry-ffi exports an ABI-identical JsThis.

Codegen: expr::body_call owns js_body_params / js_body_param_types /
emit_js_body_call(this_bits) / current_this_bits. The method-site hit passes
its receiver; arrow-only direct calls pass undefined; the closure-direct call
passes undefined when it bound the cell to undefined, else the cell's bits;
imported-object and Atomics direct calls pass the cell's bits. Stage-0 miss
closed: the inline `some` loop called its captureless callback directly.

Witness: PERRY_THIS_WITNESS=1 (compile time, in the object-cache key) emits
js_this_param_witness(%js_this, name) at the entry of every body that reads
the cell and reports `PERRY_THIS_WITNESS checks=N mismatches=M` at exit.

Gate: check_js_body_call_funnel.py refuses a body-shaped extern fn without the
receiver and a direct closure-allocator install of one (20 self-test cases).

Tests: closure/receiver_param_tests.rs (exact, padded, rest, wide, hoisted
routes; witness counts a disagreement); perry tests/this_param_abi.rs (route
fixture == node with checks >= 3000 and 0 mismatches; every installed body
defined with the ABI in the IR).

Five runtime/stdlib files pushed over the 2,000-line gate by the added
parameter are split (pipe listeners, Error user props, prototype-method
lookups, a test module, termios impls).

* perry-ffi 0.6: one typed JS body ABI, receiver-taking call entries (this-as-a-parameter stage 1b)

The JS body type (`JsThis`, `js_body_fn_ty!`, `JsBody0`..`JsBody16`) is
defined once in perry-abi and shared by perry-runtime and perry-ffi 0.6.0.
perry-ffi's `alloc_closure` / `register_closure_arity` / new
`register_closure_rest` take a typed body instead of `*const u8`, so a body
with the wrong signature does not compile (compile_fail doctests).

Every call entry takes the receiver after the function:
js_closure_call{0..16}(closure, this, ..), js_native_call_value(func, this,
args, len), js_closure_call_array(closure, this, args, len) and
js_closure_call_apply_with_spread(box, this, ..). js_closure_call1_receiverless
is gone; V8's receiverless trampoline gets its own adapter,
js_closure_v8_callback(env, args, len). `DirectCallN::call` takes the
receiver. The ext/UI/audio crates pass receivers instead of saving and
restoring the implicit-`this` cell themselves.

Stage-1 semantics are unchanged: bodies still read the implicit-`this` cell.
An entry handed a receiver other than the cell's value binds the cell to it
for the call (an ImplicitThisScope, which roots the displaced value), except
for an arrow callee; a receiver equal to the cell binds nothing. Runtime and
stdlib plain calls pass `plain_call_receiver()`, which in stage 1 is the
cell's current value, and codegen's plain closure calls pass the cell bits,
so plain calls keep running with whatever the cell holds.

check_js_body_call_funnel.py now also refuses an entry declaration without
the receiver, a closure registrar declared outside runtime/stdlib/perry-ffi,
and a perry-ffi registration function taking `*const u8`.

* perf: this-as-a-parameter stage 2 — bodies read their receiver parameter

A body that reads its dynamic `this` now reads its receiver parameter
instead of the thread-local implicit-`this` cell: function expressions and
object-literal methods store `%js_this` into their rooted entry `this` slot
(sloppy bodies apply OrdinaryCallBindThis once), top-level functions that
read `this` compile to `perry_fn_X$this` behind a receiver-less public
forwarder, `__perry_wrap_<method>` forwards its receiver, and the runtime's
native bodies read their `this` parameter.

The cell is still written by every caller, so this stage can be measured
on its own; stage 3 deletes it.

Instructions per call against stage 1 (LTO-off build, same host): an
object-literal method reading `this` 227 -> 143, an ES5 prototype method
217 -> 134, `forEach` with a `thisArg` 828 -> 744.

* perf: this-as-a-parameter stage 3 — delete the implicit-this cell

A body's `this` parameter is now the only way it learns its receiver, so no
caller saves, sets or restores an ambient `this` around a call.

- Deleted: the per-agent IMPLICIT_THIS cell, js_implicit_this_get /
  _get_sloppy / _set, ImplicitThisScope, its exception savepoint, its HotTls
  field and agent-pointer slot, the codegen save/restore funnel
  (rooting::implicit_this_*), and the stage-1 witness (PERRY_THIS_WITNESS).
- The receiver-taking entries (js_closure_call{N}, js_native_call_value,
  js_closure_call_array, js_closure_call_apply_with_spread) pass their
  receiver and bind nothing; a plain call passes undefined
  (plain_call_receiver()).
- Every runtime, stdlib and ext route that carried a receiver through the
  cell passes it: listeners get their emitter, util.promisify / callbackify /
  deprecate call the original with the wrapper's receiver, the legacy
  Intl.NumberFormat / DateTimeFormat chain sees its receiver, N-API
  napi_call_function passes recv. An accessor on an arguments object now
  runs with it as `this` (it never had it).
- Async and generator function expressions bind their receiver at entry;
  module top-level `this` is undefined (strict) / globalThis (sloppy).
- A method's entry-resolved callback target
  (js_closure_resolve_plain_direct_call) admits ordinary functions too.

Instructions per call (LTO-off build, same host), main -> this change:
closure value call 145 -> 46, two-argument closure call 160 -> 59,
object-literal method-site hit 99 -> 79, object-literal method reading
`this` 223 -> 120, ES5 prototype method 214 -> 110.

* refactor(runtime): split child_process reactor exec/execFile path into its own module

reactor.rs was 2010 lines, over the 2000-line cap enforced by
scripts/check_file_size.sh. Move the async exec/execFile section
(cp_exec_async, cp_exec_accumulate, cp_exec_fire_close,
cp_defer_exec_callback, cp_exec_cb_thunk) into a sibling
reactor/exec_async.rs, the same way stdin.rs and streams.rs were
already split out of this file. Pure code move, no behavior change.

* test(codegen): update export alias identity test for the this-as-a-parameter wrapper ABI

The this-as-a-parameter ABI now passes the JS receiver as a second
i64 parameter (i64 %this_closure, i64 %js_this) into every installed
body, so the wrapper's forwarding call must include %js_this
alongside %this_closure. Update the expected call shape; the test
still asserts what it always asserted -- function identity through
the $-export alias resolves by ID, not by the exported spelling.

* changelog: name the fragments after PR #11637

* fix(runtime): the WASI closure-arity signature probe is missing the receiver parameter

perry_wasi_sig.c ref.test candidate types (double (closure, f64 x k)) predate this-as-a-parameter: every real JS body now takes (closure, this: u64, f64 x k) on wasm32. None of the candidates ever match any more, so wasi_body_params always returns None and dispatch falls back to the caller arity instead of the body real one, under-supplying a body that declares more parameters than its call site -- an indirect-call type mismatch that traps under wasmtime (repro: scripts/wasi_smoke iterators.ts, gen().map(fn) through the shared IteratorPrototype[Symbol.iterator] thunk). Add the missing unsigned long long receiver parameter to every perry_body_N candidate typedef and update the doc comment.

* gc_effects: regenerate tables for the this-as-a-parameter body ABI

* perf: a function object points to its body's static JsFunctionInfo; delete the closure-body registry

Every JS function body has ONE static, immutable `JsFunctionInfo`
(perry-abi): its code address, the parameter count a caller pads to, the
rest kind and its fixed prefix, `.length` and its declared fallback, the
arrow / strict / async / generator / built-in bits, and the compiler-private
trusted-direct and versioned-loop clones. The function object's header word
at +8 points to it, so every per-body fact is one load from the object and
nothing is looked up by code address.

- Codegen emits `@<body>$info` as a constant next to each body, and every
  allocation names the info. Another module's info is declared `external`,
  never copied, so a body has one info and one singleton function object.
- Runtime natives and perry-ffi addons define the info as a `static` from
  the body's TYPED pointer (`fn_info!` in the runtime and stdlib,
  `perry_ffi::js_function_info!` in addons): the parameter count comes from
  the body's type, and any other signature does not compile.
- Deleted: CLOSURE_BODY_REGISTRY, TRUSTED_TARGETS, DISPATCH_RECENT, the
  twelve `js_register_closure_*` entries with their call sites, and every
  module-init registration call. A class constructor's rest position travels
  with its class constructor flags.
- perry-ffi 0.6: `alloc_closure` takes `&'static JsFunctionInfo`;
  `register_closure_arity` / `register_closure_rest` are gone.
- `ClosureHeader::code()` proves the cell is a live function object before
  it loads through the info: comparing an arbitrary receiver's code with a
  known body stays a compare.
- WASI: the `ref.test` body-signature probe (ffi/perry_wasi_sig.c and its
  build step) is deleted. The info's parameter count is the body's real
  one, so dispatch no longer infers it from the table entry's wasm type.
- check_js_body_call_funnel.py refuses any registrar or deleted code-keyed
  table name in the crates. The GC holder / registry-lifetime inventories
  drop the entries for the deleted registration flags and tables, and the
  PASS1_MARKED census pin is re-audited for the removed census row.
- test-files/test_gap_fn_info_facts.ts reads each info field through
  generic calls, against node.

Layout: the info pointer replaces the code pointer at +8 (one dependent
load on a generic indirect call through the runtime; the method-site hit
caches code and is unchanged).

* changelog: name the fragment after #11654

* gc_runtime_root_holders: drop the CP_NEXT_LIVE_ID entry the exec split made stale

Moving cp_exec_async into reactor/exec_async.rs took the only allocating
function that names CP_NEXT_LIVE_ID out of reactor.rs, so rule B no longer
makes the counter a candidate in its declaring file and the inventory entry
matches no holder. The static is still a scalar AtomicU64 id counter; the
ChildProcess values it keys live in CP_LIVE, which cp_reactor_scan_roots_mut
visits.

* perf(runtime): runtime value calls go through js_native_call_value, not an inlined dispatcher

native_call_value_this was #[inline(always)] over the whole value-call
dispatcher, and the this-as-a-parameter funnel routes ~130 runtime callers
through it, so every one of them carried its own copy (Function.prototype
call/apply thunks, forEach/replace callbacks, each arm_trap_and_run closure).
It grew every linked program by ~190 KB on linux-x64 (loop fixture
7,563,048 -> 7,755,560 stripped).

The dispatcher body now lives only in the two js_native_call_value
definitions; native_call_value_this is a thin call to the export. loop is
7,497,512 with this change, below main.

* fix(runtime): reach the stream subclass-init shim through the stream install

736782e made Function.prototype.call/.apply run the node:stream
subclass-init shim for Readable.call(this, opts) by calling
js_node_stream_*_subclass_init directly. That path is linked into every
program, so it pinned all of node_stream (and the promise, timer and
process-stream code behind it) into programs that never import stream:
+554 KB stripped on the linux-x64 loop fixture (7,009,384 -> 7,563,048),
and the darwin-arm64 small-program budget over by 6-10%.

The shim is now registered by js_nm_install_stream, which codegen emits only
when a program imports stream; a stream base callee cannot exist otherwise.
The store is black_boxed like js_nm_enable_install_all, since the slot has a
single writer and whole-program optimization otherwise devirtualizes the load
back into a direct call. The dynamic super() path shares the same entry.

loop fixture: 7,497,512 -> 6,952,040 stripped. The #10448/#10449/#10454/
#10544/#10798 and stdio-writable gap tests still match node.

* fix(runtime): stream subclass-init slot: no unused mut, thread-exit verdict

nm_stream_subclass_init reassigned its load only under cfg(test), so a
non-test build saw an unused `mut` and failed the -D warnings job. Shadow
the binding in the test-only branch instead.

NM_STREAM_SUBCLASS_INIT holds only the node_stream_subclass_init fn
pointer (its one store is in js_nm_install_stream): a code address, never
an arena address. Record that no_heap_address verdict for the #11471
thread-exit custody gate, like its NM_CTOR/NM_ATTACH sibling registries.

* gc_runtime_root_holders: keep the stage-3 re-audit note the merge dropped

The PASS1_MARKED entry's audit trail took main's side in the merge and
lost this branch's note for the implicit-this scanner registration
(`scan_dispatch_binding_roots_mut`). Restore it after main's notes.

---------

Co-authored-by: Ralph Küpper <ralph3@skelpo.com>
proggeramlug pushed a commit that referenced this pull request Sep 29, 2026
Resolve scripts/gc_runtime_root_holders.json by taking main's PASS1_MARKED
text, re-appending this branch's #11549 audit note, and pinning
gc/policy.rs to the merged file (it differs from main only by this
branch's audited hunks).

Port own_override_builtin_install_tests to main's #11654 closure ABI:
js_closure_alloc now takes a static JsFunctionInfo, and bodies take the
#11637 receiver parameter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-extended-tests Opt PR into compile-smoke/parity/doc-tests/drizzle-mysql-smoke

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant