@samitouri / QOS-React-2 / commits / 3df1ae66c0

[λ] 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