From 3df1ae66c0cf48e09e1f6fcbfa8d86b9dd8ebe4b Mon Sep 17 00:00:00 2001 From: Sathya Gunasekaran Date: Tue, 7 Feb 2023 16:59:36 +0000 Subject: [PATCH] =?UTF-8?q?[=CE=BB]=20Use=20Effect.Capture=20for=20mutatin?= =?UTF-8?q?g=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Leverage Effect.Capture to differentiate between mutating and non mutating deps. --- compiler/forget/src/HIR/BuildHIR.ts | 1 - compiler/forget/src/HIR/HIR.ts | 3 --- .../forget/src/Inference/AnalyseFunctions.ts | 9 ++++----- .../src/Inference/InferAliasForStores.ts | 8 ++------ .../src/Inference/InferReferenceEffects.ts | 18 ++++++++++++------ .../mutate-captured-arg-separately.expect.md | 14 ++++++-------- 6 files changed, 24 insertions(+), 29 deletions(-) diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index 7bcea15fe9..260b777491 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -1364,7 +1364,6 @@ function lowerExpression( name, loweredFunc, dependencies: captured.refs, - mutatedDeps: [], expr: expr.node, loc: exprLoc, }; diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index 9bd833ae59..23efaac7ac 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -470,9 +470,6 @@ export type FunctionExpression = { kind: "FunctionExpression"; name: string | null; dependencies: Array; - // TODO(gsn): Remove this mutatedDeps array and use dependencies as single - // source of truth. - mutatedDeps: Array; loweredFunc: HIRFunction; expr: t.ArrowFunctionExpression | t.FunctionExpression; }; diff --git a/compiler/forget/src/Inference/AnalyseFunctions.ts b/compiler/forget/src/Inference/AnalyseFunctions.ts index 072c807344..692ce782c7 100644 --- a/compiler/forget/src/Inference/AnalyseFunctions.ts +++ b/compiler/forget/src/Inference/AnalyseFunctions.ts @@ -5,6 +5,7 @@ import { Identifier, mergeConsecutiveBlocks, Place, + Effect, } from "../HIR"; import { constantPropagation } from "../Optimization"; import { eliminateRedundantPhi, enterSSA } from "../SSA"; @@ -85,7 +86,6 @@ function infer( .filter((m) => m !== null) as string[] ); - const mutatedDeps: Place[] = []; for (const dep of value.dependencies) { let name: string | null = null; @@ -97,7 +97,7 @@ function infer( } if (name !== null && mutations.has(name)) { - mutatedDeps.push(dep); + dep.effect = Effect.Capture; } } @@ -114,11 +114,10 @@ function infer( ); if (mutations.has(place.identifier.name)) { - mutatedDeps.push(place); + place.effect = Effect.Capture; + value.dependencies.push(place); } } - - value.mutatedDeps = mutatedDeps; } function isMutated(id: Identifier) { diff --git a/compiler/forget/src/Inference/InferAliasForStores.ts b/compiler/forget/src/Inference/InferAliasForStores.ts index 63155a8207..518ef59387 100644 --- a/compiler/forget/src/Inference/InferAliasForStores.ts +++ b/compiler/forget/src/Inference/InferAliasForStores.ts @@ -28,7 +28,8 @@ export function inferAliasForStores( case "ArrayExpression": case "ObjectExpression": case "ComputedStore": - case "PropertyStore": { + case "PropertyStore": + case "FunctionExpression": { for (const operand of eachInstructionValueOperand(value)) { if ( operand.effect === Effect.Capture || @@ -39,11 +40,6 @@ export function inferAliasForStores( } break; } - case "FunctionExpression": { - for (const dep of value.mutatedDeps) { - maybeAlias(aliases, lvalue.place, dep, instr.id); - } - } } } } diff --git a/compiler/forget/src/Inference/InferReferenceEffects.ts b/compiler/forget/src/Inference/InferReferenceEffects.ts index bda7a26fd4..a8c80043f1 100644 --- a/compiler/forget/src/Inference/InferReferenceEffects.ts +++ b/compiler/forget/src/Inference/InferReferenceEffects.ts @@ -572,12 +572,6 @@ function inferBlock(env: Environment, block: BasicBlock) { lvalueEffect = Effect.Store; break; } - case "FunctionExpression": { - valueKind = ValueKind.Mutable; - effectKind = Effect.Read; - lvalueEffect = Effect.Store; - break; - } case "UnaryExpression": { valueKind = ValueKind.Immutable; effectKind = Effect.Read; @@ -615,6 +609,18 @@ function inferBlock(env: Environment, block: BasicBlock) { valueKind = ValueKind.Immutable; break; } + case "FunctionExpression": { + for (const operand of eachInstructionOperand(instr)) { + env.reference( + operand, + operand.effect === Effect.Unknown ? Effect.Read : operand.effect + ); + } + env.initialize(instrValue, ValueKind.Mutable); + env.define(instr.lvalue.place, instrValue); + instr.lvalue.place.effect = Effect.Store; + continue; + } case "PropertyCall": { if (!env.isDefined(instrValue.receiver)) { // TODO @josephsavona: improve handling of globals diff --git a/compiler/forget/src/__tests__/fixtures/hir/mutate-captured-arg-separately.expect.md b/compiler/forget/src/__tests__/fixtures/hir/mutate-captured-arg-separately.expect.md index 12ce76b2a2..5d349cdee1 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/mutate-captured-arg-separately.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/mutate-captured-arg-separately.expect.md @@ -19,20 +19,18 @@ function component(a) { ```javascript function component(a) { const $ = React.unstable_useMemoCache(); - const c_0 = $[0] !== a; let y; - if (c_0) { + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { y = function () { m(x); }; - - const x = { a: a }; - m(x); - $[0] = a; - $[1] = y; + $[0] = y; } else { - y = $[1]; + y = $[0]; } + + const x = { a: a }; + m(x); return y; }