mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Account for stores that can occur in object/array literals
This commit is contained in:
@@ -4,9 +4,8 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
import invariant from "invariant";
|
||||
import DisjointSet from "../Utils/DisjointSet";
|
||||
import { Effect, HIRFunction, Identifier } from "./HIR";
|
||||
import { Effect, HIRFunction, Identifier, InstructionId, Place } from "./HIR";
|
||||
|
||||
export function inferAliasForStores(
|
||||
func: HIRFunction,
|
||||
@@ -18,18 +17,40 @@ export function inferAliasForStores(
|
||||
if (lvalue === null || lvalue.place.effect !== Effect.Store) {
|
||||
continue;
|
||||
}
|
||||
|
||||
invariant(
|
||||
value.kind === "Identifier",
|
||||
"only identifiers can be aliased by stores"
|
||||
);
|
||||
|
||||
if (
|
||||
lvalue.place.identifier.mutableRange.end > instr.id ||
|
||||
value.identifier.mutableRange.end > instr.id
|
||||
) {
|
||||
aliases.union([lvalue.place.identifier, value.identifier]);
|
||||
switch (value.kind) {
|
||||
case "Identifier": {
|
||||
maybeAlias(aliases, lvalue.place, value, instr.id);
|
||||
break;
|
||||
}
|
||||
case "ArrayExpression": {
|
||||
for (const item of value.elements) {
|
||||
maybeAlias(aliases, lvalue.place, item, instr.id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ObjectExpression": {
|
||||
if (value.properties !== null) {
|
||||
for (const [, property] of value.properties) {
|
||||
maybeAlias(aliases, lvalue.place, property, instr.id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function maybeAlias(
|
||||
aliases: DisjointSet<Identifier>,
|
||||
lvalue: Place,
|
||||
rvalue: Place,
|
||||
id: InstructionId
|
||||
): void {
|
||||
if (
|
||||
lvalue.identifier.mutableRange.end > id ||
|
||||
rvalue.identifier.mutableRange.end > id
|
||||
) {
|
||||
aliases.union([lvalue.identifier, rvalue.identifier]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,6 +516,7 @@ function inferBlock(env: Environment, block: BasicBlock) {
|
||||
for (const instr of block.instructions) {
|
||||
const instrValue = instr.value;
|
||||
let effectKind: Effect | null = null;
|
||||
let lvalueEffect = Effect.Mutate;
|
||||
let valueKind: ValueKind;
|
||||
switch (instrValue.kind) {
|
||||
case "BinaryExpression": {
|
||||
@@ -526,6 +527,7 @@ function inferBlock(env: Environment, block: BasicBlock) {
|
||||
case "ArrayExpression": {
|
||||
valueKind = ValueKind.Mutable;
|
||||
effectKind = Effect.Read;
|
||||
lvalueEffect = Effect.Store;
|
||||
break;
|
||||
}
|
||||
case "NewExpression": {
|
||||
@@ -547,6 +549,7 @@ function inferBlock(env: Environment, block: BasicBlock) {
|
||||
valueKind = ValueKind.Mutable;
|
||||
// Object construction captures but does not modify the key/property values
|
||||
effectKind = Effect.Read;
|
||||
lvalueEffect = Effect.Store;
|
||||
break;
|
||||
}
|
||||
case "UnaryExpression": {
|
||||
@@ -645,7 +648,7 @@ function inferBlock(env: Environment, block: BasicBlock) {
|
||||
} else {
|
||||
env.reference(instr.lvalue.place, Effect.Mutate);
|
||||
}
|
||||
instr.lvalue.place.effect = Effect.Mutate;
|
||||
instr.lvalue.place.effect = lvalueEffect;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const a = [[1]];
|
||||
const first = a.at(0);
|
||||
first.set(0, 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const $ = React.useMemoCache();
|
||||
let a;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
a = [[1]];
|
||||
const first = a.at(0);
|
||||
first.set(0, 2);
|
||||
$[0] = a;
|
||||
} else {
|
||||
a = $[0];
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
function foo() {
|
||||
const a = [[1]];
|
||||
const first = a.at(0);
|
||||
first.set(0, 2);
|
||||
return a;
|
||||
}
|
||||
+6
-17
@@ -16,29 +16,18 @@ function g() {
|
||||
```javascript
|
||||
function g() {
|
||||
const $ = React.useMemoCache();
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = {
|
||||
z: 1,
|
||||
};
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
|
||||
const c_1 = $[1] !== t0;
|
||||
let x;
|
||||
|
||||
if (c_1) {
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = {
|
||||
y: t0,
|
||||
y: {
|
||||
z: 1,
|
||||
},
|
||||
};
|
||||
x.z.y = x.y.z + 1;
|
||||
x.z.y = x.y.z * 2;
|
||||
$[1] = t0;
|
||||
$[2] = x;
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[2];
|
||||
x = $[0];
|
||||
}
|
||||
|
||||
return x;
|
||||
|
||||
+2
-19
@@ -45,32 +45,15 @@ function mutate(x, y) {}
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.useMemoCache();
|
||||
let a;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
a = {};
|
||||
$[0] = a;
|
||||
} else {
|
||||
a = $[0];
|
||||
}
|
||||
|
||||
const a = {};
|
||||
const b = [a];
|
||||
let c;
|
||||
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
c = {};
|
||||
$[1] = c;
|
||||
} else {
|
||||
c = $[1];
|
||||
}
|
||||
|
||||
const c = {};
|
||||
const d = {
|
||||
c: c,
|
||||
};
|
||||
const x = {};
|
||||
x.b = b;
|
||||
const y = mutate(x, d);
|
||||
|
||||
if (a) {
|
||||
}
|
||||
|
||||
|
||||
@@ -16,26 +16,16 @@ function foo() {
|
||||
```javascript
|
||||
function foo() {
|
||||
const $ = React.useMemoCache();
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = [];
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[0];
|
||||
}
|
||||
|
||||
const c_1 = $[1] !== x;
|
||||
let y;
|
||||
|
||||
if (c_1) {
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
const x = [];
|
||||
y = {
|
||||
x: x,
|
||||
};
|
||||
y.x.push([]);
|
||||
$[1] = x;
|
||||
$[2] = y;
|
||||
$[0] = y;
|
||||
} else {
|
||||
y = $[2];
|
||||
y = $[0];
|
||||
}
|
||||
|
||||
return y;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const x = {};
|
||||
const y = foo(x);
|
||||
y.mutate();
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const $ = React.useMemoCache();
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = {};
|
||||
const y = foo(x);
|
||||
y.mutate();
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[0];
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
function foo() {
|
||||
const x = {};
|
||||
const y = foo(x);
|
||||
y.mutate();
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Foo() {
|
||||
const x = {};
|
||||
const y = new Foo(x);
|
||||
y.mutate();
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Foo() {
|
||||
const $ = React.useMemoCache();
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = {};
|
||||
const y = new Foo(x);
|
||||
y.mutate();
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[0];
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
function Foo() {
|
||||
const x = {};
|
||||
const y = new Foo(x);
|
||||
y.mutate();
|
||||
return x;
|
||||
}
|
||||
Reference in New Issue
Block a user