Skip to content

diag(runtime): receiver-representation ledger — per-family headerless-receiver counters and a typed native-result classification replacing NR_PTR (371 rows, 0 unknown) - #9973

Closed
proggeramlug wants to merge 2 commits into
PerryTS:mainfrom
proggeramlug:perf/receiver-repr-ledger

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

First PR of the receiver-representation campaign (design: cc-perf-campaign/DESIGN_receiver_representation.md in the campaign repo). Measurement and metadata only — no JS-visible representation, release-path classifier, wrapper, or native-result boxing changes. Written by codex (0.154.0-alpha.3); all gates run locally.

Why

On the best cc bundle the receiver family — try_read_tracked_gc_header 2.46 % self, js_native_call_method_at_site 2.90, dispatch_primitive 1.79, plus the Buffer/typed-array registry residue — is ≈ 9.9 % of main-thread samples. The audit (REPORT_trust_the_tag.md) showed the direct-header read cannot replace the ownership check while seven headerless POINTER_TAG families exist (integer registry ids, AsyncHook/AsyncResource boxes, leaked global symbols, external buffers, SAB backing, the null stub, bare managed addresses). Before any of them is migrated, the campaign needs (a) counts per family on a real cc reply and (b) an executable classification of every native pointer result so a wrapper migration cannot miss a producer.

What changes

  • PERRY_RECEIVER_REPR_DIAG=<sink> (hot_diag sink, SIGKILL-safe snapshot): one line [receiver-repr-diag] constructed common= fetch= zlib= proxy= timer= text= tui= async_hook= async_resource= symbol_global= external_buffer= sab= null_stub=; observed_old …; observed_wrapped …; bare_managed= invalid_pointer_zero= direct_mismatch=. Producers bump their family at the constructors (common/fetch/zlib registries, proxy, timers, text, TUI, async hooks/resources, global symbols, external buffer, SAB, null stub — file:line in the campaign report); the five dynamic-receiver funnels (gc_pointer_and_type_from_value, dispatch_primitive, object_static_prototype, the field tail, ic_miss) classify only while armed. Every guard is one relaxed atomic load when off; direct_mismatch's header probe is debug_assertions-only.
  • Typed native-result ledger. The erased NR_PTR result kind is replaced by NR_GCPTR (131 rows), NR_NULLABLE_GCPTR (2), NR_HANDLE_ID (221), NR_FOREIGN_PTR (4: AsyncHook/AsyncResource backing), NR_JS_VALUE (13) — 371 executable declarations (the audit's "372" counted two prose comments and missed one helper row), all materialised through the same native_handle branch as before (byte-identical lowering). scripts/native_result_ledger.tsv records 322 runtime symbols with class, provider source and Rust return type (the design's 81 unresolved rows: 81/81 resolved); scripts/native_result_ledger.py fails on any remaining NR_PTR, any table/provider class disagreement, or a stale provider entry, with a --self-test; a path-filtered CI workflow runs it.

Tests (named; sabotage performed)

