Skip to content

refactor(react_compiler): share one AST walk across entrypoint replace visitors#24546

Merged
graphite-app[bot] merged 1 commit into
mainfrom
react-compiler-merge-glue-visitors
Jul 15, 2026
Merged

refactor(react_compiler): share one AST walk across entrypoint replace visitors#24546
graphite-app[bot] merged 1 commit into
mainfrom
react-compiler-merge-glue-visitors

Conversation

@Boshen

@Boshen Boshen commented Jul 15, 2026

Copy link
Copy Markdown
Member

Every distinct Visit/VisitMut implementor monomorphizes the entire generated AST walk; react_compiler/entrypoint/program.rs had three such types (OxcReplaceFnVisitor, OxcReplaceWithGatedVisitor, and the local Finder), so the walk was instantiated three times. They are now a single OxcVisitor selected by an OxcVisitMode enum (ReplaceFns / ReplaceWithGated / FindOriginalFn), so the walk is instantiated once.

Each overridden method dispatches on the mode and behaves exactly like the default walk in the modes that do not use it, preserving traversal order and the early-exit semantics (remaining == 0, done, found.is_some()). Finder moves from the read-only VisitJs walk onto the shared VisitMut walk — a superset traversal; it matches a unique scope_id, and function scopes cannot occur in the pruned type grammar (per #24532), so the lookup result is unchanged. The Babel-mirroring notes (ReplaceFnVisitor / ReplaceWithGatedVisitor) stay on the corresponding modes, and the per-node replacement logic is ported verbatim into free helpers (ox_replace_function, ox_replace_arrow, ox_build_gated_const_decl).

Measured on this crate's release example binary (--example react_compiler, workspace release profile with fat LTO): machine code (__text) shrinks by 24,112 bytes (~24 KB), file size by 16,592 bytes (~17 KB). The three walk instantiations measured ~34K/~16K/~14K in the symbol-level size analysis of the release napi binary that motivated this change.

Behavior is verified unchanged on the full fixture snapshot corpus (1,736 snapshots, including the gating__* fixtures that exercise the gated-replacement and original-function-lookup paths), and the release example binary produces byte-identical output before and after across the gating and general fixtures.

Authored with Claude Code; reviewed by a human before merge.

@codspeed-hq

codspeed-hq Bot commented Jul 15, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 10 untouched benchmarks
⏩ 61 skipped benchmarks1


Comparing react-compiler-merge-glue-visitors (d11a048) with main (4d0c601)

Open in CodSpeed

Footnotes

  1. 61 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@Boshen Boshen added the 0-merge Merge with Graphite Merge Queue label Jul 15, 2026

Boshen commented Jul 15, 2026

Copy link
Copy Markdown
Member Author

Merge activity

…e visitors (#24546)

Every distinct `Visit`/`VisitMut` implementor monomorphizes the entire generated AST walk; `react_compiler/entrypoint/program.rs` had three such types (`OxcReplaceFnVisitor`, `OxcReplaceWithGatedVisitor`, and the local `Finder`), so the walk was instantiated three times. They are now a single `OxcVisitor` selected by an `OxcVisitMode` enum (`ReplaceFns` / `ReplaceWithGated` / `FindOriginalFn`), so the walk is instantiated once.

Each overridden method dispatches on the mode and behaves exactly like the default walk in the modes that do not use it, preserving traversal order and the early-exit semantics (`remaining == 0`, `done`, `found.is_some()`). `Finder` moves from the read-only `VisitJs` walk onto the shared `VisitMut` walk — a superset traversal; it matches a unique `scope_id`, and function scopes cannot occur in the pruned type grammar (per #24532), so the lookup result is unchanged. The Babel-mirroring notes (`ReplaceFnVisitor` / `ReplaceWithGatedVisitor`) stay on the corresponding modes, and the per-node replacement logic is ported verbatim into free helpers (`ox_replace_function`, `ox_replace_arrow`, `ox_build_gated_const_decl`).

Measured on this crate's release example binary (`--example react_compiler`, workspace release profile with fat LTO): machine code (`__text`) shrinks by 24,112 bytes (~24 KB), file size by 16,592 bytes (~17 KB). The three walk instantiations measured ~34K/~16K/~14K in the symbol-level size analysis of the release napi binary that motivated this change.

Behavior is verified unchanged on the full fixture snapshot corpus (1,736 snapshots, including the `gating__*` fixtures that exercise the gated-replacement and original-function-lookup paths), and the release example binary produces byte-identical output before and after across the gating and general fixtures.

Authored with Claude Code; reviewed by a human before merge.
@graphite-app
graphite-app Bot force-pushed the react-compiler-merge-glue-visitors branch from d11a048 to 246b426 Compare July 15, 2026 12:15
@graphite-app
graphite-app Bot merged commit 246b426 into main Jul 15, 2026
29 checks passed
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label Jul 15, 2026
@graphite-app
graphite-app Bot deleted the react-compiler-merge-glue-visitors branch July 15, 2026 12:19
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