perf(gc): prune non-collecting statepoints; finish entry outlining; add iOS 27 APIs - #8700
Merged
Conversation
…dd iOS 27 APIs Lands #8689, #8697 and #8699. #8689 computes a whole-module greatest-fixed-point GC-effect closure and marks direct calls to transitively non-collecting generated callees `gc-leaf-function`, while allocation/poll paths, indirect calls, unknown externals and cross-module calls stay statepoints. Its `native_emit.rs` conflict with the just-landed #8687 was one hunk: #8689's `render_fn_external_with_gc_leaf_callees` replaces `render_fn_external`, and `gc_leaf_callees` is destructured in the same function by #8689's own change, so the conflict was positional only. #8697 (closes #8595) enables structured module-entry outlining automatically past 1,000 top-level HIR statements or 4,000 estimated safepoints, bounding chunks and marking them no-inline so LLVM cannot reconstruct the oversized entry before RS4GC, ISel or regalloc. `PERRY_OUTLINE_ENTRY=1`/`=0` remain as force-on and opt-out. #8699 (closes #5536) adds the iOS-only `perry/ios` layout API, a Swift Foundation Models bridge, and iOS 27 NowPlaying `MediaSession` for `perry/media`, with the MediaPlayer path retained for older SDKs. Its `perry-runtime/src/thread.rs` change is additive: `queue_thread_result` now delegates to `queue_thread_result_with_mode(..., is_rejection: false)`, so existing behaviour is unchanged, and `queue_promise_string_rejection` is new. Three mechanical fixes on top: - #8699's two new thread-locals in `perry-ui-ios/src/adaptive_layout.rs` (`LISTENERS`, `LAST_SNAPSHOT`) failed the root-holder gate. They hold a NaN-boxed JS callback, so they are NOT `not_a_gc_pointer`; they are recorded on the ledger FRONTIER, matching the 466 existing perry-ui-* entries of the same shape (including a byte-identical `perry-ui-ios/src/network.rs: LISTENERS`). No UI crate registers a GC scanner today -- a real, pre-existing, systemic gap, tracked separately rather than papered over with a false verdict here. - `collect_modules.rs` (1984 on main, +27) crossed the file-size cap; `collect_module_finish` moved to `collect_modules/finish.rs`. - `build_and_run.rs` (1995 on main, +6) crossed it too; the `if is_watchos` arm body moved to `link/watchos_frameworks.rs`. Also removes two unused imports that my own #8688 static-fields split left in `codegen/helpers.rs`. No version bump.
This was referenced Aug 24, 2026
|
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 (54)
📝 WalkthroughWalkthroughChangesModule-entry outlining
Transitive GC-leaf analysis
iOS platform APIs
Platform build and metadata
Estimated code review effort: 5 (Critical) | ~120 minutes ✨ 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 was referenced Aug 24, 2026
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 #8689, #8697 and #8699.
#8689 — prune transitively non-collecting statepoints
Whole-module greatest-fixed-point GC-effect closure; direct calls to transitively non-collecting generated callees get
gc-leaf-function, while allocation/poll paths, indirect calls, unknown externals and cross-module calls stay statepoints.Its
native_emit.rsconflict with the just-landed #8687 was one hunk and positional only: #8689'srender_fn_external_with_gc_leaf_calleesreplacesrender_fn_external, andgc_leaf_calleesis destructured in that same function by #8689's own change. I verified the binding is in scope rather than assuming, then took #8689's side.gc_leaf_asm_barrier_survives_rs4gc_unwrappedpasses — the inline-asm loop barrier RS4GC statepointed in #8121.#8697 — finish structured module-entry outlining (closes #8595)
Automatic past 1,000 top-level HIR statements or 4,000 estimated safepoints (
DEFAULT_AUTO_MIN_STMTS/DEFAULT_AUTO_MIN_SAFEPOINTS), chunks bounded and marked no-inline so LLVM cannot reconstruct the oversized entry before RS4GC, ISel or regalloc.PERRY_OUTLINE_ENTRY=1force-on and=0opt-out both verified still present. Its own 14 unit tests pass.#8699 — iOS 27 platform APIs (closes #5536)
The shared-runtime part is the only piece that reaches non-iOS builds, and it's cleanly additive:
queue_thread_resultnow delegates toqueue_thread_result_with_mode(..., is_rejection: false), preserving behaviour, withqueue_promise_string_rejectionadded alongside.Three mechanical fixes on top
Root-holder ledger — and a finding worth stating plainly. #8699 adds two thread-locals in
perry-ui-ios/src/adaptive_layout.rs.LISTENERS: RefCell<HashMap<i64, f64>>stores thef64callback passed toperry_ios_on_layout_changeand later calls it viainvoke_listener— thatf64is a NaN-boxed JS closure, i.e. a heap pointer, so this is emphatically notnot_a_gc_pointer.It is, however, pre-existing and systemic rather than introduced here: the ledger already carries 466
perry-ui-*frontier entries of exactly this shape, including a byte-identicalperry-ui-ios/src/network.rs: LISTENERS, and no UI crate registers a GC scanner at all. So both new holders go on the frontier alongside their siblings. Blocking this PR for a condition that predates it would be wrong; recording a falsenot_a_gc_pointerverdict to make the gate green would be worse. Flagged for separate tracking.Two file-size splits. Both files were already at the edge on
mainand were tipped over by small additions:collect_modules.rs(1984 → 2011):collect_module_finishmoved tocollect_modules/finish.rs.build_and_run.rs(1995 → 2001): theif is_watchosarm body moved tolink/watchos_frameworks.rs.Two unused imports removed from
codegen/helpers.rs— left there by my own #8688 static-fields split.Validation (on the merged result)
lint-job checkers passperry-codegen --lib: 1213 passed, 0 failedperry-runtime --lib(RUST_TEST_THREADS=1): 2655 passed, 0 failedperry --bin perry: 1032 passed, 0 failedperry-dispatch: 6 passed, 0 failedcargo check -p perry -p perry-codegen: 0 warnings, 0 errors(An intermediate run reported
perry-bin/dispatchfailures that were ENOSPC artifacts, not test failures; re-run after freeing space, both green.)No version bump.
Summary by CodeRabbit
perry/iosAPIs for adaptive layout information and layout-change subscriptions.