receiver_repr_family_fixtures_move_constructed_and_observed_old (each family's constructed > 0, observed_old > 0, observed_wrapped == 0), receiver_repr_every_family_producer_keeps_its_constructed_bump (pins the bump-site count per producer file; sabotage: one family token changed → left: 1, right: 2), receiver_repr_unarmed_funnels_never_enter_classification (test-only entry counter stays zero with the sink off; sabotage: drop a guard → nonzero), native_result_ledger.py --self-test (a planted NR_PTR row and a planted class disagreement are both rejected).

Gates (local, macOS arm64)

Runtime release lib suite 3,262 passed / 0 failed; codegen tests 1,450 passed; cargo build --release -p perry-runtime --features wasm-host and cargo build --release -p perry ok; root-holder and thread-local inventories ok; rustfmt, diff-check, file-size ok.

Next

perrymaster runs one 3300-char cc reply with the diag on the best bundle (stage RL): the ledger line prices PR 2 (wrapper creations per reply) and names which headerless families actually reach a dynamic receiver on cc. Per the design, the campaign's early kill (a forced-invariant synthetic A/B) runs before any wrapper migration.

Measured (perrymaster RL, 2026-09-08; main6 bundle relinked against this runtime and stdlib, one 3300-char cc reply, PERRY_RECEIVER_REPR_DIAG=stderr)

constructed common=11 fetch=20 zlib=0 proxy=0 timer=137 text=15 tui=0 async_hook=0 async_resource=0 symbol_global=55 external_buffer=0 sab=0 null_stub=0; observed_old common=4974 fetch=63 timer=4966 text=4949 symbol_global=148 (others 0); observed_wrapped all 0; bare_managed=0; invalid_pointer_zero=0; direct_mismatch=0. Exactly five families reach a dynamic receiver on cc (timers, global symbols, fetch handles, text handles, the common pool); eight never do. 238 constructions per reply price the next PR's wrappers as negligible. The ~4.9 k observed_old counts shared by common/timer/text are the same small-integer payloads claimed by each overlapping range, as the report predicts.

https://claude.ai/code/session_011dhBmdn4vGgNibjo3oZqTo

Instrument headerless receiver producers and dynamic receiver funnels behind
the opt-in PERRY_RECEIVER_REPR_DIAG sink. Add explicit native return storage
kinds while retaining the existing pointer-boxing lowering, plus checked
provider inventory and fail-capable fixtures.

Claude-Session: https://claude.ai/code/session_011dhBmdn4vGgNibjo3oZqTo
Record the producer map, corrected executable-row census, sabotage proofs,
gate results, and the perrymaster measurement request for campaign PR 1.

Claude-Session: https://claude.ai/code/session_011dhBmdn4vGgNibjo3oZqTo
@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 59 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 8 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 8df01816-cd03-4a4c-aa8b-da19986e805a

📥 Commits

Reviewing files that changed from the base of the PR and between 43200e9 and ecbfba3.

⛔ Files ignored due to path filters (1)
  • scripts/native_result_ledger.tsv is excluded by !**/*.tsv
📒 Files selected for processing (54)
  • .github/workflows/native-result-ledger.yml
  • cc-perf-campaign/codex/REPORT_receiver_repr_ledger.md
  • crates/perry-codegen/src/lib.rs
  • crates/perry-codegen/src/lower_call/native_module_dispatch.rs
  • crates/perry-codegen/src/lower_call/native_table/async_decimal.rs
  • crates/perry-codegen/src/lower_call/native_table/bun.rs
  • crates/perry-codegen/src/lower_call/native_table/databases.rs
  • crates/perry-codegen/src/lower_call/native_table/extras.rs
  • crates/perry-codegen/src/lower_call/native_table/fastify.rs
  • crates/perry-codegen/src/lower_call/native_table/http_client.rs
  • crates/perry-codegen/src/lower_call/native_table/http_http2.rs
  • crates/perry-codegen/src/lower_call/native_table/http_server.rs
  • crates/perry-codegen/src/lower_call/native_table/media.rs
  • crates/perry-codegen/src/lower_call/native_table/mod.rs
  • crates/perry-codegen/src/lower_call/native_table/net_classes_state.rs
  • crates/perry-codegen/src/lower_call/native_table/net_events.rs
  • crates/perry-codegen/src/lower_call/native_table/node_core/dgram_fs_os.rs
  • crates/perry-codegen/src/lower_call/native_table/node_core/util_buffer.rs
  • crates/perry-codegen/src/lower_call/native_table/node_core_process.rs
  • crates/perry-codegen/src/lower_call/native_table/node_domain.rs
  • crates/perry-codegen/src/lower_call/native_table/node_misc.rs
  • crates/perry-codegen/src/lower_call/native_table/thread_lodash.rs
  • crates/perry-codegen/src/lower_call/native_table/tls_events.rs
  • crates/perry-codegen/src/lower_call/native_table/tui.rs
  • crates/perry-codegen/src/lower_call/native_table/undici.rs
  • crates/perry-codegen/src/lower_call/native_table/utils_crypto.rs
  • crates/perry-codegen/src/lower_call/native_table/ws_events.rs
  • crates/perry-runtime/src/async_hooks.rs
  • crates/perry-runtime/src/buffer/header.rs
  • crates/perry-runtime/src/buffer/mod.rs
  • crates/perry-runtime/src/hot_diag.rs
  • crates/perry-runtime/src/hot_diag/receiver_repr.rs
  • crates/perry-runtime/src/object/field_get_set/get_field_by_name_tail.rs
  • crates/perry-runtime/src/object/field_get_set/ic_miss.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/primitive_methods.rs
  • crates/perry-runtime/src/object/null_stub.rs
  • crates/perry-runtime/src/object/prototype_chain.rs
  • crates/perry-runtime/src/proxy.rs
  • crates/perry-runtime/src/shared_sab.rs
  • crates/perry-runtime/src/symbol.rs
  • crates/perry-runtime/src/symbol/constructors.rs
  • crates/perry-runtime/src/text.rs
  • crates/perry-runtime/src/timer.rs
  • crates/perry-runtime/src/tui/hooks.rs
  • crates/perry-runtime/src/tui/mod.rs
  • crates/perry-runtime/src/tui/state.rs
  • crates/perry-runtime/src/tui/tree.rs
  • crates/perry-runtime/src/value/addr_class.rs
  • crates/perry-stdlib/src/common/handle.rs
  • crates/perry-stdlib/src/fetch/mod.rs
  • crates/perry-stdlib/src/zlib.rs
  • scripts/native_result_ledger.py

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 marked this pull request as ready for review September 7, 2026 20:45
proggeramlug pushed a commit that referenced this pull request Sep 7, 2026
#9969 makes run_lint_gates.sh derive every command of every run: step (80
now, up from 67). Two of the newly-run gates were red on this train:

- addr_class_inventory rejected #9973's two GcHeader casts in
  hot_diag/receiver_repr.rs. Both are allowlisted with reasons rather
  than converted: the block is a #[cfg(debug_assertions)] trust-the-tag
  audit that compares the ownership-derived header against a direct
  byte-offset read and counts disagreements. Routing the raw side through
  try_read_gc_header would validate the address first and return None for
  exactly the implausible cases the audit exists to catch, so the
  canonical predicate cannot stand in there.

- RUSTFLAGS="-D warnings" cargo check --workspace --all-targets rejected
  #9861's doc comment on a thread_local! macro invocation, which cannot
  carry one. Moved inside the macro onto the static it describes. This is
  a warning, not an error, so it only fails under -D warnings — which the
  driver never replayed before #9969.
@proggeramlug

Copy link
Copy Markdown
Contributor Author

Landed on main via merge train #9978. Validated as a tree: 77 of 80 lint gates pass, and perry-runtime/codegen/hir/stdlib all green (5,980 tests, 0 failures).

The three non-passing gates are accounted for: public-baseline is pre-existing on main (verified on a pristine worktree; red since 2026-07-29), and the two API docs gates are an artifact of this session's CARGO_TARGET_DIR override — regen_api_docs.sh hardcodes $ROOT/target/release/perry. With the binary placed where the script expects, regeneration succeeds and the drift check is clean. Thanks!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant