Skip to content

perf(runtime): gate property-tail registry probes by receiver header - #7897

Merged
proggeramlug merged 2 commits into
mainfrom
perf/7867-header-gated-property-tail
Aug 12, 2026
Merged

perf(runtime): gate property-tail registry probes by receiver header#7897
proggeramlug merged 2 commits into
mainfrom
perf/7867-header-gated-property-tail

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • screen Symbol candidates with SYMBOL_MAGIC before consulting the process-global registry
  • read the receiver's existing GcHeader once and consult SET_REGISTRY only for GC_TYPE_SET
  • outline the authoritative Symbol/Set dispatch into cold helpers so the ordinary IC-miss tail stays compact
  • add deterministic probe-counter coverage for ordinary objects, Sets, GC-backed Symbols, and Box-leaked Symbols

Reproduction

The issue's old pipeline_big attribution is stale on current main: a fresh debug-symbol sample contains zero is_registered_symbol_slow samples in either arm. The structural bug is still reproducible without timing noise, though. With both registry latches armed, the new plain-object miss test fails before this change because SET_REGISTRY moves from 801 to 803; after the change neither Set nor Symbol probe counters move. The companion test sabotages the Symbol magic screen after dispatch and verifies that Set plus both Symbol storage classes still use their authoritative registries.

Performance

An initial inline version grew get_field_by_name_object_tail by 40 bytes and regressed pipeline_big by +4.636% paired geomean (30 alternating quiet-M1-mini pairs, 95% CI +4.589% to +4.681%). That version was rejected.

The final reviewed version moves the cold registered-receiver bodies out of line. Against the same base compiler/runtime and correctness oracle, 30 alternating pairs on the locked quiet M1 mini measured:

  • base median: 1.693756 s
  • fix median: 1.688867 s
  • paired geomean: -0.343%
  • bootstrap 95% CI: -0.389% to -0.299%
  • both arms: exit 0, exact output 556260000 3 3

Validation

  • RUST_TEST_THREADS=1 cargo test -p perry-runtime get_field_by_name_probe_tests (2 passed)
  • RUST_TEST_THREADS=1 cargo test -p perry-runtime (2,154 passed, 4 ignored; doc tests 6 ignored)
  • python3 scripts/check_test_registration.py
  • python3 scripts/check_thread_locals.py
  • python3 scripts/addr_class_inventory.py
  • cargo fmt --check
  • git diff --check
  • bash scripts/check_file_size.sh

Review coverage also rejects an implausible upper-bound receiver before reading SYMBOL_MAGIC and proves an unknown Set key falls through to a data property installed on Set.prototype instead of being swallowed as undefined.

The address-class audit passes and also reports the pre-existing stale dyn_index.rs ratchet entry (baseline 2, found 1); this PR does not broaden into that adjacent cleanup.

Closes #7867

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The property-get miss path now gates Symbol and Set registry probes. Cold dispatch helpers preserve Symbol and Set property behavior. Tests cover probe suppression, positive dispatch, headerless Symbols, and GC-allocated Symbols.

Changes

Property miss dispatch

Layer / File(s) Summary
Cold Symbol and Set probe helpers
crates/perry-runtime/src/object/field_get_set/probe_dispatch.rs
Adds cold helpers for Symbol descriptions and Set size, methods, expandos, and fallback results.
Header-gated miss-path integration
crates/perry-runtime/src/object/field_get_set/get_field_by_name_tail.rs, crates/perry-runtime/src/object/field_get_set.rs
Checks Symbol header magic before registry lookup and dispatches Set properties only after GC_TYPE_SET validation.
Probe ordering and regression validation
crates/perry-runtime/src/object/field_get_set/get_field_by_name_probe_tests.rs, scripts/addr_class_ratchet_baseline.txt, changelog.d/7897-header-gated-property-tail.md
Adds probe-counter and positive-path tests and records the baseline and performance results.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: performance

Suggested reviewers: thehypnoo

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the performance change: gating property-tail registry probes by the receiver header.
Description check ✅ Passed The description covers the change, issue, performance data, implementation details, and validation, although it uses non-template section names.
Linked Issues check ✅ Passed The implementation satisfies issue #7867 by gating Set and Symbol probes, preserving headerless handling, and adding correctness coverage.
Out of Scope Changes check ✅ Passed The changes remain within issue #7867 scope, including implementation, focused tests, changelog documentation, and the required baseline update.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/7867-header-gated-property-tail

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 August 12, 2026 01:41

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
crates/perry-runtime/src/object/field_get_set/probe_dispatch.rs (1)

