Skip to content

land #8783: deopt exact callbacks and captured updates - #8808

Merged
proggeramlug merged 6 commits into
mainfrom
merge/land-8783
Aug 25, 2026
Merged

land #8783: deopt exact callbacks and captured updates#8808
proggeramlug merged 6 commits into
mainfrom
merge/land-8783

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Lands #8783 (perf(codegen): deopt exact callbacks and captured updates).

Why this one needed more than the lint gates

#8783 adds a fourth early-return to emit_gc_loop_safepoint (stmt/loops.rs), suppressing the GC loop poll whenever the new VersionedIndexedGuardMode::CallbackDeopt is active. Suppressing loop polls is the #7690 shape, and it is guarded by gc-root-dominance.yml — a separate workflow that the lint job does not include, so a green lint run says nothing about it. The PR touches exactly the four files that gate exists for: gc_call_effects.rs, root_reload.rs, stmt/loops.rs, stmt/versioned_indexed_loop.rs (+152/-10).

Root-dominance A/B

Same corpus, same binary profile, clean tree on each side:

clean main (db821b5fd)   violations=7  distinct fingerprints=4
main + #8783             violations=7  distinct fingerprints=4
fingerprints only under #8783:  none

#8783 introduces no root-dominance violation. The 7 are pre-existing on main (see below).

The PR's own change to gc_call_effects.rs is test-side and tightens the invariant — it asserts that a guarded call-site marker must not make its containing function transitively leaf, i.e. the marker fails closed.

Fix applied while landing

gc_runtime_root_holders flagged the new CLOSURE_VERSIONED_LOOP_REGISTRY. Researched rather than pinned as debt: it maps a closure body func_ptr (a code pointer, never moved by the collector) to TrustedDirectTarget { func_ptr: *const u8, capture_count: u32, boxed_capture_mask: u64 } — every field is a code pointer or a plain integer, so no field can hold a heap pointer and the table cannot hold a GC root. Recorded as a not_a_gc_pointer verdict, not a frontier pin. Its sibling CLOSURE_ARROW_FUNCTION_REGISTRY, same value type in the same thread_local! block, is currently only frontier-pinned.

Validation

  • all 30 lint-job gates pass
  • perry-codegen 1246, perry-runtime 2687 — 0 failed
  • acceptance e2e versioned_indexed_loop_callback_deopt::cold_callback_arms_resume_once_at_the_next_index — passed (313 s)

Two pre-existing findings on main, filed separately from this PR

Both reproduce on clean main at db821b5fd, so neither blocks this:

  1. gc_root_dominance_check.py reports 7 violations / 4 fingerprints against an empty allowlistjs_closure_alloc -> js_object_set_field_by_name in test_gap_array_iterator_manual_next, test_gap_gc_method_receiver_rooting, test_gap_object_create_method_this, and js_object_alloc_class_inline_keys_stamped -> js_private_brand_add in test_gap_class_advanced.
  2. gc_root_dominance_corpus.sh reports 2 of 152 sources "failed to compile" against a budget of 0test_gap_gc_http2_pending_event_callback_rooting and test_gap_gc_net_once_flags_rekey. Both compile fine standalone (Wrote executable, IR emitted), so this is a corpus-harness discrepancy rather than a compiler regression.

Measured with a perry-dev binary; CI uses release, so the absolute numbers may differ there. The A/B is valid regardless — both arms used the identical profile and corpus.

Summary by CodeRabbit

  • New Features

    • Improved performance for eligible indexed loops using exact callback optimizations.
    • Supports simple additive callbacks and numeric increment/decrement updates.
    • Automatically resumes safely through fallback paths when callbacks encounter unsupported operations or runtime edge cases.
    • Improved garbage-collection handling for optimized callback execution.
  • Bug Fixes

    • Added safeguards for property misses, coercion, TDZ access, exceptions, and callback mismatches.
    • Ensured optimized callbacks fail safely when their exact requirements are not met.

@proggeramlug
proggeramlug merged commit 1db5a84 into main Aug 25, 2026
17 of 18 checks passed
@proggeramlug
proggeramlug deleted the merge/land-8783 branch August 25, 2026 08:52
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e323b606-8130-4b27-aaae-a7eb3b4ed9fe

📥 Commits

Reviewing files that changed from the base of the PR and between db821b5 and f5e1698.

