mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Initial pass at dead code elimination
This is a first pass at DCE without having read any literate on the subject, so
lemme know if there's a better approach. That said the algorithm is:
* Keep a `Set<Identifier>` of identifiers that are used (and whose constructing
logic cannot be removed).
* Do a first RPO iteration of all block's phis. Any phi operand that
participates in a loop is preemptively marked as "used" even if it isn't
strictly used somewhere. This step is necessary bc these operands may otherwise
not be used.
* Do a second post-order iteration of all blocks, including iterating first
their terminals, then reverse iteration of instructions, then their phis. Mark
the operands of each as used as we encounter them, and prune instructions whose
lvalue is never used.
For now I was conservative about which types of instructions can be pruned. For
example, call instructions are never pruned, even if the result of the call is
never used.
However one catch is that we currently prune instructions that cause values to
become frozen. We had planned to add runtime calls (in dev) to freeze values for
runtime enforcement, and if we want to do that we can always add these
instructions back (or replace them with explicit freeze calls).
There are a few potential next steps but we should discuss whether they're worth
it:
* Use fixpoint iteration to find exactly which operands are actually used. This
would allow us to to prune cases such as `let x = 0; while (...) { x += 1 }` eg
where there's a phi but the result is never used. Such cases should be rare in
practice though.
* Eliminate more types of instructions, eg eliminate function calls that don't
have any mutable arguments.
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
import { NodePath } from "@babel/traverse";
|
||||
import * as t from "@babel/types";
|
||||
import { CompilerError } from "./CompilerError";
|
||||
import {
|
||||
HIRFunction,
|
||||
lower,
|
||||
@@ -18,7 +17,7 @@ import {
|
||||
inferMutableRanges,
|
||||
inferReferenceEffects,
|
||||
} from "./Inference";
|
||||
import { constantPropagation } from "./Optimization";
|
||||
import { constantPropagation, deadCodeElimination } from "./Optimization";
|
||||
import {
|
||||
alignReactiveScopesToBlockScopes,
|
||||
buildReactiveBlocks,
|
||||
@@ -71,6 +70,10 @@ export function* run(
|
||||
inferReferenceEffects(hir);
|
||||
yield log({ kind: "hir", name: "InferReferenceEffects", value: hir });
|
||||
|
||||
// Note: Has to come after infer reference effects because "dead" code may still affect inference
|
||||
deadCodeElimination(hir);
|
||||
yield log({ kind: "hir", name: "DeadCodeElimination", value: hir });
|
||||
|
||||
inferMutableRanges(hir);
|
||||
yield log({ kind: "hir", name: "InferMutableRanges", value: hir });
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
|
||||
switch (terminal.kind) {
|
||||
case "if": {
|
||||
const testValue = read(constants, terminal.test);
|
||||
if (testValue !== null && testValue.kind === "Primitive") {
|
||||
if (testValue !== null) {
|
||||
hasChanges = true;
|
||||
const targetBlockId = Boolean(testValue.value)
|
||||
? terminal.consequent
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* 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 {
|
||||
BlockId,
|
||||
HIRFunction,
|
||||
Identifier,
|
||||
Instruction,
|
||||
InstructionValue,
|
||||
} from "../HIR";
|
||||
import {
|
||||
eachInstructionValueOperand,
|
||||
eachTerminalOperand,
|
||||
} from "../HIR/visitors";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
|
||||
/**
|
||||
* Implements dead-code elimination, eliminating instructions whose values are unused.
|
||||
*
|
||||
* Note that unreachable blocks are already pruned during HIR construction.
|
||||
*/
|
||||
export function deadCodeElimination(fn: HIRFunction): void {
|
||||
const used = new Set<Identifier>();
|
||||
|
||||
// Find any phi operands involved in a loop, which might otherwise appear as dead
|
||||
// code when using a reverse iteration.
|
||||
//
|
||||
// A more advanced algorithm could still prune some of these operands
|
||||
// let's keep it simple for now
|
||||
const seen = new Set<BlockId>();
|
||||
for (const [, block] of fn.body.blocks) {
|
||||
for (const phi of block.phis) {
|
||||
for (const [pred, operand] of phi.operands) {
|
||||
if (!seen.has(pred)) {
|
||||
used.add(operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
seen.add(block.id);
|
||||
}
|
||||
|
||||
// Iterate blocks in postorder (successors before predecessors, excepting loops)
|
||||
// to find usages before declarations
|
||||
const reversedBlocks = [...fn.body.blocks.values()].reverse();
|
||||
for (const block of reversedBlocks) {
|
||||
for (const operand of eachTerminalOperand(block.terminal)) {
|
||||
used.add(operand.identifier);
|
||||
}
|
||||
|
||||
let nextInstructions: Array<Instruction> | null = null;
|
||||
for (let i = block.instructions.length - 1; i >= 0; i--) {
|
||||
const instr = block.instructions[i]!;
|
||||
if (
|
||||
!used.has(instr.lvalue.place.identifier) &&
|
||||
pruneableValue(instr.value) &&
|
||||
// Can't prune the last value of a value block, that's its value!
|
||||
!(block.kind !== "block" && i === block.instructions.length - 1)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
used.add(instr.lvalue.place.identifier);
|
||||
nextInstructions ??= [];
|
||||
nextInstructions.push(instr);
|
||||
for (const operand of eachInstructionValueOperand(instr.value)) {
|
||||
used.add(operand.identifier);
|
||||
}
|
||||
}
|
||||
if (nextInstructions !== null) {
|
||||
nextInstructions.reverse();
|
||||
block.instructions = nextInstructions;
|
||||
}
|
||||
for (const phi of block.phis) {
|
||||
if (used.has(phi.id)) {
|
||||
for (const [, operand] of phi.operands) {
|
||||
used.add(operand);
|
||||
}
|
||||
} else {
|
||||
for (const [, operand] of phi.operands) {
|
||||
if (used.has(operand)) {
|
||||
used.add(phi.id);
|
||||
for (const [, operand] of phi.operands) {
|
||||
used.add(operand);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it is safe to prune an instruction with the given value.
|
||||
* Functions which may have side-
|
||||
*/
|
||||
function pruneableValue(value: InstructionValue): boolean {
|
||||
switch (value.kind) {
|
||||
case "CallExpression":
|
||||
case "ComputedCall":
|
||||
case "ComputedStore":
|
||||
case "PropertyCall":
|
||||
case "PropertyStore": {
|
||||
// Mutating instructions are not safe to prune.
|
||||
// TODO: we could be more precise and make this conditional on whether
|
||||
// any arguments are actually modified
|
||||
return false;
|
||||
}
|
||||
case "NewExpression":
|
||||
case "UnsupportedNode":
|
||||
case "TaggedTemplateExpression": {
|
||||
// Potentially safe to prune, since they should just be creating new values
|
||||
return false;
|
||||
}
|
||||
case "ArrayExpression":
|
||||
case "BinaryExpression":
|
||||
case "ComputedLoad":
|
||||
case "ComputedStore":
|
||||
case "FunctionExpression":
|
||||
case "Identifier":
|
||||
case "JsxExpression":
|
||||
case "JsxFragment":
|
||||
case "JSXText":
|
||||
case "ObjectExpression":
|
||||
case "Primitive":
|
||||
case "PropertyLoad":
|
||||
case "TemplateLiteral":
|
||||
case "TypeCastExpression":
|
||||
case "UnaryExpression": {
|
||||
// Definitely safe to prune since they are read-only
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(value, `Unexepcted value kind '${(value as any).kind}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,3 +6,4 @@
|
||||
*/
|
||||
|
||||
export { constantPropagation } from "./ConstantPropagation";
|
||||
export { deadCodeElimination } from "./DeadCodeElimination";
|
||||
|
||||
@@ -15,10 +15,6 @@ function f() {
|
||||
|
||||
```javascript
|
||||
function f() {
|
||||
const x = 1;
|
||||
|
||||
const x$0 = 2;
|
||||
4;
|
||||
return 6;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ function Component(props) {
|
||||
a = [];
|
||||
b = {};
|
||||
foo(a, b);
|
||||
const _ = <div a={a}></div>;
|
||||
|
||||
foo(b);
|
||||
$[0] = a;
|
||||
$[1] = b;
|
||||
|
||||
+5
-6
@@ -29,19 +29,18 @@ function component(a) {
|
||||
} else {
|
||||
z = $[1];
|
||||
}
|
||||
const x = undefined;
|
||||
const c_2 = $[2] !== z;
|
||||
let x$0;
|
||||
let x;
|
||||
if (c_2) {
|
||||
x$0 = function () {
|
||||
x = function () {
|
||||
z;
|
||||
};
|
||||
$[2] = z;
|
||||
$[3] = x$0;
|
||||
$[3] = x;
|
||||
} else {
|
||||
x$0 = $[3];
|
||||
x = $[3];
|
||||
}
|
||||
return x$0;
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -22,7 +22,6 @@ function component() {
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const x = t0[0];
|
||||
const setX = t0[1];
|
||||
let handler;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
|
||||
@@ -20,7 +20,7 @@ function foo() {
|
||||
let y;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
y = 0;
|
||||
for (const x = 100; 10, false; 100) {
|
||||
for (const x = 100; false; 100) {
|
||||
y = y + 1;
|
||||
}
|
||||
$[0] = y;
|
||||
|
||||
@@ -18,11 +18,10 @@ function foo() {
|
||||
```javascript
|
||||
function foo() {
|
||||
const $ = React.useMemoCache();
|
||||
const x = 100;
|
||||
let y;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
y = 0;
|
||||
while ((10, false)) {
|
||||
while (false) {
|
||||
y = y + 1;
|
||||
}
|
||||
$[0] = y;
|
||||
|
||||
@@ -27,18 +27,8 @@ function foo() {
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const a = 1;
|
||||
const b = 2;
|
||||
const c = 3;
|
||||
const d = 3;
|
||||
const e = 9;
|
||||
const f = 3;
|
||||
const g = -6;
|
||||
|
||||
console.log("foo");
|
||||
|
||||
const h = -6;
|
||||
const i = -6;
|
||||
const j = -6;
|
||||
return j;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@ function Component(props) {
|
||||
a = [];
|
||||
b = {};
|
||||
new Foo(a, b);
|
||||
|
||||
const _ = <div a={a}></div>;
|
||||
new Foo(b);
|
||||
$[0] = a;
|
||||
$[1] = b;
|
||||
|
||||
@@ -33,7 +33,6 @@ function foo(a, b) {
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
<div>{x}</div>;
|
||||
|
||||
const y = [];
|
||||
if (x.length) {
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ function f(reader) {
|
||||
## Error
|
||||
|
||||
```
|
||||
[ReactForget] Todo: (CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare 'value$0'
|
||||
[ReactForget] Todo: (CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare 'value'
|
||||
```
|
||||
|
||||
|
||||
@@ -32,10 +32,9 @@ function foo(props) {
|
||||
for (
|
||||
let x = 0;
|
||||
x > props.min && x < props.max;
|
||||
x = x$0 + (props.cond ? props.increment : (2, 2)), x
|
||||
x = x$0 + (props.cond ? props.increment : 2), x
|
||||
) {
|
||||
const x$0 = x * 2;
|
||||
const y$1 = y + x$0;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
+15
-16
@@ -29,36 +29,35 @@ function Component(props) {
|
||||
const $ = React.useMemoCache();
|
||||
const cond = props.cond;
|
||||
const x = props.x;
|
||||
const a = undefined;
|
||||
const c_0 = $[0] !== cond;
|
||||
const c_1 = $[1] !== x;
|
||||
let a$0;
|
||||
let a;
|
||||
if (c_0 || c_1) {
|
||||
a$0 = undefined;
|
||||
a = undefined;
|
||||
if (cond) {
|
||||
const a$1 = x;
|
||||
a$0 = a$1;
|
||||
const a$0 = x;
|
||||
a = a$0;
|
||||
} else {
|
||||
let a$2;
|
||||
let a$1;
|
||||
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
a$2 = [];
|
||||
$[3] = a$2;
|
||||
a$1 = [];
|
||||
$[3] = a$1;
|
||||
} else {
|
||||
a$2 = $[3];
|
||||
a$1 = $[3];
|
||||
}
|
||||
a$0 = a$2;
|
||||
a = a$1;
|
||||
}
|
||||
$[0] = cond;
|
||||
$[1] = x;
|
||||
$[2] = a$0;
|
||||
$[2] = a;
|
||||
} else {
|
||||
a$0 = $[2];
|
||||
a = $[2];
|
||||
}
|
||||
|
||||
useFreeze(a$0);
|
||||
useFreeze(a$0);
|
||||
call(a$0);
|
||||
return a$0;
|
||||
useFreeze(a);
|
||||
useFreeze(a);
|
||||
call(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
function useFreeze(x) {}
|
||||
|
||||
@@ -15,19 +15,8 @@ function Component(c) {
|
||||
|
||||
```javascript
|
||||
function Component(c) {
|
||||
const $ = React.useMemoCache();
|
||||
const c_0 = $[0] !== c;
|
||||
let x;
|
||||
if (c_0) {
|
||||
x = { c: c };
|
||||
mutate(x);
|
||||
$[0] = c;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
const a = x;
|
||||
const b = a;
|
||||
const x = { c: c };
|
||||
mutate(x);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -41,10 +41,6 @@ function foo(a, b, c) {
|
||||
} else {
|
||||
y = $[3];
|
||||
}
|
||||
<div>
|
||||
{x}
|
||||
{y}
|
||||
</div>;
|
||||
const c_4 = $[4] !== x;
|
||||
const c_5 = $[5] !== y.method;
|
||||
const c_6 = $[6] !== b;
|
||||
|
||||
@@ -29,7 +29,6 @@ function foo(a, b, c) {
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
<div>{x}</div>;
|
||||
|
||||
const method = x.method;
|
||||
const c_2 = $[2] !== method;
|
||||
|
||||
@@ -28,7 +28,6 @@ function foo(a, b, c) {
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
<div>{x}</div>;
|
||||
const c_2 = $[2] !== x;
|
||||
const c_3 = $[3] !== b;
|
||||
let y;
|
||||
|
||||
@@ -14,8 +14,6 @@ function foo(a, b, c) {
|
||||
```javascript
|
||||
function foo(a, b, c) {
|
||||
a[b] = c[b];
|
||||
1;
|
||||
2;
|
||||
a[3] = c[b * 4];
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,10 @@ function foo(a, b, c) {
|
||||
|
||||
```javascript
|
||||
function foo(a, b, c) {
|
||||
const x = a.x;
|
||||
const y = b.c.d;
|
||||
y.z = c.d.e;
|
||||
|
||||
foo(a.b.c);
|
||||
[a.b.c];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -55,7 +55,6 @@ function Component(props) {
|
||||
x$0 = $[3];
|
||||
}
|
||||
|
||||
const _ = <Component x={x$0}></Component>;
|
||||
y.push(props.p2);
|
||||
const c_5 = $[5] !== x$0;
|
||||
const c_6 = $[6] !== y;
|
||||
|
||||
@@ -36,7 +36,6 @@ function Component(props) {
|
||||
} else {
|
||||
x$0 = $[3];
|
||||
}
|
||||
const _ = <Component x={x$0}></Component>;
|
||||
|
||||
y.push(props.p1);
|
||||
$[0] = props.p0;
|
||||
|
||||
@@ -37,7 +37,6 @@ function Component(props) {
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.useMemoCache();
|
||||
const x = undefined;
|
||||
const c_0 = $[0] !== props.cond;
|
||||
const c_1 = $[1] !== props.test;
|
||||
const c_2 = $[2] !== props.v0;
|
||||
@@ -46,35 +45,35 @@ function Component(props) {
|
||||
const c_5 = $[5] !== props.cond2;
|
||||
const c_6 = $[6] !== props.b;
|
||||
const c_7 = $[7] !== props.c;
|
||||
let x$0;
|
||||
let x;
|
||||
if (c_0 || c_1 || c_2 || c_3 || c_4 || c_5 || c_6 || c_7) {
|
||||
x$0 = undefined;
|
||||
x = undefined;
|
||||
bb1: if (props.cond) {
|
||||
switch (props.test) {
|
||||
case 0: {
|
||||
const x$1 = props.v0;
|
||||
x$0 = x$1;
|
||||
const x$0 = props.v0;
|
||||
x = x$0;
|
||||
break bb1;
|
||||
}
|
||||
case 1: {
|
||||
const x$2 = props.v1;
|
||||
x$0 = x$2;
|
||||
const x$1 = props.v1;
|
||||
x = x$1;
|
||||
break bb1;
|
||||
}
|
||||
case 2: {
|
||||
}
|
||||
default: {
|
||||
const x$3 = props.v2;
|
||||
x$0 = x$3;
|
||||
const x$2 = props.v2;
|
||||
x = x$2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (props.cond2) {
|
||||
const x$4 = props.b;
|
||||
x$0 = x$4;
|
||||
const x$3 = props.b;
|
||||
x = x$3;
|
||||
} else {
|
||||
const x$5 = props.c;
|
||||
x$0 = x$5;
|
||||
const x$4 = props.c;
|
||||
x = x$4;
|
||||
}
|
||||
}
|
||||
$[0] = props.cond;
|
||||
@@ -85,11 +84,11 @@ function Component(props) {
|
||||
$[5] = props.cond2;
|
||||
$[6] = props.b;
|
||||
$[7] = props.c;
|
||||
$[8] = x$0;
|
||||
$[8] = x;
|
||||
} else {
|
||||
x$0 = $[8];
|
||||
x = $[8];
|
||||
}
|
||||
x$0;
|
||||
x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -19,7 +19,6 @@ function foo() {}
|
||||
```javascript
|
||||
function sequence(props) {
|
||||
const $ = React.useMemoCache();
|
||||
null;
|
||||
Math.max(1, 2);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
@@ -33,7 +32,6 @@ function sequence(props) {
|
||||
x = t0;
|
||||
while ((foo(), true)) {
|
||||
foo();
|
||||
2;
|
||||
x = 2;
|
||||
}
|
||||
$[1] = x;
|
||||
|
||||
@@ -22,20 +22,19 @@ function foo() {
|
||||
function mutate() {}
|
||||
function foo() {
|
||||
const $ = React.useMemoCache();
|
||||
const a = {};
|
||||
let c$2;
|
||||
let c$1;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
const b = {};
|
||||
const c = {};
|
||||
const a$0 = b;
|
||||
const b$1 = c;
|
||||
c$2 = a$0;
|
||||
mutate(a$0, b$1);
|
||||
$[0] = c$2;
|
||||
const a = b;
|
||||
const b$0 = c;
|
||||
c$1 = a;
|
||||
mutate(a, b$0);
|
||||
$[0] = c$1;
|
||||
} else {
|
||||
c$2 = $[0];
|
||||
c$1 = $[0];
|
||||
}
|
||||
return c$2;
|
||||
return c$1;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -28,7 +28,7 @@ function Component(props) {
|
||||
a = [];
|
||||
b = {};
|
||||
foo(a, b);
|
||||
const _ = <div a={a}></div>;
|
||||
|
||||
foo(a, b);
|
||||
$[0] = a;
|
||||
$[1] = b;
|
||||
|
||||
@@ -20,7 +20,7 @@ function foo() {
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = 1;
|
||||
for (const i = 0; 10, true; 0) {
|
||||
for (const i = 0; true; 0) {
|
||||
x = x + 1;
|
||||
}
|
||||
$[0] = x;
|
||||
|
||||
@@ -28,13 +28,8 @@ function foo(a, b, c, d) {
|
||||
|
||||
```javascript
|
||||
function foo(a, b, c, d) {
|
||||
const x = 0;
|
||||
true;
|
||||
true;
|
||||
|
||||
const x$0 = a;
|
||||
x$0;
|
||||
return x$0;
|
||||
const x = a;
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -24,14 +24,11 @@ function foo() {
|
||||
function foo() {
|
||||
const $ = React.useMemoCache();
|
||||
const x = 1;
|
||||
const y = 2;
|
||||
1;
|
||||
false;
|
||||
|
||||
const y$0 = 3;
|
||||
const y = 3;
|
||||
let t;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t = { x: x, y: y$0 };
|
||||
t = { x: x, y: y };
|
||||
$[0] = t;
|
||||
} else {
|
||||
t = $[0];
|
||||
|
||||
@@ -16,11 +16,8 @@ function foo(a, b, c) {
|
||||
|
||||
```javascript
|
||||
function foo(a, b, c) {
|
||||
const x = 0;
|
||||
const x$0 = a;
|
||||
const x$1 = b;
|
||||
const x$2 = c;
|
||||
return x$2;
|
||||
const x = c;
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -17,12 +17,8 @@ function foo() {
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const x = 1;
|
||||
1;
|
||||
true;
|
||||
|
||||
const x$0 = 2;
|
||||
return x$0;
|
||||
const x = 2;
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -16,12 +16,8 @@ function foo() {
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const x = 1;
|
||||
1;
|
||||
true;
|
||||
|
||||
const x$0 = 2;
|
||||
throw x$0;
|
||||
const x = 2;
|
||||
throw x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -18,7 +18,7 @@ function foo() {
|
||||
```javascript
|
||||
function foo() {
|
||||
const x = 1;
|
||||
while ((10, true)) {
|
||||
while (true) {
|
||||
1;
|
||||
2;
|
||||
}
|
||||
|
||||
@@ -36,30 +36,29 @@ function foo(x) {
|
||||
|
||||
```javascript
|
||||
function foo(x) {
|
||||
const y = undefined;
|
||||
bb1: switch (x) {
|
||||
case 0: {
|
||||
const y$0 = 0;
|
||||
const y = 0;
|
||||
}
|
||||
case 1: {
|
||||
const y$1 = 1;
|
||||
const y = 1;
|
||||
break bb1;
|
||||
}
|
||||
case 2: {
|
||||
break bb1;
|
||||
}
|
||||
case 3: {
|
||||
const y$2 = 3;
|
||||
const y = 3;
|
||||
break bb1;
|
||||
}
|
||||
case 4: {
|
||||
const y$3 = 4;
|
||||
const y = 4;
|
||||
}
|
||||
case 5: {
|
||||
const y$4 = 5;
|
||||
const y = 5;
|
||||
}
|
||||
default: {
|
||||
const y$5 = 0;
|
||||
const y = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,11 +41,10 @@ function Component(props) {
|
||||
case true: {
|
||||
x.push(props.p2);
|
||||
x.push(props.p3);
|
||||
const y$1 = [];
|
||||
}
|
||||
case false: {
|
||||
const y$2 = x;
|
||||
y$0 = y$2;
|
||||
const y$1 = x;
|
||||
y$0 = y$1;
|
||||
}
|
||||
}
|
||||
$[0] = props.p0;
|
||||
|
||||
@@ -39,7 +39,7 @@ function ternary(props) {
|
||||
const c_5 = $[5] !== b;
|
||||
let t2;
|
||||
if (c_4 || c_5) {
|
||||
t2 = a ? b : (null, null);
|
||||
t2 = a ? b : null;
|
||||
$[4] = a;
|
||||
$[5] = b;
|
||||
$[6] = t2;
|
||||
|
||||
@@ -16,23 +16,15 @@ function component() {
|
||||
```javascript
|
||||
function component() {
|
||||
const $ = React.useMemoCache();
|
||||
let x;
|
||||
const x = {};
|
||||
let q;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = {};
|
||||
let q;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
q = {};
|
||||
$[1] = q;
|
||||
} else {
|
||||
q = $[1];
|
||||
}
|
||||
x.t = q;
|
||||
$[0] = x;
|
||||
q = {};
|
||||
$[0] = q;
|
||||
} else {
|
||||
x = $[0];
|
||||
q = $[0];
|
||||
}
|
||||
|
||||
const z = x.t;
|
||||
x.t = q;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -30,7 +30,6 @@ function component() {
|
||||
} else {
|
||||
p = $[0];
|
||||
}
|
||||
p + p;
|
||||
let o;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
o = {};
|
||||
@@ -38,19 +37,10 @@ function component() {
|
||||
} else {
|
||||
o = $[1];
|
||||
}
|
||||
let x;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = {};
|
||||
x.t = p;
|
||||
|
||||
const z = x.t;
|
||||
x.t = o;
|
||||
$[2] = x;
|
||||
} else {
|
||||
x = $[2];
|
||||
}
|
||||
|
||||
const y = x.t;
|
||||
const x = {};
|
||||
x.t = p;
|
||||
x.t = o;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -17,10 +17,8 @@ function foo(a) {
|
||||
|
||||
```javascript
|
||||
function foo(a) {
|
||||
const x = 0;
|
||||
|
||||
const x$0 = 1;
|
||||
return a + x$0;
|
||||
const x = 1;
|
||||
return a + x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user