18-23: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the canonical pointer NaN-boxing helper.

Line 19 duplicates the pointer tag as 0x7FFD. Use crate::value::js_nanbox_pointer(obj as i64) instead. This keeps the Symbol receiver aligned with the canonical POINTER_TAG encoding.

Proposed fix
-        let sym_f64 =
-            f64::from_bits(0x7FFD_0000_0000_0000u64 | (obj as u64 & 0x0000_FFFF_FFFF_FFFF));
+        let sym_f64 = crate::value::js_nanbox_pointer(obj as i64);

As per coding guidelines, “objects/pointers use POINTER_TAG; preserve raw bits with f64::from_bits, not numeric as f64 conversion.”

🤖 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/object/field_get_set/probe_dispatch.rs` around lines
18 - 23, Update the Symbol receiver setup in the field probe dispatch to use
crate::value::js_nanbox_pointer(obj as i64) instead of manually constructing the
0x7FFD NaN-boxed bits. Preserve the resulting raw-bit handling when passing the
value to js_symbol_description.

Source: Coding guidelines

🤖 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/object/field_get_set/get_field_by_name_tail.rs`:
- Around line 454-464: Update the symbol check around may_be_symbol_header to
first validate obj with is_plausible_heap_addr, then perform the SYMBOL_MAGIC
read and registry lookup. Preserve support for both GC-backed and Box-leaked
Symbols by using the plausibility predicate rather than requiring a GC header.

In `@crates/perry-runtime/src/object/field_get_set/probe_dispatch.rs`:
- Around line 42-79: Update the Set property probe around the registered-key
handling so unknown Set keys return None rather than Some(undefined), allowing
map_set_instance_property to continue prototype and instance-property lookup.
Preserve the existing size, known-method, and exotic-expando behavior while
changing only the final fallback for unrecognized keys.

---

Nitpick comments:
In `@crates/perry-runtime/src/object/field_get_set/probe_dispatch.rs`:
- Around line 18-23: Update the Symbol receiver setup in the field probe
dispatch to use crate::value::js_nanbox_pointer(obj as i64) instead of manually
constructing the 0x7FFD NaN-boxed bits. Preserve the resulting raw-bit handling
when passing the value to js_symbol_description.
🪄 Autofix

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: 33c5bc46-8992-4b55-af79-aba7c5c036ce

📥 Commits

Reviewing files that changed from the base of the PR and between 5b3dc14 and 7619696.

📒 Files selected for processing (6)
  • changelog.d/7897-header-gated-property-tail.md
  • crates/perry-runtime/src/object/field_get_set.rs
  • crates/perry-runtime/src/object/field_get_set/get_field_by_name_probe_tests.rs
  • crates/perry-runtime/src/object/field_get_set/get_field_by_name_tail.rs
  • crates/perry-runtime/src/object/field_get_set/probe_dispatch.rs
  • scripts/addr_class_ratchet_baseline.txt

Comment thread crates/perry-runtime/src/object/field_get_set/probe_dispatch.rs
@proggeramlug
proggeramlug merged commit 6094b0e into main Aug 12, 2026
1 of 19 checks passed
@proggeramlug
proggeramlug deleted the perf/7867-header-gated-property-tail branch August 12, 2026 02:01
@proggeramlug

Copy link
Copy Markdown
Contributor Author

Also applied the review nit: Symbol receiver construction now uses the canonical js_nanbox_pointer helper. The exact reviewed binary was rebuilt and remeasured on the locked quiet M1 mini: 30 alternating pairs, -0.343% paired geomean (95% CI -0.389% to -0.299%), exact oracle output in both arms. The PR body and changelog now carry these final numbers.

@proggeramlug

Copy link
Copy Markdown
Contributor Author

Because #7897 merged while these review fixes were being rebuilt and measured, the fixes could not enter the merged commit. They are now isolated in follow-up #7898 with the failing-before prototype regression, implausible-address guard coverage, full runtime validation, and the final quiet-mini A/B.

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

Labels

None yet

Projects

None yet

1 participant