[ReactiveHIR] Infer reactive identifiers and promote temporaries

Messed up ghstack, this is a duplicate of #1093
This commit is contained in:
mofeiZ
2023-02-03 14:52:46 -05:00
parent 34a7b58334
commit ecb084c4b8
46 changed files with 505 additions and 344 deletions
+8
View File
@@ -27,6 +27,7 @@ import {
flattenReactiveLoops,
inferReactiveScopeVariables,
mergeOverlappingReactiveScopes,
promoteUsedTemporaries,
propagateScopeDependencies,
pruneUnusedLabels,
pruneUnusedLValues,
@@ -128,6 +129,13 @@ export function* run(
value: reactiveFunction,
});
promoteUsedTemporaries(reactiveFunction);
yield log({
kind: "reactive",
name: "promoteUsedTemporaries",
value: reactiveFunction,
});
pruneUnusedLabels(reactiveFunction);
yield log({
kind: "reactive",
@@ -185,8 +185,11 @@ function codegenReactiveScope(
firstOutputIndex = index;
}
// TODO @josephsavona: ensure change and temp variables have non-conflicting names
output.name ??= `t${index}`;
invariant(
output.name != null,
"Expected identifier '@%s' to be named",
output.id
);
const name = convertIdentifier(output);
cx.declare(output);
@@ -0,0 +1,127 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {
Identifier,
ReactiveFunction,
ReactiveInstruction,
ReactiveScope,
} from "../HIR/HIR";
import {
eachReactiveValueOperand,
ReactiveFunctionVisitor,
visitReactiveFunction,
} from "./visitors";
type IdentifierReactivity = Map<Identifier, boolean>;
class Environment extends ReactiveFunctionVisitor<IdentifierReactivity> {
override visitInstruction(
instr: ReactiveInstruction,
reactivityMap: IdentifierReactivity
) {
this.traverseInstruction(instr, reactivityMap);
const lval = instr.lvalue;
if (lval == null || reactivityMap.get(lval.place.identifier) === true) {
return;
}
const { value } = instr;
let hasReactiveInput = false;
for (const operand of eachReactiveValueOperand(value)) {
// We currently treat free variables (from module or global scope) as
// non-reactive. We may later want type information about specific
// free variables, or a toggle `treatFreeVarsAsReactive`.
if (reactivityMap.get(operand.identifier)) {
hasReactiveInput = true;
break;
}
}
reactivityMap.set(lval.place.identifier, hasReactiveInput);
if (hasReactiveInput) {
// all mutating effects must also be marked as reactive
for (const operand of eachReactiveValueOperand(value)) {
if (operand.effect === "store" || operand.effect === "mutate") {
// Explicitly compare to `false` here, since absence from the
// map indicates a free variable
// todo [@mofeiZ] add knowledge about free variables
if (reactivityMap.get(operand.identifier) === false) {
reactivityMap.set(operand.identifier, true);
}
}
}
}
}
}
/**
* Computes a map of {@link Place} -> reactivityMap. A Place is reactive if any
* operant used in its construction is reactive. Sources of reactivity are
* {@link ReactiveFunction.params} and HookCall return values (TODO).
* Free values are currently not populated.
*
* This relies on alias analysis done by InferReactiveScopeVariables, which
* creates reactive scopes for variables that mutate together. If one value
* declared in a scope is Reactive, then the rest are marked as reactive as
* well.
* e.g.
* ```javascript
* function foo(props) {
* let x = {};
* let y = [];
* x.y = y;
* y.push(props.a)
* // references to x are reactive here
* }
* ```
* This an overestimate when two identifiers have overlapping scope, but
* one is not actually reactive. However, since the same ReactiveBlock now
* produces both identifiers, they are effectively both effective (i.e.
* object creation is not stable)
* e.g.
* ```javascript
* function bar(props) {
* let x = {};
* let y = [];
* mutate1(x, props);
* mutate2(y);
* }
* ```
*/
export function inferReactiveIdentifiers(
fn: ReactiveFunction
): Set<Identifier> {
const visitor = new Environment();
const reactivityMap: IdentifierReactivity = new Map();
for (const param of fn.params) {
reactivityMap.set(param.identifier, true);
}
const actuallyReactiveScopes = new Set<ReactiveScope>();
let prevScopesSize = -1;
// TODO(mofeiZ): avoid fixpoint iteration by keeping a map of identifiers
// read by a ReactiveScope (that are produced outside of it)
while (actuallyReactiveScopes.size > prevScopesSize) {
prevScopesSize = actuallyReactiveScopes.size;
visitReactiveFunction(fn, visitor, reactivityMap);
for (const [id, value] of reactivityMap) {
const { scope } = id;
if (value && scope != null) {
actuallyReactiveScopes.add(scope);
}
}
for (const [id, _] of reactivityMap) {
if (id.scope && actuallyReactiveScopes.has(id.scope)) {
reactivityMap.set(id, true);
}
}
}
const result = new Set<Identifier>();
reactivityMap.forEach((isReactive, id) => {
if (isReactive) result.add(id);
});
return result;
}
@@ -0,0 +1,37 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { ReactiveFunction, ReactiveScopeBlock } from "../HIR/HIR";
import { ReactiveFunctionVisitor, visitReactiveFunction } from "./visitors";
type VisitorState = {
nextId: number;
};
class Visitor extends ReactiveFunctionVisitor<VisitorState> {
override visitScope(block: ReactiveScopeBlock, state: VisitorState) {
this.traverseScope(block, state);
for (const dep of block.scope.dependencies) {
const { identifier } = dep.place;
if (identifier.name == null) {
identifier.name = `t${state.nextId++}`;
}
}
// This is technically optional. We could prune ReactiveScopes
// whose outputs are not used in another computation or return
// value.
// Many of our current test fixtures do not return a value, so
// it is better for now to promote (and memoize) every output.
for (const identifier of block.scope.outputs) {
if (identifier.name == null) {
identifier.name = `t${state.nextId++}`;
}
}
}
}
export function promoteUsedTemporaries(fn: ReactiveFunction) {
visitReactiveFunction(fn, new Visitor(), { nextId: 0 });
}
@@ -9,7 +9,6 @@ import {
Identifier,
InstructionId,
InstructionKind,
isPrimitiveType,
LValue,
makeInstructionId,
Place,
@@ -22,6 +21,7 @@ import {
} from "../HIR/HIR";
import { eachInstructionValueOperand } from "../HIR/visitors";
import { assertExhaustive } from "../Utils/utils";
import { inferReactiveIdentifiers } from "./InferReactiveIdentifiers";
import { eachReactiveValueOperand } from "./visitors";
/**
@@ -31,7 +31,7 @@ import { eachReactiveValueOperand } from "./visitors";
* their direct dependencies and those of their child scopes.
*/
export function propagateScopeDependencies(fn: ReactiveFunction): void {
const context = new Context();
const context = new Context(inferReactiveIdentifiers(fn));
if (fn.id !== null) {
context.declare(fn.id, { kind: DeclKind.Const, id: makeInstructionId(0) });
}
@@ -57,9 +57,16 @@ type Scopes = Array<ReactiveScope>;
class Context {
#declarations: DeclMap = new Map();
#dependencies: Set<ReactiveScopeDependency> = new Set();
#reactiveIdentifiers: Set<Identifier>;
// Produces a de-duplicated mapping of Id -> ReactiveScopeDependency
// This helps with.. temporaries that are created only for property loads
// but can be generalized to all non-allocating temporaries
#properties: Map<Identifier, ReactiveScopeDependency> = new Map();
#scopes: Scopes = [];
constructor(reactiveIdentifiers: Set<Identifier>) {
this.#reactiveIdentifiers = reactiveIdentifiers;
}
enter(scope: ReactiveScope, fn: () => void): Set<ReactiveScopeDependency> {
const previousDependencies = this.#dependencies;
const scopedDependencies = new Set<ReactiveScopeDependency>();
@@ -97,6 +104,10 @@ class Context {
return this.#scopes.at(-1)!;
}
isReactive(id: Identifier): boolean {
return this.#reactiveIdentifiers.has(id);
}
visitOperand(place: Place): void {
this.visitDependency({ place, path: null });
}
@@ -133,6 +144,8 @@ class Context {
}
const decl = this.#declarations.get(maybeDependency.place.identifier);
// if decl is undefined here, then this is a free var
// (all other decls e.g. `let x;` should be initialized in BuildHIR)
// Any value used after its defining scope has concluded must be added as an
// output of its defining scope. Regardless of whether its a const or not,
@@ -323,19 +336,13 @@ function visitInstruction(context: Context, instr: ReactiveInstruction): void {
const { lvalue } = instr;
visitInstructionValue(context, instr.value, lvalue);
if (lvalue !== null && lvalue.kind !== InstructionKind.Reassign) {
const range = lvalue.place.identifier.mutableRange;
// TODO: only assign Const if the value is never reassigned
const kind =
range.end === range.start + 1
? valueKind(lvalue.place.identifier)
: DeclKind.Dynamic;
const kind = context.isReactive(lvalue.place.identifier)
? DeclKind.Dynamic
: DeclKind.Const;
context.declare(lvalue.place.identifier, {
kind,
id: lvalue.place.identifier.mutableRange.start,
});
}
}
function valueKind(id: Identifier): DeclKind {
return isPrimitiveType(id) ? DeclKind.Const : DeclKind.Dynamic;
}
@@ -13,6 +13,7 @@ export { flattenReactiveLoops } from "./FlattenReactiveLoops";
export { inferReactiveScopeVariables } from "./InferReactiveScopeVariables";
export { mergeOverlappingReactiveScopes } from "./MergeOverlappingReactiveScopes";
export { printReactiveFunction } from "./PrintReactiveFunction";
export { promoteUsedTemporaries } from "./PromoteUsedTemporaries";
export { propagateScopeDependencies } from "./PropagateScopeDependencies";
export { pruneTemporaryLValues as pruneUnusedLValues } from "./PruneTemporaryLValues";
export { pruneUnusedLabels } from "./PruneUnusedLabels";
@@ -25,25 +25,21 @@ function component() {
} else {
z = $[0];
}
const c_1 = $[1] !== z;
let y;
if (c_1) {
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
y = {};
y.z = z;
$[1] = z;
$[2] = y;
$[1] = y;
} else {
y = $[2];
y = $[1];
}
const c_3 = $[3] !== y;
let x;
if (c_3) {
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
x = {};
x.y = y;
$[3] = y;
$[4] = x;
$[2] = x;
} else {
x = $[4];
x = $[2];
}
return x;
}
@@ -36,18 +36,14 @@ function Component(props) {
a = $[0];
b = $[1];
}
const c_2 = $[2] !== a;
const c_3 = $[3] !== b;
let t4;
if (c_2 || c_3) {
t4 = <div a={a} b={b}></div>;
$[2] = a;
$[3] = b;
$[4] = t4;
let t0;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t0 = <div a={a} b={b}></div>;
$[2] = t0;
} else {
t4 = $[4];
t0 = $[2];
}
return t4;
return t0;
}
```
@@ -48,9 +48,9 @@ function getNativeLogFunction(level) {
function getNativeLogFunction(level) {
const $ = React.useMemoCache();
const c_0 = $[0] !== level;
let t1;
let t0;
if (c_0) {
t1 = function () {
t0 = function () {
let str;
if (arguments.length === 1 && typeof arguments[0] === "string") {
str = arguments[0];
@@ -86,11 +86,11 @@ function getNativeLogFunction(level) {
global.nativeLoggingHook(str, logLevel);
};
$[0] = level;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
return t1;
return t0;
}
```
@@ -18,19 +18,19 @@ function component(a) {
function component(a) {
const $ = React.useMemoCache();
const c_0 = $[0] !== a;
let t1;
let t0;
if (c_0) {
t1 = { a: a };
t0 = { a: a };
$[0] = a;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
const c_2 = $[2] !== t1;
const c_2 = $[2] !== t0;
let z;
if (c_2) {
z = { a: t1 };
$[2] = t1;
z = { a: t0 };
$[2] = t0;
$[3] = z;
} else {
z = $[3];
@@ -20,19 +20,19 @@ function component(a) {
function component(a) {
const $ = React.useMemoCache();
const c_0 = $[0] !== a;
let t1;
let t0;
if (c_0) {
t1 = { a: a };
t0 = { a: a };
$[0] = a;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
const c_2 = $[2] !== t1;
const c_2 = $[2] !== t0;
let z;
if (c_2) {
z = { a: t1 };
$[2] = t1;
z = { a: t0 };
$[2] = t0;
$[3] = z;
} else {
z = $[3];
@@ -18,19 +18,19 @@ function component(a) {
function component(a) {
const $ = React.useMemoCache();
const c_0 = $[0] !== a;
let t1;
let t0;
if (c_0) {
t1 = { a: a };
t0 = { a: a };
$[0] = a;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
const c_2 = $[2] !== t1;
const c_2 = $[2] !== t0;
let z;
if (c_2) {
z = { a: t1 };
$[2] = t1;
z = { a: t0 };
$[2] = t0;
$[3] = z;
} else {
z = $[3];
@@ -74,31 +74,31 @@ function Component(props) {
const count = renderedItems.length;
const c_5 = $[5] !== count;
let t6;
let t0;
if (c_5) {
t6 = <h1>{count} Items</h1>;
t0 = <h1>{count} Items</h1>;
$[5] = count;
$[6] = t6;
$[6] = t0;
} else {
t6 = $[6];
t0 = $[6];
}
const c_7 = $[7] !== t6;
const c_7 = $[7] !== t0;
const c_8 = $[8] !== renderedItems;
let t9;
let t1;
if (c_7 || c_8) {
t9 = (
t1 = (
<div>
{t6}
{t0}
{renderedItems}
</div>
);
$[7] = t6;
$[7] = t0;
$[8] = renderedItems;
$[9] = t9;
$[9] = t1;
} else {
t9 = $[9];
t1 = $[9];
}
return t9;
return t1;
}
```
@@ -24,25 +24,21 @@ function component() {
}
const x = t0[0];
const setX = t0[1];
const c_1 = $[1] !== setX;
let handler;
if (c_1) {
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
handler = (v) => setX(v);
$[1] = setX;
$[2] = handler;
$[1] = handler;
} else {
handler = $[2];
handler = $[1];
}
const c_3 = $[3] !== handler;
let t4;
if (c_3) {
t4 = <Foo handler={handler}></Foo>;
$[3] = handler;
$[4] = t4;
let t1;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <Foo handler={handler}></Foo>;
$[2] = t1;
} else {
t4 = $[4];
t1 = $[2];
}
return t4;
return t1;
}
```
@@ -61,16 +61,16 @@ function ComponentA(props) {
}
const c_5 = $[5] !== a;
const c_6 = $[6] !== b;
let t7;
let t0;
if (c_5 || c_6) {
t7 = <Foo a={a} b={b}></Foo>;
t0 = <Foo a={a} b={b}></Foo>;
$[5] = a;
$[6] = b;
$[7] = t7;
$[7] = t0;
} else {
t7 = $[7];
t0 = $[7];
}
return t7;
return t0;
}
function ComponentB(props) {
@@ -100,16 +100,16 @@ function ComponentB(props) {
}
const c_5 = $[5] !== a;
const c_6 = $[6] !== b;
let t7;
let t0;
if (c_5 || c_6) {
t7 = <Foo a={a} b={b}></Foo>;
t0 = <Foo a={a} b={b}></Foo>;
$[5] = a;
$[6] = b;
$[7] = t7;
$[7] = t0;
} else {
t7 = $[7];
t0 = $[7];
}
return t7;
return t0;
}
function Foo() {}
@@ -37,18 +37,14 @@ function Component(props) {
a = $[0];
b = $[1];
}
const c_2 = $[2] !== a;
const c_3 = $[3] !== b;
let t4;
if (c_2 || c_3) {
t4 = <div a={a} b={b}></div>;
$[2] = a;
$[3] = b;
$[4] = t4;
let t0;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t0 = <div a={a} b={b}></div>;
$[2] = t0;
} else {
t4 = $[4];
t0 = $[2];
}
return t4;
return t0;
}
```
@@ -34,33 +34,27 @@ function Component(props) {
} else {
x = $[0];
}
const c_1 = $[1] !== x;
let y;
if (c_1) {
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
y = useFreeze(x);
$[1] = x;
$[2] = y;
$[1] = y;
} else {
y = $[2];
y = $[1];
}
foo(y, x);
const c_3 = $[3] !== x;
const c_4 = $[4] !== y;
let t5;
if (c_3 || c_4) {
t5 = (
let t0;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t0 = (
<Component>
{x}
{y}
</Component>
);
$[3] = x;
$[4] = y;
$[5] = t5;
$[2] = t0;
} else {
t5 = $[5];
t0 = $[2];
}
return t5;
return t0;
}
```
@@ -80,16 +80,16 @@ function Component(props) {
}
const c_5 = $[5] !== a;
const c_6 = $[6] !== b;
let t7;
let t0;
if (c_5 || c_6) {
t7 = <Foo a={a} b={b}></Foo>;
t0 = <Foo a={a} b={b}></Foo>;
$[5] = a;
$[6] = b;
$[7] = t7;
$[7] = t0;
} else {
t7 = $[7];
t0 = $[7];
}
return t7;
return t0;
}
```
@@ -59,16 +59,16 @@ function Component(props) {
}
const c_4 = $[4] !== a;
const c_5 = $[5] !== b;
let t6;
let t0;
if (c_4 || c_5) {
t6 = <Foo a={a} b={b}></Foo>;
t0 = <Foo a={a} b={b}></Foo>;
$[4] = a;
$[5] = b;
$[6] = t6;
$[6] = t0;
} else {
t6 = $[6];
t0 = $[6];
}
return t6;
return t0;
}
function compute() {}
@@ -25,16 +25,16 @@ function foo(a, b, c) {
x = { a: a };
const c_4 = $[4] !== b;
const c_5 = $[5] !== c;
let t6;
let t0;
if (c_4 || c_5) {
t6 = [b, c];
t0 = [b, c];
$[4] = b;
$[5] = c;
$[6] = t6;
$[6] = t0;
} else {
t6 = $[6];
t0 = $[6];
}
x.y = t6;
x.y = t0;
$[0] = a;
$[1] = b;
$[2] = c;
@@ -68,16 +68,16 @@ function Component(props) {
}
const c_5 = $[5] !== a;
const c_6 = $[6] !== b;
let t7;
let t0;
if (c_5 || c_6) {
t7 = <Foo a={a} b={b}></Foo>;
t0 = <Foo a={a} b={b}></Foo>;
$[5] = a;
$[6] = b;
$[7] = t7;
$[7] = t0;
} else {
t7 = $[7];
t0 = $[7];
}
return t7;
return t0;
}
```
@@ -56,16 +56,16 @@ function Component(props) {
}
const c_4 = $[4] !== a;
const c_5 = $[5] !== b;
let t6;
let t0;
if (c_4 || c_5) {
t6 = <Foo a={a} b={b}></Foo>;
t0 = <Foo a={a} b={b}></Foo>;
$[4] = a;
$[5] = b;
$[6] = t6;
$[6] = t0;
} else {
t6 = $[6];
t0 = $[6];
}
return t6;
return t0;
}
function compute() {}
@@ -27,32 +27,28 @@ function Foo(props) {
} else {
t0 = $[0];
}
const c_1 = $[1] !== t0;
let t2;
if (c_1) {
t2 = <div>{t0}</div>;
$[1] = t0;
$[2] = t2;
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <div>{t0}</div>;
$[1] = t1;
} else {
t2 = $[2];
t1 = $[1];
}
const c_3 = $[3] !== props.greeting;
const c_4 = $[4] !== t2;
let t5;
if (c_3 || c_4) {
t5 = (
const c_2 = $[2] !== props.greeting;
let t2;
if (c_2) {
t2 = (
<>
Hello {props.greeting}
{t2}
{t1}
</>
);
$[3] = props.greeting;
$[4] = t2;
$[5] = t5;
$[2] = props.greeting;
$[3] = t2;
} else {
t5 = $[5];
t2 = $[3];
}
return t5;
return t2;
}
```
@@ -16,35 +16,35 @@ function Component(props) {
function Component(props) {
const $ = React.useMemoCache();
const c_0 = $[0] !== props;
let t1;
let t0;
if (c_0) {
t1 = props.cond ? props.foo : props.bar;
t0 = props.cond ? props.foo : props.bar;
$[0] = props;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
const c_2 = $[2] !== t1;
let t3;
const c_2 = $[2] !== t0;
let t1;
if (c_2) {
t3 = { bar: t1 };
$[2] = t1;
$[3] = t3;
t1 = { bar: t0 };
$[2] = t0;
$[3] = t1;
} else {
t3 = $[3];
t1 = $[3];
}
const c_4 = $[4] !== props;
const c_5 = $[5] !== t3;
let t6;
const c_5 = $[5] !== t1;
let t2;
if (c_4 || c_5) {
t6 = <Component {...props} {...t3}></Component>;
t2 = <Component {...props} {...t1}></Component>;
$[4] = props;
$[5] = t3;
$[6] = t6;
$[5] = t1;
$[6] = t2;
} else {
t6 = $[6];
t2 = $[6];
}
return t6;
return t2;
}
```
@@ -21,37 +21,37 @@ function component(props) {
function component(props) {
const $ = React.useMemoCache();
const c_0 = $[0] !== props;
let t1;
let t0;
if (c_0) {
t1 = props.a || (props.b && props.c && props.d);
t0 = props.a || (props.b && props.c && props.d);
$[0] = props;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
const a = t1;
const a = t0;
const c_2 = $[2] !== props;
let t3;
let t1;
if (c_2) {
t3 = (props.a && props.b && props.c) || props.d;
t1 = (props.a && props.b && props.c) || props.d;
$[2] = props;
$[3] = t3;
$[3] = t1;
} else {
t3 = $[3];
t1 = $[3];
}
const b = t3;
const b = t1;
const c_4 = $[4] !== a;
const c_5 = $[5] !== b;
let t6;
let t2;
if (c_4 || c_5) {
t6 = { a: a, b: b };
t2 = { a: a, b: b };
$[4] = a;
$[5] = b;
$[6] = t6;
$[6] = t2;
} else {
t6 = $[6];
t2 = $[6];
}
return t6;
return t2;
}
```
@@ -16,39 +16,39 @@ function component(props) {
function component(props) {
const $ = React.useMemoCache();
const c_0 = $[0] !== props;
let t1;
let t0;
if (c_0) {
t1 = props.a || (props.b && props.c && props.d);
t0 = props.a || (props.b && props.c && props.d);
$[0] = props;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
const a = t1;
const a = t0;
const c_2 = $[2] !== props;
let t3;
let t1;
if (c_2) {
t3 = (props.a && props.b && props.c) || props.d;
t1 = (props.a && props.b && props.c) || props.d;
$[2] = props;
$[3] = t3;
$[3] = t1;
} else {
t3 = $[3];
t1 = $[3];
}
const b = t3;
const b = t1;
const c_4 = $[4] !== a;
const c_5 = $[5] !== b;
const c_6 = $[6] !== props;
let t7;
let t2;
if (c_4 || c_5 || c_6) {
t7 = a ? b : props.c;
t2 = a ? b : props.c;
$[4] = a;
$[5] = b;
$[6] = props;
$[7] = t7;
$[7] = t2;
} else {
t7 = $[7];
t2 = $[7];
}
return t7;
return t2;
}
```
@@ -37,16 +37,16 @@ function component(t8) {
}
const c_4 = $[4] !== y;
const c_5 = $[5] !== z;
let t6;
let t0;
if (c_4 || c_5) {
t6 = { y: y, z: z };
t0 = { y: y, z: z };
$[4] = y;
$[5] = z;
$[6] = t6;
$[6] = t0;
} else {
t6 = $[6];
t0 = $[6];
}
return t6;
return t0;
}
```
@@ -44,15 +44,15 @@ function foo(a, b, c) {
y = $[6];
}
const c_7 = $[7] !== y;
let t8;
let t0;
if (c_7) {
t8 = <div>{y}</div>;
t0 = <div>{y}</div>;
$[7] = y;
$[8] = t8;
$[8] = t0;
} else {
t8 = $[8];
t0 = $[8];
}
x.push(t8);
x.push(t0);
}
$[0] = a;
$[1] = b;
@@ -37,16 +37,16 @@ function Component(props) {
}
const c_3 = $[3] !== x;
const c_4 = $[4] !== child;
let t5;
let t0;
if (c_3 || c_4) {
t5 = <Component data={x}>{child}</Component>;
t0 = <Component data={x}>{child}</Component>;
$[3] = x;
$[4] = child;
$[5] = t5;
$[5] = t0;
} else {
t5 = $[5];
t0 = $[5];
}
return t5;
return t0;
}
```
@@ -39,15 +39,15 @@ function foo(a, b, c) {
y = $[5];
}
const c_6 = $[6] !== y;
let t7;
let t0;
if (c_6) {
t7 = <div>{y}</div>;
t0 = <div>{y}</div>;
$[6] = y;
$[7] = t7;
$[7] = t0;
} else {
t7 = $[7];
t0 = $[7];
}
x.push(t7);
x.push(t0);
} else {
x.push(c);
}
@@ -37,15 +37,15 @@ function f(a, b) {
x = $[2];
}
const c_3 = $[3] !== x;
let t4;
let t0;
if (c_3) {
t4 = <div>{x}</div>;
t0 = <div>{x}</div>;
$[3] = x;
$[4] = t4;
$[4] = t0;
} else {
t4 = $[4];
t0 = $[4];
}
return t4;
return t0;
}
```
@@ -59,16 +59,16 @@ function Component(props) {
y.push(props.p2);
const c_5 = $[5] !== x$0;
const c_6 = $[6] !== y;
let t7;
let t0;
if (c_5 || c_6) {
t7 = <Component x={x$0} y={y}></Component>;
t0 = <Component x={x$0} y={y}></Component>;
$[5] = x$0;
$[6] = y;
$[7] = t7;
$[7] = t0;
} else {
t7 = $[7];
t0 = $[7];
}
return t7;
return t0;
}
```
@@ -98,9 +98,9 @@ function foo(a, b, c) {
}
const c_11 = $[11] !== y;
const c_12 = $[12] !== x$0;
let t13;
let t0;
if (c_11 || c_12) {
t13 = (
t0 = (
<div>
{y}
{x$0}
@@ -108,11 +108,11 @@ function foo(a, b, c) {
);
$[11] = y;
$[12] = x$0;
$[13] = t13;
$[13] = t0;
} else {
t13 = $[13];
t0 = $[13];
}
return t13;
return t0;
}
```
@@ -45,18 +45,16 @@ function Component(props) {
} else {
y = $[2];
}
const c_4 = $[4] !== x$0;
const c_5 = $[5] !== y;
let t6;
if (c_4 || c_5) {
t6 = <Component x={x$0} y={y}></Component>;
$[4] = x$0;
$[5] = y;
$[6] = t6;
const c_4 = $[4] !== y;
let t0;
if (c_4) {
t0 = <Component x={x$0} y={y}></Component>;
$[4] = y;
$[5] = t0;
} else {
t6 = $[6];
t0 = $[5];
}
return t6;
return t0;
}
```
@@ -28,19 +28,17 @@ function sequence(props) {
} else {
t0 = $[0];
}
const c_1 = $[1] !== t0;
let x;
if (c_1) {
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
x = t0;
while ((foo(), true)) {
foo();
2;
x = 2;
}
$[1] = t0;
$[2] = x;
$[1] = x;
} else {
x = $[2];
x = $[1];
}
return x;
}
@@ -18,22 +18,26 @@ export default function foo(x, y) {
const $ = React.useMemoCache();
if (x) {
const c_0 = $[0] !== y;
let t1;
let t0;
if (c_0) {
t1 = foo(false, y);
t0 = foo(false, y);
$[0] = y;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
return t1;
return t0;
}
const t1 = y * 10;
const c_2 = $[2] !== t1;
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = [y * 10];
$[2] = t2;
if (c_2) {
t2 = [t1];
$[2] = t1;
$[3] = t2;
} else {
t2 = $[2];
t2 = $[3];
}
return t2;
}
@@ -32,14 +32,14 @@ function Component(props) {
a = [];
b = {};
foo(a, b);
let t2;
let t0;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = foo();
$[2] = t2;
t0 = foo();
$[2] = t0;
} else {
t2 = $[2];
t0 = $[2];
}
if (t2) {
if (t0) {
const _ = <div a={a}></div>;
}
@@ -50,18 +50,14 @@ function Component(props) {
a = $[0];
b = $[1];
}
const c_3 = $[3] !== a;
const c_4 = $[4] !== b;
let t5;
if (c_3 || c_4) {
t5 = <div a={a} b={b}></div>;
$[3] = a;
$[4] = b;
$[5] = t5;
let t1;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <div a={a} b={b}></div>;
$[3] = t1;
} else {
t5 = $[5];
t1 = $[3];
}
return t5;
return t1;
}
```
@@ -36,18 +36,14 @@ function Component(props) {
a = $[0];
b = $[1];
}
const c_2 = $[2] !== a;
const c_3 = $[3] !== b;
let t4;
if (c_2 || c_3) {
t4 = <div a={a} b={b}></div>;
$[2] = a;
$[3] = b;
$[4] = t4;
let t0;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t0 = <div a={a} b={b}></div>;
$[2] = t0;
} else {
t4 = $[4];
t0 = $[2];
}
return t4;
return t0;
}
```
@@ -23,15 +23,13 @@ function foo() {
} else {
x = $[0];
}
const c_1 = $[1] !== x;
let y;
if (c_1) {
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
y = {};
y.x = x;
$[1] = x;
$[2] = y;
$[1] = y;
} else {
y = $[2];
y = $[1];
}
return y;
}
@@ -85,16 +85,16 @@ function Component(props) {
y$0.push(props.p4);
const c_7 = $[7] !== y$0;
const c_8 = $[8] !== child;
let t9;
let t0;
if (c_7 || c_8) {
t9 = <Component data={y$0}>{child}</Component>;
t0 = <Component data={y$0}>{child}</Component>;
$[7] = y$0;
$[8] = child;
$[9] = t9;
$[9] = t0;
} else {
t9 = $[9];
t0 = $[9];
}
return t9;
return t0;
}
```
@@ -69,16 +69,16 @@ function Component(props) {
y$0.push(props.p4);
const c_7 = $[7] !== y$0;
const c_8 = $[8] !== child;
let t9;
let t0;
if (c_7 || c_8) {
t9 = <Component data={y$0}>{child}</Component>;
t0 = <Component data={y$0}>{child}</Component>;
$[7] = y$0;
$[8] = child;
$[9] = t9;
$[9] = t0;
} else {
t9 = $[9];
t0 = $[9];
}
return t9;
return t0;
}
```
@@ -16,37 +16,37 @@ function ternary(props) {
function ternary(props) {
const $ = React.useMemoCache();
const c_0 = $[0] !== props;
let t1;
let t0;
if (c_0) {
t1 = props.a && props.b ? props.c || props.d : props.e ?? props.f;
t0 = props.a && props.b ? props.c || props.d : props.e ?? props.f;
$[0] = props;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
const a = t1;
const a = t0;
const c_2 = $[2] !== props;
let t3;
let t1;
if (c_2) {
t3 = props.a ? (props.b && props.c ? props.d : props.e) : props.f;
t1 = props.a ? (props.b && props.c ? props.d : props.e) : props.f;
$[2] = props;
$[3] = t3;
$[3] = t1;
} else {
t3 = $[3];
t1 = $[3];
}
const b = t3;
const b = t1;
const c_4 = $[4] !== a;
const c_5 = $[5] !== b;
let t6;
let t2;
if (c_4 || c_5) {
t6 = a ? b : (null, null);
t2 = a ? b : (null, null);
$[4] = a;
$[5] = b;
$[6] = t6;
$[6] = t2;
} else {
t6 = $[6];
t2 = $[6];
}
return t6;
return t2;
}
```
@@ -34,16 +34,12 @@ function component() {
} else {
t1 = $[1];
}
const c_2 = $[2] !== t0;
const c_3 = $[3] !== t1;
let x;
if (c_2 || c_3) {
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
x = { u: t0, v: t1 };
$[2] = t0;
$[3] = t1;
$[4] = x;
$[2] = x;
} else {
x = $[4];
x = $[2];
}
const u = x.u;
const v = x.v;
@@ -38,18 +38,16 @@ function component() {
} else {
o = $[1];
}
const c_2 = $[2] !== o;
let x;
if (c_2) {
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
x = {};
x.t = p;
const z = x.t;
x.t = o;
$[2] = o;
$[3] = x;
$[2] = x;
} else {
x = $[3];
x = $[2];
}
const y = x.t;
@@ -37,14 +37,28 @@ function component(a) {
const m = !t.t;
const e = ~t.t;
const f = typeof t.t;
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = { z: z, p: p, q: q, n: n, m: m, e: e, f: f };
$[2] = t2;
const c_2 = $[2] !== z;
const c_3 = $[3] !== p;
const c_4 = $[4] !== q;
const c_5 = $[5] !== n;
const c_6 = $[6] !== m;
const c_7 = $[7] !== e;
const c_8 = $[8] !== f;
let t0;
if (c_2 || c_3 || c_4 || c_5 || c_6 || c_7 || c_8) {
t0 = { z: z, p: p, q: q, n: n, m: m, e: e, f: f };
$[2] = z;
$[3] = p;
$[4] = q;
$[5] = n;
$[6] = m;
$[7] = e;
$[8] = f;
$[9] = t0;
} else {
t2 = $[2];
t0 = $[9];
}
return t2;
return t0;
}
```
@@ -21,12 +21,18 @@ function foo(props) {
const y = x$0;
const x$1 = x$0 - 1;
const z = x$1;
const c_0 = $[0] !== x$1;
const c_1 = $[1] !== y;
const c_2 = $[2] !== z;
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
if (c_0 || c_1 || c_2) {
t0 = { x: x$1, y: y, z: z };
$[0] = t0;
$[0] = x$1;
$[1] = y;
$[2] = z;
$[3] = t0;
} else {
t0 = $[0];
t0 = $[3];
}
return t0;
}