Skip to content

perf(gc): prune non-collecting statepoints; finish entry outlining; add iOS 27 APIs - #8700

Merged
proggeramlug merged 1 commit into
mainfrom
merge/b13
Aug 24, 2026
Merged

perf(gc): prune non-collecting statepoints; finish entry outlining; add iOS 27 APIs#8700
proggeramlug merged 1 commit into
mainfrom
merge/b13

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

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.rs conflict with the just-landed #8687 was one hunk and positional only: #8689's render_fn_external_with_gc_leaf_callees replaces render_fn_external, and gc_leaf_callees is 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_unwrapped passes — 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=1 force-on and =0 opt-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_result now delegates to queue_thread_result_with_mode(..., is_rejection: false), preserving behaviour, with queue_promise_string_rejection added 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 the f64 callback passed to perry_ios_on_layout_change and later calls it via invoke_listener — that f64 is a NaN-boxed JS closure, i.e. a heap pointer, so this is emphatically not not_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-identical perry-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 false not_a_gc_pointer verdict to make the gate green would be worse. Flagged for separate tracking.

Two file-size splits. Both files were already at the edge on main and were tipped over by small additions:

  • collect_modules.rs (1984 → 2011): collect_module_finish moved to collect_modules/finish.rs.
  • build_and_run.rs (1995 → 2001): the if is_watchos arm body moved to link/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)

  • All 30 lint-job checkers pass
  • perry-codegen --lib: 1213 passed, 0 failed
  • perry-runtime --lib (RUST_TEST_THREADS=1): 2655 passed, 0 failed
  • perry --bin perry: 1032 passed, 0 failed
  • perry-dispatch: 6 passed, 0 failed
  • cargo check -p perry -p perry-codegen: 0 warnings, 0 errors
  • Squashed tree verified identical to the validated tree

(An intermediate run reported perry-bin/dispatch failures that were ENOSPC artifacts, not test failures; re-run after freeing space, both green.)

No version bump.

Summary by CodeRabbit

  • New Features
    • Added perry/ios APIs for adaptive layout information and layout-change subscriptions.
    • Added iOS Foundation Models support for availability checks, language-model sessions, and asynchronous responses.
    • Added iOS 27 Now Playing integration with media metadata, playback updates, and remote commands.
    • Added TypeScript declarations and API documentation for the new iOS capabilities.
  • Improvements
    • Improved split-view layouts on narrow screens.
    • Reduced unnecessary garbage-collection safepoints for eligible calls.
  • Bug Fixes
    • Promise operations can now report rejection messages from asynchronous results.

…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.
@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7c3207a2-bea7-4961-a423-666ea3b3eeec

📥 Commits

Reviewing files that changed from the base of the PR and between fdbddeb and 18a0ea0.

📒 Files selected for processing (54)
  • changelog.d/8595-entry-outline-default.md
  • changelog.d/8596-transitive-leaf.md
  • crates/perry-api-manifest/src/entries.rs
  • crates/perry-api-manifest/src/entries/part_4.rs
  • crates/perry-codegen/src/codegen/artifacts.rs
  • crates/perry-codegen/src/codegen/entry.rs
  • crates/perry-codegen/src/codegen/entry_outline.rs
  • crates/perry-codegen/src/codegen/function.rs
  • crates/perry-codegen/src/codegen/helpers.rs
  • crates/perry-codegen/src/codegen/mod.rs
  • crates/perry-codegen/src/codegen/module_globals_emit.rs
  • crates/perry-codegen/src/codegen/static_fields.rs
  • crates/perry-codegen/src/collectors/mod.rs
  • crates/perry-codegen/src/dialect/eh.rs
  • crates/perry-codegen/src/dialect/tests.rs
  • crates/perry-codegen/src/function.rs
  • crates/perry-codegen/src/gc_call_effects.rs
  • crates/perry-codegen/src/lower_call/mod.rs
  • crates/perry-codegen/src/lower_call/native/mod.rs
  • crates/perry-codegen/src/lower_call/native/native_ui_widgets_branch.rs
  • crates/perry-codegen/src/lower_call/ui_tables.rs
  • crates/perry-codegen/src/module.rs
  • crates/perry-codegen/src/native_emit.rs
  • crates/perry-codegen/src/native_root_coverage/mechanics.rs
  • crates/perry-codegen/tests/ios_platform_api_lowering.rs
  • crates/perry-dispatch/src/ios_table.rs
  • crates/perry-dispatch/src/lib.rs
  • crates/perry-runtime/src/thread.rs
  • crates/perry-ui-ios/Cargo.toml
  • crates/perry-ui-ios/src/adaptive_layout.rs
  • crates/perry-ui-ios/src/app.rs
  • crates/perry-ui-ios/src/foundation_models.rs
  • crates/perry-ui-ios/src/lib.rs
  • crates/perry-ui-ios/src/media_playback.rs
  • crates/perry-ui-ios/src/widgets/splitview.rs
  • crates/perry-ui-ios/swift/PerryFoundationModels.swift
  • crates/perry-ui-ios/swift/PerryNowPlaying.swift
  • crates/perry/src/commands/compile/collect_modules.rs
  • crates/perry/src/commands/compile/collect_modules/finish.rs
  • crates/perry/src/commands/compile/link/build_and_run.rs
  • crates/perry/src/commands/compile/link/mod.rs
  • crates/perry/src/commands/compile/link/platform_cmd.rs
  • crates/perry/src/commands/compile/link/watchos_frameworks.rs
  • crates/perry/src/commands/compile/run_pipeline.rs
  • crates/perry/src/commands/types.rs
  • crates/perry/tests/entry_outline_transform_8595.rs
  • docs/api/perry.d.ts
  • docs/src/api/reference.md
  • docs/src/platforms/ios.md
  • docs/src/system/media.md
  • docs/statepoint-gc-experiment.md
  • scripts/gc_runtime_root_holders.json
  • types/perry/ios/index.d.ts
  • types/perry/media/index.d.ts

