Skip to content

Commit

Permalink
[compiler] HIR-based FlattenReactiveLoops
Browse files Browse the repository at this point in the history
Pre the title, this implements an HIR-based version of FlattenReactiveLoops. Another step on the way to HIR-everywhere.

ghstack-source-id: e1d166352df6b0725e4c4915a19445437916251f
Pull Request resolved: #29838
  • Loading branch information
josephsavona committed Jun 10, 2024
1 parent ba5fe6e commit a121d04
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ import {
} from "../ReactiveScopes";
import { alignMethodCallScopes } from "../ReactiveScopes/AlignMethodCallScopes";
import { alignReactiveScopesToBlockScopesHIR } from "../ReactiveScopes/AlignReactiveScopesToBlockScopesHIR";
import { flattenReactiveLoopsHIR } from "../ReactiveScopes/FlattenReactiveLoopsHIR";
import { pruneAlwaysInvalidatingScopes } from "../ReactiveScopes/PruneAlwaysInvalidatingScopes";
import pruneInitializationDependencies from "../ReactiveScopes/PruneInitializationDependencies";
import { stabilizeBlockIds } from "../ReactiveScopes/StabilizeBlockIds";
import { eliminateRedundantPhi, enterSSA, leaveSSA } from "../SSA";
import { inferTypes } from "../TypeInference";
Expand All @@ -91,7 +93,6 @@ import {
validatePreservedManualMemoization,
validateUseMemo,
} from "../Validation";
import pruneInitializationDependencies from "../ReactiveScopes/PruneInitializationDependencies";

export type CompilerPipelineValue =
| { kind: "ast"; name: string; value: CodegenFunction }
Expand Down Expand Up @@ -281,6 +282,13 @@ function* runWithEnvironment(
});

assertValidBlockNesting(hir);

flattenReactiveLoopsHIR(hir);
yield log({
kind: "hir",
name: "FlattenReactiveLoopsHIR",
value: hir,
});
}

const reactiveFunction = buildReactiveFunction(hir);
Expand Down Expand Up @@ -320,14 +328,14 @@ function* runWithEnvironment(
name: "BuildReactiveBlocks",
value: reactiveFunction,
});
}

flattenReactiveLoops(reactiveFunction);
yield log({
kind: "reactive",
name: "FlattenReactiveLoops",
value: reactiveFunction,
});
flattenReactiveLoops(reactiveFunction);
yield log({
kind: "reactive",
name: "FlattenReactiveLoops",
value: reactiveFunction,
});
}

assertScopeInstructionsWithinScopes(reactiveFunction);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import { BlockId, HIRFunction, PrunedScopeTerminal } from "../HIR";
import { assertExhaustive, retainWhere } from "../Utils/utils";

/**
* Prunes any reactive scopes that are within a loop (for, while, etc). We don't yet
* support memoization within loops because this would require an extra layer of reconciliation
* (plus a way to identify values across runs, similar to how we use `key` in JSX for lists).
* Eventually we may integrate more deeply into the runtime so that we can do a single level
* of reconciliation, but for now we've found it's sufficient to memoize *around* the loop.
*/
export function flattenReactiveLoopsHIR(fn: HIRFunction): void {
const activeLoops = Array<BlockId>();
for (const [, block] of fn.body.blocks) {
retainWhere(activeLoops, (id) => id !== block.id);
const { terminal } = block;
switch (terminal.kind) {
case "do-while":
case "for":
case "for-in":
case "for-of":
case "while": {
activeLoops.push(terminal.fallthrough);
break;
}
case "scope": {
if (activeLoops.length !== 0) {
block.terminal = {
kind: "pruned-scope",
block: terminal.block,
fallthrough: terminal.fallthrough,
id: terminal.id,
loc: terminal.loc,
scope: terminal.scope,
} as PrunedScopeTerminal;
}
break;
}
case "branch":
case "goto":
case "if":
case "label":
case "logical":
case "maybe-throw":
case "optional":
case "pruned-scope":
case "return":
case "sequence":
case "switch":
case "ternary":
case "throw":
case "try":
case "unreachable":
case "unsupported": {
break;
}
default: {
assertExhaustive(
terminal,
`Unexpected terminal kind \`${(terminal as any).kind}\``
);
}
}
}
}

0 comments on commit a121d04

Please sign in to comment.