[aliasing] Introduce Effect.Capture
Effect.Capture is very similar to Effect.Read, but the only difference is that this reference is stored somewhere via a Effect.Store. Previously, any operand associated with a Effect.Store in the same instruction would get aliased -- so there was no need to explicitly differentiate between a "normal read" and "read that gets stored". This difference is now explicit with FunctionExpression where every dependency is "read" but only a few are "captured" for store (and mutation). In a follow up PR, the mutating deps will have an Effect.Capture to differentiate from the other non mutating deps (Effect.Read).
Sathya Gunasekaran committed
Feb 7, 2023 at 16:59 UTC
85c92bcfbe04c0edb8ec2bc850ec0d4edda6bb19
4 files changed
+18
-6
compiler/forget/src/HIR/HIR.ts
+2
@@ -546,6 +546,8 @@ export enum Effect {
546
Freeze = "freeze",
547
// This reference reads the value
548
Read = "read",
549
+ // This reference reads and stores the value
550
+ Capture = "capture",
551
// This reference may write to (mutate) the value
552
Mutate = "mutate",
553
// This reference may alias to (mutate) the value
compiler/forget/src/Inference/InferAliasForStores.ts
+6
-1
@@ -30,7 +30,12 @@ export function inferAliasForStores(
30
case "ComputedStore":
31
case "PropertyStore": {
32
for (const operand of eachInstructionValueOperand(value)) {
33
- maybeAlias(aliases, lvalue.place, operand, instr.id);
33
+ if (
34
+ operand.effect === Effect.Capture ||
35
+ operand.effect === Effect.Store
36
+ ) {
37
+ maybeAlias(aliases, lvalue.place, operand, instr.id);
38
+ }
39
}
40
break;
41
}
compiler/forget/src/Inference/InferMutableLifetimes.ts
+1
@@ -77,6 +77,7 @@ function inferPlace(
77
)}!`
78
);
79
}
80
+ case Effect.Capture:
81
case Effect.Read:
82
case Effect.Freeze:
83
return;
compiler/forget/src/Inference/InferReferenceEffects.ts
+9
-5
@@ -303,6 +303,10 @@ class Environment {
303
effect = Effect.Store;
304
break;
305
}
306
+ case Effect.Capture: {
307
+ effect = Effect.Capture;
308
+ break;
309
+ }
310
case Effect.Read: {
311
effect = Effect.Read;
312
break;
@@ -542,7 +546,7 @@ function inferBlock(env: Environment, block: BasicBlock) {
546
}
547
case "ArrayExpression": {
548
valueKind = ValueKind.Mutable;
545
- effectKind = Effect.Read;
549
+ effectKind = Effect.Capture;
550
lvalueEffect = Effect.Store;
551
break;
552
}
@@ -564,7 +568,7 @@ function inferBlock(env: Environment, block: BasicBlock) {
568
case "ObjectExpression": {
569
valueKind = ValueKind.Mutable;
570
// Object construction captures but does not modify the key/property values
567
- effectKind = Effect.Read;
571
+ effectKind = Effect.Capture;
572
lvalueEffect = Effect.Store;
573
break;
574
}
@@ -658,7 +662,7 @@ function inferBlock(env: Environment, block: BasicBlock) {
662
const effect = isObjectType(instrValue.object.identifier)
663
? Effect.Store
664
: Effect.Mutate;
661
- env.reference(instrValue.value, Effect.Read);
665
+ env.reference(instrValue.value, Effect.Capture);
666
env.reference(instrValue.object, effect);
667
668
const lvalue = instr.lvalue;
@@ -688,8 +692,8 @@ function inferBlock(env: Environment, block: BasicBlock) {
692
const effect = isObjectType(instrValue.object.identifier)
693
? Effect.Store
694
: Effect.Mutate;
691
- env.reference(instrValue.value, Effect.Read);
692
- env.reference(instrValue.property, Effect.Read);
695
+ env.reference(instrValue.value, Effect.Capture);
696
+ env.reference(instrValue.property, Effect.Capture);
697
env.reference(instrValue.object, effect);
698
699
const lvalue = instr.lvalue;