mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[compiler] More fine-grained memoization in change detection mode
[ghstack-poisoned]
This commit is contained in:
+7
@@ -653,6 +653,7 @@ function codegenReactiveScope(
|
||||
const cacheLoadOldValueStatements: Array<t.Statement> = [];
|
||||
const changeDetectionStatements: Array<t.Statement> = [];
|
||||
const idempotenceDetectionStatements: Array<t.Statement> = [];
|
||||
const restoreOldValueStatements: Array<t.Statement> = [];
|
||||
|
||||
for (const { name, index, value } of cacheLoads) {
|
||||
const loadName = cx.synthesizeName(`old$${name.name}`);
|
||||
@@ -669,6 +670,11 @@ function codegenReactiveScope(
|
||||
t.variableDeclarator(t.identifier(loadName), slot),
|
||||
])
|
||||
);
|
||||
if (scope.source) {
|
||||
restoreOldValueStatements.push(
|
||||
t.expressionStatement(t.assignmentExpression("=", t.cloneNode(name, true), t.identifier(loadName)))
|
||||
);
|
||||
}
|
||||
changeDetectionStatements.push(
|
||||
t.expressionStatement(
|
||||
t.callExpression(t.identifier(detectionFunction), [
|
||||
@@ -709,6 +715,7 @@ function codegenReactiveScope(
|
||||
t.blockStatement([
|
||||
...cacheLoadOldValueStatements,
|
||||
...changeDetectionStatements,
|
||||
...restoreOldValueStatements,
|
||||
])
|
||||
),
|
||||
...cacheStoreStatements,
|
||||
|
||||
+8
-6
@@ -191,11 +191,10 @@ export function mayAllocate(env: Environment, instruction: Instruction, conserva
|
||||
const { value } = instruction;
|
||||
switch (value.kind) {
|
||||
case "Destructure": {
|
||||
return doesPatternContainSpreadElement(value.lvalue.pattern);
|
||||
return doesPatternContainSpreadElement(value.lvalue.pattern) || env.config.enableChangeDetectionForDebugging != null;
|
||||
}
|
||||
case "PostfixUpdate":
|
||||
case "PrefixUpdate":
|
||||
case "Await":
|
||||
case "DeclareLocal":
|
||||
case "DeclareContext":
|
||||
case "StoreLocal":
|
||||
@@ -206,26 +205,29 @@ export function mayAllocate(env: Environment, instruction: Instruction, conserva
|
||||
case "LoadContext":
|
||||
case "StoreContext":
|
||||
case "PropertyDelete":
|
||||
case "ComputedLoad":
|
||||
case "ComputedDelete":
|
||||
case "JSXText":
|
||||
case "TemplateLiteral":
|
||||
case "Primitive":
|
||||
case "GetIterator":
|
||||
case "IteratorNext":
|
||||
case "NextPropertyOf":
|
||||
case "Debugger":
|
||||
case "StartMemoize":
|
||||
case "FinishMemoize":
|
||||
case "UnaryExpression":
|
||||
case "BinaryExpression":
|
||||
case "PropertyLoad":
|
||||
case "StoreGlobal": {
|
||||
return false;
|
||||
}
|
||||
case "PropertyLoad":
|
||||
case "NextPropertyOf":
|
||||
case "ComputedLoad":
|
||||
case "Await": {
|
||||
return env.config.enableChangeDetectionForDebugging != null;
|
||||
}
|
||||
case "CallExpression":
|
||||
case "MethodCall": {
|
||||
return conservative || instruction.lvalue.identifier.type.kind !== "Primitive";
|
||||
return conservative || instruction.lvalue.identifier.type.kind !== "Primitive" || env.config.enableChangeDetectionForDebugging != null;
|
||||
}
|
||||
case "RegExpLiteral":
|
||||
case "PropertyStore":
|
||||
|
||||
+47
-30
@@ -39,43 +39,60 @@ function useOther(x) {
|
||||
}
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(4);
|
||||
let t0;
|
||||
{
|
||||
t0 = f(props.x);
|
||||
let condition = $[0] !== props.x;
|
||||
if (!condition) {
|
||||
let old$t0 = $[1];
|
||||
$structuralCheck(old$t0, t0, "t0", "Component", "cached", "(8:8)");
|
||||
}
|
||||
$[0] = props.x;
|
||||
$[1] = t0;
|
||||
if (condition) {
|
||||
t0 = f(props.x);
|
||||
$structuralCheck($[1], t0, "t0", "Component", "recomputed", "(8:8)");
|
||||
t0 = $[1];
|
||||
}
|
||||
}
|
||||
const w = t0;
|
||||
const z = useOther(w);
|
||||
const [x] = useState(z);
|
||||
const $ = _c(6);
|
||||
const t0 = props.x;
|
||||
let t1;
|
||||
{
|
||||
t1 = <div>{x}</div>;
|
||||
let condition = $[2] !== x;
|
||||
t1 = f(t0);
|
||||
let condition = $[0] !== t0;
|
||||
if (!condition) {
|
||||
let old$t1 = $[3];
|
||||
$structuralCheck(old$t1, t1, "t1", "Component", "cached", "(11:11)");
|
||||
let old$t1 = $[1];
|
||||
$structuralCheck(old$t1, t1, "t1", "Component", "cached", "(8:8)");
|
||||
}
|
||||
$[2] = x;
|
||||
$[3] = t1;
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
if (condition) {
|
||||
t1 = <div>{x}</div>;
|
||||
$structuralCheck($[3], t1, "t1", "Component", "recomputed", "(11:11)");
|
||||
t1 = $[3];
|
||||
t1 = f(t0);
|
||||
$structuralCheck($[1], t1, "t1", "Component", "recomputed", "(8:8)");
|
||||
t1 = $[1];
|
||||
}
|
||||
}
|
||||
return t1;
|
||||
const w = t1;
|
||||
const z = useOther(w);
|
||||
const t2 = useState(z);
|
||||
let x;
|
||||
{
|
||||
[x] = t2;
|
||||
let condition = $[2] !== t2;
|
||||
if (!condition) {
|
||||
let old$x = $[3];
|
||||
$structuralCheck(old$x, x, "x", "Component", "cached", "(10:10)");
|
||||
}
|
||||
$[2] = t2;
|
||||
$[3] = x;
|
||||
if (condition) {
|
||||
[x] = t2;
|
||||
$structuralCheck($[3], x, "x", "Component", "recomputed", "(10:10)");
|
||||
x = $[3];
|
||||
}
|
||||
}
|
||||
let t3;
|
||||
{
|
||||
t3 = <div>{x}</div>;
|
||||
let condition = $[4] !== x;
|
||||
if (!condition) {
|
||||
let old$t3 = $[5];
|
||||
$structuralCheck(old$t3, t3, "t3", "Component", "cached", "(11:11)");
|
||||
}
|
||||
$[4] = x;
|
||||
$[5] = t3;
|
||||
if (condition) {
|
||||
t3 = <div>{x}</div>;
|
||||
$structuralCheck($[5], t3, "t3", "Component", "recomputed", "(11:11)");
|
||||
t3 = $[5];
|
||||
}
|
||||
}
|
||||
return t3;
|
||||
}
|
||||
|
||||
function f(x) {
|
||||
|
||||
+29
-13
@@ -20,7 +20,7 @@ import { c as _c } from "react/compiler-runtime"; // @enableChangeDetectionForDe
|
||||
import { useState } from "react";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(3);
|
||||
const $ = _c(5);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = f(props.x);
|
||||
@@ -28,24 +28,40 @@ function Component(props) {
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const [x] = useState(t0);
|
||||
let t1;
|
||||
const t1 = useState(t0);
|
||||
let x;
|
||||
{
|
||||
t1 = <div>{x}</div>;
|
||||
let condition = $[1] !== x;
|
||||
[x] = t1;
|
||||
let condition = $[1] !== t1;
|
||||
if (!condition) {
|
||||
let old$t1 = $[2];
|
||||
$structuralCheck(old$t1, t1, "t1", "Component", "cached", "(6:6)");
|
||||
let old$x = $[2];
|
||||
$structuralCheck(old$x, x, "x", "Component", "cached", "(5:5)");
|
||||
}
|
||||
$[1] = x;
|
||||
$[2] = t1;
|
||||
$[1] = t1;
|
||||
$[2] = x;
|
||||
if (condition) {
|
||||
t1 = <div>{x}</div>;
|
||||
$structuralCheck($[2], t1, "t1", "Component", "recomputed", "(6:6)");
|
||||
t1 = $[2];
|
||||
[x] = t1;
|
||||
$structuralCheck($[2], x, "x", "Component", "recomputed", "(5:5)");
|
||||
x = $[2];
|
||||
}
|
||||
}
|
||||
return t1;
|
||||
let t2;
|
||||
{
|
||||
t2 = <div>{x}</div>;
|
||||
let condition = $[3] !== x;
|
||||
if (!condition) {
|
||||
let old$t2 = $[4];
|
||||
$structuralCheck(old$t2, t2, "t2", "Component", "cached", "(6:6)");
|
||||
}
|
||||
$[3] = x;
|
||||
$[4] = t2;
|
||||
if (condition) {
|
||||
t2 = <div>{x}</div>;
|
||||
$structuralCheck($[4], t2, "t2", "Component", "recomputed", "(6:6)");
|
||||
t2 = $[4];
|
||||
}
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+47
-30
@@ -35,53 +35,70 @@ import { c as _c } from "react/compiler-runtime";
|
||||
import { useState } from "react"; // @enableChangeDetectionForDebugging
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(5);
|
||||
let t0;
|
||||
{
|
||||
t0 = f(props.x);
|
||||
let condition = $[0] !== props.x;
|
||||
if (!condition) {
|
||||
let old$t0 = $[1];
|
||||
$structuralCheck(old$t0, t0, "t0", "Component", "cached", "(4:4)");
|
||||
}
|
||||
$[0] = props.x;
|
||||
$[1] = t0;
|
||||
if (condition) {
|
||||
t0 = f(props.x);
|
||||
$structuralCheck($[1], t0, "t0", "Component", "recomputed", "(4:4)");
|
||||
t0 = $[1];
|
||||
}
|
||||
}
|
||||
const w = t0;
|
||||
const [x] = useState(w);
|
||||
const $ = _c(7);
|
||||
const t0 = props.x;
|
||||
let t1;
|
||||
{
|
||||
t1 = (
|
||||
t1 = f(t0);
|
||||
let condition = $[0] !== t0;
|
||||
if (!condition) {
|
||||
let old$t1 = $[1];
|
||||
$structuralCheck(old$t1, t1, "t1", "Component", "cached", "(4:4)");
|
||||
}
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
if (condition) {
|
||||
t1 = f(t0);
|
||||
$structuralCheck($[1], t1, "t1", "Component", "recomputed", "(4:4)");
|
||||
t1 = $[1];
|
||||
}
|
||||
}
|
||||
const w = t1;
|
||||
const t2 = useState(w);
|
||||
let x;
|
||||
{
|
||||
[x] = t2;
|
||||
let condition = $[2] !== t2;
|
||||
if (!condition) {
|
||||
let old$x = $[3];
|
||||
$structuralCheck(old$x, x, "x", "Component", "cached", "(5:5)");
|
||||
}
|
||||
$[2] = t2;
|
||||
$[3] = x;
|
||||
if (condition) {
|
||||
[x] = t2;
|
||||
$structuralCheck($[3], x, "x", "Component", "recomputed", "(5:5)");
|
||||
x = $[3];
|
||||
}
|
||||
}
|
||||
let t3;
|
||||
{
|
||||
t3 = (
|
||||
<div>
|
||||
{x}
|
||||
{w}
|
||||
</div>
|
||||
);
|
||||
let condition = $[2] !== x || $[3] !== w;
|
||||
let condition = $[4] !== x || $[5] !== w;
|
||||
if (!condition) {
|
||||
let old$t1 = $[4];
|
||||
$structuralCheck(old$t1, t1, "t1", "Component", "cached", "(7:10)");
|
||||
let old$t3 = $[6];
|
||||
$structuralCheck(old$t3, t3, "t3", "Component", "cached", "(7:10)");
|
||||
}
|
||||
$[2] = x;
|
||||
$[3] = w;
|
||||
$[4] = t1;
|
||||
$[4] = x;
|
||||
$[5] = w;
|
||||
$[6] = t3;
|
||||
if (condition) {
|
||||
t1 = (
|
||||
t3 = (
|
||||
<div>
|
||||
{x}
|
||||
{w}
|
||||
</div>
|
||||
);
|
||||
$structuralCheck($[4], t1, "t1", "Component", "recomputed", "(7:10)");
|
||||
t1 = $[4];
|
||||
$structuralCheck($[6], t3, "t3", "Component", "recomputed", "(7:10)");
|
||||
t3 = $[6];
|
||||
}
|
||||
}
|
||||
return t1;
|
||||
return t3;
|
||||
}
|
||||
|
||||
function f(x) {
|
||||
|
||||
Reference in New Issue
Block a user