mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Prune memoize instructions in codegen
The previous PR introduced `memoize` instructions whose lvalues aren't used, but which can't be pruned by DCE due to pipeline ordering. Here we change to make memoize an instruction intended for its side effects only, and prune during codegen.
This commit is contained in:
@@ -849,6 +849,10 @@ export type InstructionValue =
|
||||
* Represents semantic information from useMemo/useCallback that the developer
|
||||
* has indicated a particular value should be memoized. This value is ignored
|
||||
* unless the TODO flag is enabled.
|
||||
*
|
||||
* NOTE: the Memoize instruction is intended for side-effects only, and is pruned
|
||||
* during codegen. It can't be pruned during DCE because we need to preserve the
|
||||
* instruction so it can be visible in InferReferenceEffects.
|
||||
*/
|
||||
| { kind: "Memoize"; value: Place; loc: SourceLocation }
|
||||
/*
|
||||
|
||||
@@ -137,9 +137,6 @@ export function dropManualMemoization(func: HIRFunction): void {
|
||||
* the original lvalue for the result of the Memoize instruction, so that
|
||||
* we don't have to rewrite subsequent instructions.
|
||||
*/
|
||||
const lvalue = instr.lvalue;
|
||||
const temp = createTemporaryPlace(func.env);
|
||||
instr.lvalue = { ...temp };
|
||||
nextInstructions =
|
||||
nextInstructions ?? block.instructions.slice(0, i);
|
||||
|
||||
@@ -148,10 +145,10 @@ export function dropManualMemoization(func: HIRFunction): void {
|
||||
for (const operand of eachInstructionValueOperand(
|
||||
functionExpression
|
||||
)) {
|
||||
const operandLValue = createTemporaryPlace(func.env);
|
||||
const temp = createTemporaryPlace(func.env);
|
||||
nextInstructions.push({
|
||||
id: makeInstructionId(0),
|
||||
lvalue: operandLValue,
|
||||
lvalue: temp,
|
||||
value: {
|
||||
kind: "Memoize",
|
||||
value: { ...operand },
|
||||
@@ -164,12 +161,13 @@ export function dropManualMemoization(func: HIRFunction): void {
|
||||
|
||||
nextInstructions.push(instr);
|
||||
|
||||
const temp = createTemporaryPlace(func.env);
|
||||
nextInstructions.push({
|
||||
id: makeInstructionId(0),
|
||||
lvalue,
|
||||
lvalue: temp,
|
||||
value: {
|
||||
kind: "Memoize",
|
||||
value: temp,
|
||||
value: { ...instr.lvalue },
|
||||
loc: instr.loc,
|
||||
},
|
||||
loc: instr.loc,
|
||||
|
||||
@@ -1163,14 +1163,14 @@ function inferBlock(
|
||||
continue;
|
||||
}
|
||||
case "Memoize": {
|
||||
state.initialize(instrValue, {
|
||||
kind: ValueKind.Frozen,
|
||||
reason: new Set([ValueReason.Other]),
|
||||
});
|
||||
state.reference(instrValue.value, Effect.Freeze, ValueReason.Other);
|
||||
const lvalue = instr.lvalue;
|
||||
lvalue.effect = Effect.ConditionallyMutate;
|
||||
state.alias(lvalue, instrValue.value);
|
||||
state.initialize(instrValue, {
|
||||
kind: ValueKind.Immutable,
|
||||
reason: new Set([ValueReason.Other]),
|
||||
});
|
||||
state.define(lvalue, instrValue);
|
||||
continue;
|
||||
}
|
||||
case "LoadLocal": {
|
||||
|
||||
+3
-4
@@ -835,6 +835,8 @@ function codegenInstructionNullable(
|
||||
assertExhaustive(kind, `Unexpected instruction kind '${kind}'`);
|
||||
}
|
||||
}
|
||||
} else if (instr.value.kind === "Memoize") {
|
||||
return null;
|
||||
} else if (instr.value.kind === "Debugger") {
|
||||
return t.debuggerStatement();
|
||||
} else if (instr.value.kind === "ObjectMethod") {
|
||||
@@ -1628,10 +1630,7 @@ function codegenInstructionValue(
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "Memoize": {
|
||||
value = codegenPlaceToExpression(cx, instrValue.value);
|
||||
break;
|
||||
}
|
||||
case "Memoize":
|
||||
case "Debugger":
|
||||
case "DeclareLocal":
|
||||
case "DeclareContext":
|
||||
|
||||
+1
-1
@@ -453,6 +453,7 @@ function computeMemoizationInputs(
|
||||
};
|
||||
}
|
||||
case "NextPropertyOf":
|
||||
case "Memoize":
|
||||
case "Debugger":
|
||||
case "ComputedDelete":
|
||||
case "PropertyDelete":
|
||||
@@ -471,7 +472,6 @@ function computeMemoizationInputs(
|
||||
rvalues: [],
|
||||
};
|
||||
}
|
||||
case "Memoize":
|
||||
case "Await":
|
||||
case "TypeCastExpression":
|
||||
case "NextIterableOf": {
|
||||
|
||||
@@ -280,11 +280,6 @@ function* generateInstructionTypes(
|
||||
break;
|
||||
}
|
||||
|
||||
case "Memoize": {
|
||||
yield equation(left, value.value.identifier.type);
|
||||
break;
|
||||
}
|
||||
|
||||
case "PropertyDelete":
|
||||
case "ComputedDelete": {
|
||||
yield equation(left, { kind: "Primitive" });
|
||||
@@ -319,7 +314,9 @@ function* generateInstructionTypes(
|
||||
case "NextIterableOf":
|
||||
case "UnsupportedNode":
|
||||
case "Debugger":
|
||||
case "Memoize": {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assertExhaustive(value, `Unhandled instruction value kind: ${value}`);
|
||||
}
|
||||
|
||||
+3
-7
@@ -64,11 +64,7 @@ function Component(props) {
|
||||
const free2 = t1;
|
||||
const part = free2.part;
|
||||
useHook();
|
||||
|
||||
props.value;
|
||||
free;
|
||||
part;
|
||||
let t44;
|
||||
let t39;
|
||||
let x;
|
||||
if ($[2] !== props.value) {
|
||||
x = makeObject_Primitives();
|
||||
@@ -79,8 +75,8 @@ function Component(props) {
|
||||
} else {
|
||||
x = $[3];
|
||||
}
|
||||
t44 = x;
|
||||
const object = t44;
|
||||
t39 = x;
|
||||
const object = t39;
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@ import { identity, makeObject_Primitives, mutate } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(1);
|
||||
let t15;
|
||||
let t7;
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = makeObject_Primitives();
|
||||
@@ -36,8 +36,8 @@ function Component(props) {
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
t15 = t0;
|
||||
const object = t15;
|
||||
t7 = t0;
|
||||
const object = t7;
|
||||
identity(object);
|
||||
return object;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user