perf(runtime): reuse stable one-key for-in snapshots - #8710
Merged
Conversation
Lands #8709. Routes compiled `ForInKeys` through `js_for_in_keys_stable_value` and reuses the immutable shape-owned key snapshot when the receiver, key, descriptors and %Object.prototype% generation prove the result exact, keeping the complete generic enumerator for every proof miss. The reuse guard was checked rather than assumed. `PrototypeSignature` carries a raw `prototype_addr`, which is the shape that went stale in #8393 -- but this is not that shape. The signature is recomputed live on every call from `object_prototype_addr()`, with `try_read_gc_header` validation and an explicit `GC_FLAG_FORWARDED` rejection, and the cached verdict is consulted only when the freshly-read signature compares equal in all three fields. The cached address is never dereferenced, so a moved prototype produces a mismatch and a cold recompute rather than a false hit. Descriptor, key and prototype mutations mint a new ShapeId, and class-level changes move `vtable_generation`. `PROTOTYPE_VERDICT` is a new rule-T holder, pinned on the inventory frontier alongside the other identity-ratcheted thread-locals. No version bump.
13 tasks
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughCompiled ChangesStable for-in enumeration
Estimated code review effort: 4 (Complex) | ~45 minutes Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant CompiledForIn
participant js_for_in_keys_stable_value
participant PrototypeVerdictCache
participant js_for_in_keys_value
CompiledForIn->>js_for_in_keys_stable_value: submit object value
js_for_in_keys_stable_value->>PrototypeVerdictCache: check prototype signature
PrototypeVerdictCache-->>js_for_in_keys_stable_value: return cached or validated verdict
js_for_in_keys_stable_value-->>CompiledForIn: return stable key snapshot
js_for_in_keys_stable_value->>js_for_in_keys_value: handle validation miss
js_for_in_keys_value-->>CompiledForIn: return generic enumeration keys
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands #8709. (#8707 is held — see below.)
Routes compiled
ForInKeysthroughjs_for_in_keys_stable_value, reusing the immutable shape-owned key snapshot when the receiver, key, descriptors and%Object.prototype%generation prove the result exact, with the complete generic enumerator kept for every proof miss.The reuse guard
PrototypeSignaturecarries a rawprototype_addr, which is exactly the shape that went stale in #8393 — so that's what I checked. It is not that shape. The signature is recomputed live on every call fromobject_prototype_addr(), withtry_read_gc_headervalidation and an explicitGC_FLAG_FORWARDEDrejection:The cached verdict is consulted only when that freshly-read signature compares equal in all three fields, and the cached address is never dereferenced — so a moved prototype yields a mismatch and a cold recompute, not a false hit. Descriptor, key and prototype mutations mint a new ShapeId; class-level changes move
vtable_generation.PROTOTYPE_VERDICTis a new rule-T holder and is pinned on the inventory frontier alongside the other identity-ratcheted thread-locals.Validation
lint-job checkers passperry-runtime --lib(RUST_TEST_THREADS=1): 2655 passed, 0 failedperry-codegen --lib: 1214 passed, 0 failedperry-transform --lib: 87 passed, 0 failedissue_8694_stable_for_inacceptance test: 1 passedThat last one initially failed, and the cause is worth recording:
cargo test -p perry --test <suite>links a stalelibperry_{runtime,stdlib}.aunless the-staticwrapper crates are rebuilt first. Aftercargo build -p perry -p perry-runtime-static -p perry-stdlib-staticwithPERRY_RUNTIME_DIRpinned, it passes. The failure was the harness, not the change.Why #8707 is not in this batch
#8707 fixes a real and serious bug —
awaitinside acatchcompiling to a blocking busy-wait that deadlocks the single runtime thread. But its own new testasync_generator_linearizes_every_await_positionfails once rebased onto currentmain:It passes on #8707's own head, so this is an interaction with
main, not a defect in the PR as written. Both the test and itsawait-in-finallycase are new in #8707 — neither exists onmainor at #8707's merge base — so the PR is catching a genuine remaining gap rather than regressing anything. Resolving it means knowing whetherfinallyshould route throughcatch_entry_statethe same waycatchnow does, which is the author's call, not mine to guess at.It also needs a
changelog.d/fragment and a trivialsource_order: 0field on theClassComputedMembertest fixture atasync_to_generator.rs:2196(the field landed onmainwith #8645).Summary by CodeRabbit
Performance
for...inloops for ordinary objects with stable keys, reducing repeated enumeration overhead.Testing
Documentation
for...inperformance improvement.