Skip to content

perf(runtime): gate dynamic-index collection probes by GcHeader (#7865) - #7880

Merged
proggeramlug merged 4 commits into
mainfrom
perf/7865-dyn-index-header-gates
Aug 11, 2026
Merged

perf(runtime): gate dynamic-index collection probes by GcHeader (#7865)#7880
proggeramlug merged 4 commits into
mainfrom
perf/7865-dyn-index-header-gates

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • read the dynamic-index receiver's already-required GC header after the header-less TypedArray and Buffer routes
  • use its object type to select at most one of the Map/Set registries; registration remains the authoritative ownership check
  • add dedicated probe counters and regressions proving ordinary arrays touch neither registry while Map and Set operations reach exactly their own registry

Reproduction

With both collection registries armed, the regression test failed before the implementation because three plain-array dynamic index operations moved the Map/Set probe counts from (0, 0) to (3, 3). It passes with both counters unchanged after the header gate.

Validation

  • RUST_TEST_THREADS=1 cargo test -p perry-runtime --lib: 2,127 passed, 4 ignored, 0 failed
  • focused collection-tag filter: 8 passed, including both new dynamic-index tests
  • address-classification audit: 1,037 files, 279 allowlisted, 547 ratcheted sites
  • test-registration audit: 195 files across 4 registries
  • formatting, diff whitespace, and file-size gates pass
  • baseline/fixed compilers were linked against distinct matching runtime archives; both outputs matched Node.js v26.5.1 byte-for-byte

Performance

Quiet M1 mini, lock held, alternating A/B order:

  • amplified bench/interp.ts, 7 pairs and 3 executions per cell: baseline 3.32 s wall / 3.30 s user; fix 3.31 s / 3.29 s (about -0.3%, within noise)
  • targeted 20-million-iteration dynamic get/set workload, 7 pairs and 10 executions per cell: both arms exactly 2.60 s wall / 2.57 s user

This PR claims the structurally eliminated registry lookups and regression coverage, not a measurable wall-clock speedup.

Closes #7865

Summary by CodeRabbit

  • Bug Fixes

    • Improved dynamic indexing for arrays, maps, and sets by selecting the correct collection type before lookup.
    • Prevented unnecessary registry checks for array access, improving consistency and performance.
    • Ensured map and set operations use the appropriate registries.
    • Safely rejected invalid legacy receivers before accessing collection metadata.
  • Tests

    • Added coverage for collection dispatch, registry probing, and invalid receiver handling.
  • Documentation

    • Added changelog notes covering dynamic-indexing improvements and benchmark observations.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6677f0e7-30f4-4164-80ae-722a71c9508b

📥 Commits

Reviewing files that changed from the base of the PR and between 1357b87 and cc763d5.

📒 Files selected for processing (2)
  • crates/perry-runtime/src/value/dyn_index.rs
  • crates/perry-runtime/src/value/dyn_index_collection_tag_tests.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/perry-runtime/src/value/dyn_index_collection_tag_tests.rs

📝 Walkthrough

Walkthrough

Dynamic index reads and writes use receiver GC metadata to select Map or Set registry probes. Raw-I64 receivers undergo managed-membership validation before header access. Tests verify array bypass, registry selection, and rejection of unmapped receivers.

Changes

Dynamic index dispatch

Layer / File(s) Summary
GC-tagged collection dispatch
crates/perry-runtime/src/value/dyn_index.rs
Dynamic get and set operations select the matching Map or Set registry from the receiver GC tag. Raw-I64 receivers are validated before header access. Cached metadata determines array dispatch.
Probe regression coverage
crates/perry-runtime/src/value/dyn_index.rs, crates/perry-runtime/src/value/dyn_index_collection_tag_tests.rs, changelog.d/7880-dyn-index-header-gates.md
Test-only counters and tests verify array bypass behavior, Map/Set registry selection, and rejection of unmapped raw-I64 receivers. The changelog records benchmark observations.

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

Sequence Diagram(s)

sequenceDiagram
  participant DynIndex
  participant GCMetadata
  participant CollectionRegistry
  DynIndex->>GCMetadata: Validate receiver and read GC tag
  GCMetadata-->>DynIndex: Receiver GC tag and flags
  DynIndex->>CollectionRegistry: Probe matching Map or Set registry
  CollectionRegistry-->>DynIndex: Confirm collection ownership
Loading

Possibly related PRs

  • PerryTS/perry#7765: Both changes use GC-tag-based Map/Set receiver gating and registry-probe suppression.
  • PerryTS/perry#7868: Both changes use GC-header type information to select the appropriate registry probe.

Suggested reviewers: thehypnoo

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main runtime change: gating dynamic-index collection probes by the GC header.
Description check ✅ Passed The description explains the change, linked issue, validation results, regression coverage, and performance findings, although it does not use every template heading.
Linked Issues check ✅ Passed The implementation addresses issue #7865 by gating Map and Set probes with GC-header classification while preserving safe pointer validation and adding regression coverage.
Out of Scope Changes check ✅ Passed The changelog entry, runtime changes, counters, and tests all support the linked issue objectives without unrelated code changes.
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/7865-dyn-index-header-gates

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.

@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: 1

🤖 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/value/dyn_index.rs`:
- Around line 594-597: Move the raw-pointer validity check in js_dyn_index_set
ahead of the receiver_gc_tag call, rejecting unmapped legacy raw-I64 addresses
before any GC-header read. Preserve the existing collection-tag handling after
validation.
🪄 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: 675fd78a-2e66-443b-9a1f-53c4703e05d4

📥 Commits

Reviewing files that changed from the base of the PR and between 9ca8b4f and 467f7e4.

📒 Files selected for processing (3)
  • changelog.d/7880-dyn-index-header-gates.md
  • crates/perry-runtime/src/value/dyn_index.rs
  • crates/perry-runtime/src/value/dyn_index_collection_tag_tests.rs

Comment thread crates/perry-runtime/src/value/dyn_index.rs

@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: 1

🤖 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/value/dyn_index_collection_tag_tests.rs`:
- Around line 61-81: Extend the test-only instrumentation in receiver_gc_tag
with a GC-header-read counter, incrementing it only when the header is actually
accessed. Update unmapped_legacy_raw_i64_is_rejected_before_the_gc_header_read
to invoke both js_dyn_index_get and js_dyn_index_set, while retaining the
probes() assertion and asserting the new counter remains zero after each
dispatch.
🪄 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: 75b630d8-7cac-4301-8723-64b0001702f3

📥 Commits

Reviewing files that changed from the base of the PR and between 467f7e4 and 1357b87.

📒 Files selected for processing (2)
  • crates/perry-runtime/src/value/dyn_index.rs
  • crates/perry-runtime/src/value/dyn_index_collection_tag_tests.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/perry-runtime/src/value/dyn_index.rs

Comment thread crates/perry-runtime/src/value/dyn_index_collection_tag_tests.rs
@proggeramlug
proggeramlug merged commit 5fa24a2 into main Aug 11, 2026
1 of 19 checks passed
@proggeramlug
proggeramlug deleted the perf/7865-dyn-index-header-gates branch August 11, 2026 20:57
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.

Every dynamic index read and write probes the Set and Map registries before reading the GcHeader that answers (~1% of interp)

1 participant