Skip to content

feat: add 2-pass release build for Dynamic Dispatch table#119

Draft
bdero wants to merge 9 commits intoshorebird/devfrom
bdero/cascade-limiter
Draft

feat: add 2-pass release build for Dynamic Dispatch table#119
bdero wants to merge 9 commits intoshorebird/devfrom
bdero/cascade-limiter

Conversation

@bdero
Copy link
Copy Markdown
Member

@bdero bdero commented Mar 31, 2026

Summary

  • Adds a 2-pass release build for arm64 Apple platforms to compute the Dynamic Dispatch (DD) table
  • Pass 1 produces a temporary ELF snapshot for analyze_snapshot to compute DD table manifest, caller links, and slot mapping
  • Also exports a DD function identity side file (--print_dd_function_identity_to) mapping each Code object's InstructionsTable index to its Function's kernel_offset, which is passed to analyze_snapshot --compute_dd_slot_mapping via --dd_function_identity for kernel_offset-based function matching
  • Pass 2 produces the final assembly snapshot with indirect calls wired up via --dd_slot_mapping
  • DD table files (App.dd.link, App.dd_callers.link) are copied into the supplement directory alongside existing link files

Test plan

  • Flutter Tools Tests pass on Ubuntu and macOS
  • Shard Runner Tests pass
  • Android Tests pass

bdero added 7 commits April 2, 2026 20:35
When building for arm64 Apple platforms with the linker enabled, run
gen_snapshot twice: first in ELF mode to produce a temporary snapshot
for analyze_snapshot to compute the DD table manifest, caller links,
and slot mapping, then in assembly mode with --dd_slot_mapping to
produce the final snapshot with indirect calls wired up.

The DD table files (App.dd.link, App.dd_callers.link) are copied into
the shorebird supplement directory alongside the existing link files
so they can be bundled with releases and used during patch builds.
The 2-pass DD table build runs gen_snapshot in ELF mode before the
main assembly pass. Update tests to expect this additional command.
The arm64 DD analysis pass delays the arm64 assembly, so x86_64
(which skips DD) completes its build first when both run concurrently
via Future.wait.
Move the analyze_snapshot existence check before the gen_snapshot ELF
pass so the entire DD computation is a no-op on standard Flutter SDKs
that don't ship analyze_snapshot. This fixes iOS smoke test failures
where gen_snapshot was being invoked unnecessarily in ELF mode.

Also reverts test changes that are no longer needed since DD commands
won't appear when analyze_snapshot doesn't exist in the test filesystem.
The arm64 build's async _computeDDTable() check (even a no-op when
analyze_snapshot is absent) introduces an await that lets x86_64
reach gen_snapshot first in Future.wait. Reorder test expectations
to match the actual interleaving: x86_64 before arm64 at each step.
The DD slot mapping now uses kernel_offset-based function matching
(instead of function names). The base build must export an identity
side file during gen_snapshot pass 1 and pass it to
analyze_snapshot --compute_dd_slot_mapping.

Without this, the DDSlotMapping has empty kernel_offset_to_slot and
FinalizeIndirectStaticCallTable can't assign any DD slots, resulting
in an empty DD table in the base snapshot.
Read SHOREBIRD_DD_MAX_BYTES from the environment to allow overriding
the cascade limiter threshold. Defaults to 10000 if not set.

An environment variable is used (rather than a command-line flag) so
that older Flutter builds without DD table support silently ignore it.
@bdero bdero force-pushed the bdero/cascade-limiter branch 4 times, most recently from a9427e1 to a223f85 Compare April 3, 2026 05:22
Updates dart_sdk_revision to include SIMARM64 simulator fixes
(DoRedirectedCall, ClobberVolatileRegisters, Execute reason param)
needed for ios_debug engine builds.
@bdero bdero force-pushed the bdero/cascade-limiter branch from a223f85 to bcc42c8 Compare April 3, 2026 05:32
The GN action for building the Rust updater via cargo declared only a
stamp file as output. The library path referenced by libs[] was in the
source tree, so Ninja couldn't map it to any build rule — causing
"missing and no known rule to make it" for targets where the pre-built
library didn't already exist (e.g. host_debug on macOS).

Fix: the build_rust_updater.py script now copies the cargo-built
library from the source tree to target_gen_dir, which is declared as
an action output. This lets Ninja properly order the link step after
the cargo build.
@bdero bdero force-pushed the bdero/cascade-limiter branch from bcc42c8 to 5572ff2 Compare April 3, 2026 11:04
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