📝 Walkthrough

Walkthrough

Changes

Module-entry outlining

Layer / File(s) Summary
Entry outline transformation
crates/perry-codegen/src/codegen/entry_outline.rs, changelog.d/8595-entry-outline-default.md
Large module entries can split into ordered compiler-generated chunks. Automatic, forced, and disabled modes are supported. Cross-chunk bindings become module globals.
Logical entry integration
crates/perry-codegen/src/codegen/*, crates/perry/src/commands/compile/*
Codegen analyses now use reconstructed logical entry statements. Outlined chunks avoid inline paths and run during module finalization.
Outlining validation
crates/perry/tests/entry_outline_transform_8595.rs
Tests cover thresholds, safepoint splitting, ordering, globals, dependencies, structured control flow, and automatic outlining.

Transitive GC-leaf analysis

Layer / File(s) Summary
GC effect proof and annotation
crates/perry-codegen/src/gc_call_effects.rs, crates/perry-codegen/src/function.rs, crates/perry-codegen/src/dialect/*
The compiler computes transitive non-collecting callees and annotates eligible direct calls and invoke instructions with gc-leaf-function.
Emission propagation
crates/perry-codegen/src/module.rs, crates/perry-codegen/src/native_emit.rs
The shared leaf set flows through whole-module, native, fallback, and split-unit rendering.
GC validation
crates/perry-codegen/src/gc_call_effects.rs, crates/perry-codegen/src/native_emit.rs
Tests cover recursion, collecting paths, indirect calls, invokes, and emission consistency.

iOS platform APIs

Layer / File(s) Summary
API contracts and lowering
crates/perry-api-manifest/*, crates/perry-dispatch/*, crates/perry-codegen/lower_call/*, types/perry/ios/*
The perry/ios module exposes adaptive layout and Foundation Models methods with iOS-target validation and TypeScript declarations.
Adaptive layout
crates/perry-ui-ios/src/adaptive_layout.rs, crates/perry-ui-ios/src/app.rs
The runtime publishes scene geometry, traits, safe areas, window modes, and layout-change callbacks.
Foundation Models
crates/perry-ui-ios/src/foundation_models.rs, crates/perry-ui-ios/swift/PerryFoundationModels.swift, crates/perry-runtime/src/thread.rs
Rust and Swift expose model availability, session lifecycle, asynchronous responses, and promise rejection handling.
Now Playing
crates/perry-ui-ios/src/media_playback.rs, crates/perry-ui-ios/swift/PerryNowPlaying.swift
iOS 27 uses handle-scoped observable media sessions with command routing and legacy fallback support.

Platform build and metadata

Layer / File(s) Summary
Compilation and linking
crates/perry/src/commands/compile/*
Swift bridge compilation, conditional framework linking, watchOS framework extraction, and iOS module markers were added.
API and platform documentation
docs/api/*, docs/src/*, types/perry/media/index.d.ts
Generated API references and iOS documentation describe the new APIs and platform behavior.
Layout support
crates/perry-ui-ios/src/widgets/splitview.rs, scripts/gc_runtime_root_holders.json
Split-view widths can shrink in narrow scenes, and adaptive-layout state holders are tracked.

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

✨ 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/b13

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

1 participant