Skip to main content

Compiler Architecture

React Compiler transforms React code through a multi-stage pipeline consisting of over 55 distinct compiler passes organized into seven major phases.

Pipeline Overview

The compilation pipeline is defined in packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts and executes passes in a specific order:

Phase 1: HIR Construction

1. Lower (BuildHIR)

File: src/HIR/BuildHIR.ts Converts Babel AST to High-level Intermediate Representation (HIR). Key Operations:
  • Creates control-flow graph (CFG) with basic blocks
  • Resolves identifiers and bindings
  • Converts expressions to instructions
  • Makes control flow explicit (if/else, loops, etc.)

2. EnterSSA

File: src/SSA/EnterSSA.ts Converts HIR to Static Single Assignment (SSA) form. Key Operations:
  • Each variable assigned exactly once
  • Inserts phi nodes at control flow merge points
  • Creates unique identifiers for each assignment

3. EliminateRedundantPhi

File: src/SSA/EliminateRedundantPhi.ts Removes unnecessary phi nodes where all operands are identical.

Phase 2: Early Optimization

4. ConstantPropagation

File: src/Optimization/ConstantPropagation.ts Implements sparse conditional constant propagation.

5. DeadCodeElimination

File: src/Optimization/DeadCodeElimination.ts Removes unreferenced instructions and unreachable blocks.

Phase 3: Type & Effect Inference

6. InferTypes

File: src/TypeInference/InferTypes.ts Infers types using constraint-based unification. Inferred Types:
  • Primitive: numbers, strings, booleans, null, undefined
  • Object: objects with shape information
  • Function: functions and hooks
  • Array: array types
  • Poly: polymorphic types

7. AnalyseFunctions

File: src/Inference/AnalyseFunctions.ts Analyzes nested functions to determine their effects and captures.

8. InferMutationAliasingEffects

File: src/Inference/InferMutationAliasingEffects.ts Infers mutation and aliasing through abstract interpretation. Effect Types:

9. InferMutationAliasingRanges

File: src/Inference/InferMutationAliasingRanges.ts Computes mutable ranges (instruction ranges where values can be mutated).

10. InferReactivePlaces

File: src/Inference/InferReactivePlaces.ts Marks places as reactive if they:
  • Are component props
  • Are hook return values
  • Are derived from reactive places
  • Are used in JSX (render context)

Phase 4: Reactive Scope Inference

11. InferReactiveScopeVariables

File: src/ReactiveScopes/InferReactiveScopeVariables.ts Groups co-mutating variables into reactive scopes. Algorithm:
  1. Identify value blocks (sets of instructions creating a value)
  2. Compute dependencies for each value
  3. Group values with shared dependencies
  4. Create scope boundaries

12. RewriteInstructionKindsBasedOnReassignment

File: src/SSA/RewriteInstructionKindsBasedOnReassignment.ts Converts SSA loads to context loads for reassigned variables.

13-15. Scope Alignment

Files:
  • src/ReactiveScopes/AlignMethodCallScopes.ts
  • src/ReactiveScopes/AlignObjectMethodScopes.ts
  • src/ReactiveScopes/AlignReactiveScopesToBlockScopesHIR.ts
Aligns reactive scopes to:
  • Method call receivers
  • Object method boundaries
  • Control flow block boundaries

16-17. Scope Construction

Files:
  • src/HIR/MergeOverlappingReactiveScopesHIR.ts
  • src/HIR/BuildReactiveScopeTerminalsHIR.ts
Merges overlapping scopes and inserts scope terminals (start/end markers) into the CFG.

18-20. Scope Refinement

Files:
  • src/ReactiveScopes/FlattenReactiveLoopsHIR.ts
  • src/ReactiveScopes/FlattenScopesWithHooksOrUseHIR.ts
  • src/HIR/PropagateScopeDependenciesHIR.ts
Flattens problematic scopes (loops, hooks) and derives minimal dependencies.

Phase 5: Reactive Function Construction

21. BuildReactiveFunction

