Skip to content

Commit

Permalink
[compiler] Early sketch of ReactiveIR
Browse files Browse the repository at this point in the history
Early sketch of a new representation for the middle-phase of the compiler. This is a sea-of-nodes approach, representing instructions and terminals as nodes with direct and control dependencies.

Something like this:

```js
let array = [];
if (cond) {
  array.push(value);
}
return array;
```

Would correspond roughly to a graph as follows. Note that the actual representation uses `Instruction` as-is, and maps dependencies into local `Place`s, but for ease of reading i've mapped operands as the node they come from (n0 etc):

```
n0 = ArrayExpression []
n1 = StoreLocal 'array' = n0

// nodes from the consequent
n2 = LoadLocal 'array'
n3 = PropertyLoad n3 . 'push'
n4 = LoadLocal 'value'
n5 = MethodCall n2 . n3 ( n4 )

// if terminal
n6 = LoadLocal 'cond'
n7 = If test=n6 consequent=n5 alternate=(not pictured)

// return terminal
n8 = LoadLocal 'array';
n9 = Return value=n8

exit=n9
```

Note that even if there are multiple returns, there will always be a single "exit" node, which is just the node corresponding to the last statement of the outer block in the original program.

What's implemented so far is very basic translation of HIR to ReactiveGraph. The only dependencies created are direct data dependencies and basic control flow, which means that e.g. code inside an if consequent will stay "inside" that consequent, but it's possible for mutations or reassignments to get reordered. The reordering happens because we reverse-postorder the graph after construction, which automatically orders strictly based on dependencies and moves things around otherwise.

There is lots left to do here, including cleaning up the node dependencies and how they map to local Places, establishing other forms of dependencies, etc.

ghstack-source-id: 49414d19361d9bbd58690828bfa6317ba682257a
Pull Request resolved: #31974
  • Loading branch information
josephsavona committed Jan 6, 2025
1 parent bf883be commit e829198
Show file tree
Hide file tree
Showing 6 changed files with 979 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ import {propagateScopeDependenciesHIR} from '../HIR/PropagateScopeDependenciesHI
import {outlineJSX} from '../Optimization/OutlineJsx';
import {optimizePropsMethodCalls} from '../Optimization/OptimizePropsMethodCalls';
import {transformFire} from '../Transform';
import {buildReactiveGraph} from '../ReactiveIR/BuildReactiveGraph';
import {printReactiveGraph} from '../ReactiveIR/ReactiveIR';

export type CompilerPipelineValue =
| {kind: 'ast'; name: string; value: CodegenFunction}
Expand Down Expand Up @@ -314,6 +316,15 @@ function runWithEnvironment(
value: hir,
});

if (env.config.enableReactiveGraph) {
const reactiveGraph = buildReactiveGraph(hir);
log({
kind: 'debug',
name: 'BuildReactiveGraph',
value: printReactiveGraph(reactiveGraph),
});
}

alignReactiveScopesToBlockScopesHIR(hir);
log({
kind: 'hir',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,12 @@ const EnvironmentConfigSchema = z.object({
*/
enableInstructionReordering: z.boolean().default(false),

/**
* Enables ReactiveGraph-based optimizations including reordering across terminal
* boundaries
*/
enableReactiveGraph: z.boolean().default(false),

/**
* Enables function outlinining, where anonymous functions that do not close over
* local variables can be extracted into top-level helper functions.
Expand Down
Loading

0 comments on commit e829198

Please sign in to comment.