@samitouri / QOS-React-2 / commits / 85c92bcfbe

[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;