File: src/ReactiveScopes/BuildReactiveFunction.ts Converts HIR control-flow graph to ReactiveFunction tree structure. Transformation:

Phase 6: Reactive Function Optimization

22-25. Pruning Passes

Files:
  • src/ReactiveScopes/PruneUnusedLabels.ts
  • src/ReactiveScopes/PruneNonEscapingScopes.ts
  • src/ReactiveScopes/PruneNonReactiveDependencies.ts
  • src/ReactiveScopes/PruneUnusedScopes.ts
Removes:
  • Unused labels
  • Non-escaping scopes (values that don’t escape function)
  • Non-reactive dependencies
  • Empty or unreferenced scopes

26-28. Scope Optimization

Files:
  • src/ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts
  • src/ReactiveScopes/PruneAlwaysInvalidatingScopes.ts
  • src/ReactiveScopes/PropagateEarlyReturns.ts
Optimizes:
  • Merges scopes that always invalidate together
  • Removes always-invalidating scopes
  • Handles early returns

29. PromoteUsedTemporaries

File: src/ReactiveScopes/PromoteUsedTemporaries.ts Promotes temporary variables to named variables when referenced across scopes.

Phase 7: Code Generation

30. RenameVariables

File: src/ReactiveScopes/RenameVariables.ts Ensures unique variable names in the output.

31. CodegenReactiveFunction

File: src/ReactiveScopes/CodegenReactiveFunction.ts Generates final Babel AST with memoization. Output Structure:

Validation Passes

Validation passes run throughout the pipeline: Hook Validation:
  • ValidateHooksUsage: Rules of Hooks compliance
  • ValidateUseMemo: useMemo callback requirements
Mutation Validation:
  • ValidateLocalsNotReassignedAfterRender: Mutation safety
  • ValidateNoSetStateInRender: setState timing
  • ValidateNoSetStateInEffects: Effect performance
Dependency Validation:
  • ValidateExhaustiveDependencies: Complete dependencies
  • ValidateMemoizedEffectDependencies: Effect memoization
  • ValidatePreservedManualMemoization: Manual memo preservation
Other Validation:
  • ValidateNoCapitalizedCalls: Component vs function calls
  • ValidateNoJSXInTryStatement: Error boundary usage
  • ValidateNoRefAccessInRender: Ref access constraints
  • ValidateSourceLocations: Source map correctness

Optional Transformations

These run conditionally based on configuration:

TransformFire

File: src/Transform/TransformFire.ts
Flag: enableFire
Transforms fire() calls in effects.

LowerContextAccess

File: src/Optimization/LowerContextAccess.ts
Flag: lowerContextAccess
Optimizes React context access with selectors.

OutlineJsx

File: src/Optimization/OutlineJsx.ts
Flag: enableJsxOutlining
Extracts static JSX into separate components.

OutlineFunctions

File: src/Optimization/OutlineFunctions.ts
Flag: enableFunctionOutlining
Outlines pure functions for better memoization.

InferEffectDependencies

File: src/Inference/InferEffectDependencies.ts
Flag: inferEffectDependencies
Auto-infers and inserts effect dependencies.

Data Structures

HIR Types

File: src/HIR/HIR.ts

ReactiveFunction

File: src/ReactiveScopes/ReactiveFunction.ts

Performance Characteristics

Pass Complexity

  • Lowering: O(n) where n = AST nodes
  • SSA Conversion: O(n + e) where e = CFG edges
  • Type Inference: O(n²) worst case (unification)
  • Effect Inference: O(n·d) where d = average dependencies
  • Scope Inference: O(n·s) where s = scope count
  • Codegen: O(n + s)

Memory Usage

  • HIR: ~200 bytes per instruction
  • Type variables: ~50 bytes each
  • Reactive scopes: ~100 bytes + dependencies
  • Total: ~1-5MB for typical component

Debugging

Enable Debug Output

Implement a logger to see each pass:

Test Runner

Use the snap test runner:

Next Steps

HIR

Understand the intermediate representation

Optimization Passes

Learn about specific optimizations

Contributing

Contribute to the compiler

Configuration

Configure compiler behavior