📒 Files selected for processing (31)
  • changelog.d/8783-exact-callback-versioned-loops.md
  • crates/perry-codegen/src/block.rs
  • crates/perry-codegen/src/codegen/artifact_context.rs
  • crates/perry-codegen/src/codegen/artifacts.rs
  • crates/perry-codegen/src/codegen/closure.rs
  • crates/perry-codegen/src/codegen/closure_collect.rs
  • crates/perry-codegen/src/codegen/entry.rs
  • crates/perry-codegen/src/codegen/function.rs
  • crates/perry-codegen/src/codegen/index_method_clone_tests.rs
  • crates/perry-codegen/src/codegen/method.rs
  • crates/perry-codegen/src/codegen/mod.rs
  • crates/perry-codegen/src/codegen/string_pool.rs
  • crates/perry-codegen/src/codegen/trusted_box_callback_tests.rs
  • crates/perry-codegen/src/dialect/mod.rs
  • crates/perry-codegen/src/expr/binary.rs
  • crates/perry-codegen/src/expr/literals_vars.rs
  • crates/perry-codegen/src/expr/mod.rs
  • crates/perry-codegen/src/expr/property_get/generic_dispatch.rs
  • crates/perry-codegen/src/gc_call_effects.rs
  • crates/perry-codegen/src/inst.rs
  • crates/perry-codegen/src/lower_call/early_branches.rs
  • crates/perry-codegen/src/lower_call/property_get/dynamic_dispatch.rs
  • crates/perry-codegen/src/root_reload.rs
  • crates/perry-codegen/src/root_reload_tests.rs
  • crates/perry-codegen/src/runtime_decls/strings.rs
  • crates/perry-codegen/src/stmt/loops.rs
  • crates/perry-codegen/src/stmt/versioned_indexed_loop.rs
  • crates/perry-runtime/src/closure/dispatch/direct.rs
  • crates/perry-runtime/src/closure/registry.rs
  • crates/perry/tests/versioned_indexed_loop_callback_deopt.rs
  • scripts/gc_runtime_root_holders.json

📝 Walkthrough

Walkthrough

The compiler now selects exact additive and update callbacks for versioned indexed loops. It emits private callback clones, resolves targets through runtime metadata, deoptimizes before unsupported operations, resumes at the next index, and marks specialized calls as GC-leaf call sites.

Changes

Versioned loop callback specialization

Layer / File(s) Summary
Callback selection and runtime registration
crates/perry-codegen/src/codegen/closure_collect.rs, crates/perry-codegen/src/codegen/closure.rs, crates/perry-codegen/src/codegen/artifacts.rs, crates/perry-codegen/src/codegen/string_pool.rs, crates/perry-runtime/src/closure/...
The compiler selects narrowly matched arrow callbacks, emits versioned-loop clones, registers their targets, and resolves exact capture layouts and arities at runtime.
Loop target resolution and deopt context
crates/perry-codegen/src/codegen/{entry.rs,function.rs,method.rs}, crates/perry-codegen/src/expr/mod.rs, crates/perry-codegen/src/stmt/{loops.rs,versioned_indexed_loop.rs}
Function contexts carry callback targets and deoptimization state. Versioned loops dispatch through callback preheaders and resume through the guarded slow path at the recorded next index.
Callback clone execution and fallback paths
crates/perry-codegen/src/expr/..., crates/perry-codegen/src/lower_call/..., crates/perry-codegen/src/codegen/trusted_box_callback_tests.rs
Callback clones use loop context for direct calls. Property misses, dynamic additions, TDZ reads, coercion, and boxed updates record deoptimization before fallback behavior.
GC-leaf call emission and reload analysis
crates/perry-codegen/src/{block.rs,dialect/mod.rs,inst.rs,root_reload.rs}, crates/perry-codegen/src/*tests.rs
Direct and indirect calls support the gc-leaf-function attribute. Root reload analysis treats marked call sites as non-collecting while transitive effect analysis remains collecting.
Specialization fixtures and regression coverage
crates/perry-codegen/src/codegen/*tests.rs, crates/perry/tests/versioned_indexed_loop_callback_deopt.rs, changelog.d/8783-exact-callback-versioned-loops.md
Tests cover callback selection, LLVM emission, numeric updates, exception behavior, runtime resolution, and deterministic next-index resumption.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers: thehypnoo

✨ 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 merge/land-8783

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.

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