[λ] Use Effect.Capture for mutating deps
Leverage Effect.Capture to differentiate between mutating and non mutating deps.
Sathya Gunasekaran committed
Feb 7, 2023 at 16:59 UTC
3df1ae66c0cf48e09e1f6fcbfa8d86b9dd8ebe4b
6 files changed
+24
-29
compiler/forget/src/HIR/BuildHIR.ts
-1
@@ -1364,7 +1364,6 @@ function lowerExpression(
1364
name,
1365
loweredFunc,
1366
dependencies: captured.refs,
1367
- mutatedDeps: [],
1367
expr: expr.node,
1368
loc: exprLoc,
1369
};
compiler/forget/src/HIR/HIR.ts
-3
@@ -470,9 +470,6 @@ export type FunctionExpression = {
470
kind: "FunctionExpression";
471
name: string | null;
472
dependencies: Array<Place>;
473
- // TODO(gsn): Remove this mutatedDeps array and use dependencies as single
474
- // source of truth.
475
- mutatedDeps: Array<Place>;
473
loweredFunc: HIRFunction;
474
expr: t.ArrowFunctionExpression | t.FunctionExpression;
475
};
compiler/forget/src/Inference/AnalyseFunctions.ts
+4
-5
@@ -5,6 +5,7 @@ import {
5
Identifier,
6
mergeConsecutiveBlocks,
7
Place,
8
+ Effect,
9
} from "../HIR";
10
import { constantPropagation } from "../Optimization";
11
import { eliminateRedundantPhi, enterSSA } from "../SSA";
@@ -85,7 +86,6 @@ function infer(
86
.filter((m) => m !== null) as string[]
87
);
88
88
- const mutatedDeps: Place[] = [];
89
for (const dep of value.dependencies) {
90
let name: string | null = null;
91
@@ -97,7 +97,7 @@ function infer(
97
}
98
99
if (name !== null && mutations.has(name)) {
100
- mutatedDeps.push(dep);
100
+ dep.effect = Effect.Capture;
101
}
102
}
103
@@ -114,11 +114,10 @@ function infer(
114
);
115
116
if (mutations.has(place.identifier.name)) {
117
- mutatedDeps.push(place);
117
+ place.effect = Effect.Capture;
118
+ value.dependencies.push(place);
119
}
120
}
120
-
121
- value.mutatedDeps = mutatedDeps;
121
}
122
123
function isMutated(id: Identifier) {
compiler/forget/src/Inference/InferAliasForStores.ts
+2
-6
@@ -28,7 +28,8 @@ export function inferAliasForStores(
28
case "ArrayExpression":
29
case "ObjectExpression":
30
case "ComputedStore":
31
- case "PropertyStore": {
31
+ case "PropertyStore":
32
+ case "FunctionExpression": {
33
for (const operand of eachInstructionValueOperand(value)) {
34
if (
35
operand.effect === Effect.Capture ||
@@ -39,11 +40,6 @@ export function inferAliasForStores(
40
}
41
break;
42
}
42
- case "FunctionExpression": {
43
- for (const dep of value.mutatedDeps) {
44
- maybeAlias(aliases, lvalue.place, dep, instr.id);
45
- }
46
- }
43
}
44
}
45
}
compiler/forget/src/Inference/InferReferenceEffects.ts
+12
-6
@@ -572,12 +572,6 @@ function inferBlock(env: Environment, block: BasicBlock) {
572
lvalueEffect = Effect.Store;
573
break;
574
}
575
- case "FunctionExpression": {
576
- valueKind = ValueKind.Mutable;
577
- effectKind = Effect.Read;
578
- lvalueEffect = Effect.Store;
579
- break;
580
- }
575
case "UnaryExpression": {
576
valueKind = ValueKind.Immutable;
577
effectKind = Effect.Read;
@@ -615,6 +609,18 @@ function inferBlock(env: Environment, block: BasicBlock) {
609
valueKind = ValueKind.Immutable;
610
break;
611
}
612
+ case "FunctionExpression": {
613
+ for (const operand of eachInstructionOperand(instr)) {
614
+ env.reference(
615
+ operand,
616
+ operand.effect === Effect.Unknown ? Effect.Read : operand.effect
617
+ );
618
+ }
619
+ env.initialize(instrValue, ValueKind.Mutable);
620
+ env.define(instr.lvalue.place, instrValue);
621
+ instr.lvalue.place.effect = Effect.Store;
622
+ continue;
623
+ }
624
case "PropertyCall": {
625
if (!env.isDefined(instrValue.receiver)) {
626
// TODO @josephsavona: improve handling of globals
compiler/forget/src/__tests__/fixtures/hir/mutate-captured-arg-separately.expect.md
+6
-8
@@ -19,20 +19,18 @@ function component(a) {
19
```javascript
20
function component(a) {
21
const $ = React.unstable_useMemoCache();
22
- const c_0 = $[0] !== a;
22
let y;
24
- if (c_0) {
23
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
24
y = function () {
25
m(x);
26
};
28
-
29
- const x = { a: a };
30
- m(x);
31
- $[0] = a;
32
- $[1] = y;
27
+ $[0] = y;
28
} else {
34
- y = $[1];
29
+ y = $[0];
30
}
31
+
32
+ const x = { a: a };
33
+ m(x);
34
return y;
35
}
36