InferReactiveScopes considers all operands, incl terminals

This commit is contained in:
Joe Savona
2022-11-22 14:10:06 -08:00
parent a0054a1837
commit e51553f5da
10 changed files with 159 additions and 49 deletions
+15 -10
View File
@@ -66,7 +66,9 @@ class Driver<TBlock, TValue, TItem, TCase> {
switch (terminal.kind) {
case "return": {
const value =
terminal.value != null ? this.visitPlace(terminal.value) : null;
terminal.value != null
? this.visitPlace(terminal.value, terminal.id)
: null;
this.visitor.visitTerminalId(terminal.id);
this.visitor.appendBlock(
blockValue,
@@ -78,7 +80,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
break;
}
case "throw": {
const value = this.visitPlace(terminal.value);
const value = this.visitPlace(terminal.value, terminal.id);
this.visitor.visitTerminalId(terminal.id);
this.visitor.appendBlock(
blockValue,
@@ -90,7 +92,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
break;
}
case "if": {
const test = this.visitPlace(terminal.test);
const test = this.visitPlace(terminal.test, terminal.id);
const fallthroughId =
terminal.fallthrough !== null &&
!this.cx.isScheduled(terminal.fallthrough)
@@ -152,7 +154,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
break;
}
case "switch": {
const test = this.visitPlace(terminal.test);
const test = this.visitPlace(terminal.test, terminal.id);
const fallthroughId =
terminal.fallthrough !== null &&
!this.cx.isScheduled(terminal.fallthrough)
@@ -166,7 +168,10 @@ class Driver<TBlock, TValue, TItem, TCase> {
this.visitor.visitTerminalId(terminal.id);
const cases: Array<TCase> = [];
[...terminal.cases].reverse().forEach((case_, index) => {
const test = case_.test !== null ? this.visitPlace(case_.test) : null;
const test =
case_.test !== null
? this.visitPlace(case_.test, terminal.id)
: null;
let consequent;
if (this.cx.isScheduled(case_.block)) {
@@ -241,7 +246,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
// body.length === bodyLength,
// "Expected test to produce only temporaries"
// );
const testValue = this.visitPlace(testTerminal.test);
const testValue = this.visitPlace(testTerminal.test, terminal.id);
const fallthroughId =
terminal.fallthrough !== null &&
!this.cx.isScheduled(terminal.fallthrough)
@@ -391,13 +396,13 @@ class Driver<TBlock, TValue, TItem, TCase> {
}
visitInstr(instr: Instruction, blockValue: TBlock): void {
const value = this.visitor.visitValue(instr.value);
const value = this.visitor.visitValue(instr.value, instr.id);
const item = this.visitor.visitInstruction(instr, value);
this.visitor.appendBlock(blockValue, item);
}
visitPlace(place: Place): TValue {
return this.visitor.visitValue(place);
visitPlace(place: Place, id: InstructionId): TValue {
return this.visitor.visitValue(place, id);
}
}
@@ -642,7 +647,7 @@ export interface Visitor<TBlock, TValue, TItem, TCase> {
* Convert an InstructionValue into the visitor's own representation
* of a value.
*/
visitValue(value: InstructionValue): TValue;
visitValue(value: InstructionValue, id: InstructionId): TValue;
/**
* Convert an Instruction into the visitor's own representation of
+24 -6
View File
@@ -17,7 +17,10 @@ import {
ScopeId,
} from "./HIR";
import { BlockTerminal, Visitor, visitTree } from "./HIRTreeVisitor";
import { eachInstructionOperand } from "./visitors";
import {
eachInstructionOperand,
eachInstructionValueOperand,
} from "./visitors";
/**
* This is a second (final) stage of constructing reactive scopes. Prior to this pass,
@@ -249,13 +252,28 @@ class MergeOverlappingReactiveScopesVisitor
enterBlock(): void {
this.scopes.push(new BlockScope());
}
visitValue(value: InstructionValue): void {}
visitInstruction(instruction: Instruction, value: void): void {
const scope = getInstructionScope(instruction);
if (scope !== null && instruction.id < scope.range.end) {
this.visitScope(scope);
visitValue(value: InstructionValue, id: InstructionId): void {
this.visitId(id);
for (const operand of eachInstructionValueOperand(value)) {
if (
operand.identifier.scope !== null &&
id >= operand.identifier.scope.range.start &&
id < operand.identifier.scope.range.end
) {
this.visitScope(operand.identifier.scope);
}
}
}
visitInstruction(instruction: Instruction, value: void): void {
this.visitId(instruction.id);
if (
instruction.lvalue !== null &&
instruction.lvalue.place.identifier.scope !== null &&
instruction.id >= instruction.lvalue.place.identifier.scope.range.start &&
instruction.id < instruction.lvalue.place.identifier.scope.range.end
) {
this.visitScope(instruction.lvalue.place.identifier.scope);
}
}
visitTerminalId(id: InstructionId): void {
this.visitId(id);
+6 -1
View File
@@ -10,13 +10,18 @@ import {
BasicBlock,
BlockId,
Instruction,
InstructionValue,
makeInstructionId,
Place,
Terminal,
} from "./HIR";
export function* eachInstructionOperand(instr: Instruction): Iterable<Place> {
const instrValue = instr.value;
yield* eachInstructionValueOperand(instr.value);
}
export function* eachInstructionValueOperand(
instrValue: InstructionValue
): Iterable<Place> {
switch (instrValue.kind) {
case "NewExpression":
case "CallExpression": {
@@ -33,8 +33,8 @@ bb4:
[4] If (read c$9) then:bb6 else:bb1
bb6:
predecessor blocks: bb4
[5] Const mutate $11_@0[1:8] = 0
[6] Call mutate x$10_@0.push(read $11_@0)
[5] Const mutate $11_@1 = 0
[6] Call mutate x$10_@0.push(read $11_@1)
[7] Goto bb1
bb1:
predecessor blocks: bb6 bb4 bb2 bb0
@@ -67,8 +67,8 @@ flowchart TB
end
subgraph bb6
bb6_instrs["
[5] Const mutate $11_@0[1:8] = 0
[6] Call mutate x$10_@0.push(read $11_@0)
[5] Const mutate $11_@1 = 0
[6] Call mutate x$10_@0.push(read $11_@1)
"]
bb6_instrs --> bb6_terminal(["Goto"])
end
@@ -0,0 +1,72 @@
## Input
```javascript
function foo(a, b, c) {
const x = [];
const y = [];
if (x) {
}
y.push(a);
x.push(b);
}
```
## HIR
```
bb0:
[1] Const mutate x$9_@0[1:6] = Array []
[2] Const mutate y$10_@0[1:6] = Array []
[3] If (read x$9_@0) then:bb1 else:bb1
bb1:
predecessor blocks: bb0
[4] Call mutate y$10_@0.push(read a$6)
[5] Call mutate x$9_@0.push(read b$7)
[6] Return
```
### CFG
```mermaid
flowchart TB
%% Basic Blocks
subgraph bb0
bb0_instrs["
[1] Const mutate x$9_@0[1:6] = Array []
[2] Const mutate y$10_@0[1:6] = Array []
"]
bb0_instrs --> bb0_terminal(["If (read x$9_@0)"])
end
subgraph bb1
bb1_instrs["
[4] Call mutate y$10_@0.push(read a$6)
[5] Call mutate x$9_@0.push(read b$7)
"]
bb1_instrs --> bb1_terminal(["Return"])
end
%% Jumps
bb0_terminal -- "then" --> bb1
bb0_terminal -- "else" --> bb1
```
## Code
```javascript
function foo$0(a$1, b$2, c$3) {
const x$4 = [];
const y$5 = [];
bb1: if (x$4) {
}
y$5.push(a$1);
x$4.push(b$2);
}
```
@@ -0,0 +1,10 @@
function foo(a, b, c) {
const x = [];
const y = [];
if (x) {
}
y.push(a);
x.push(b);
}
@@ -34,8 +34,8 @@ bb4:
bb3:
predecessor blocks: bb4 bb2
[7] Const mutate $13_@2 = "div"
[8] Const mutate $15_@0[1:11] = JSX <read $13_@2>{freeze y$12_@1}</read $13_@2>
[9] Call mutate x$11_@0.push(read $15_@0)
[8] Const mutate $15_@3 = JSX <read $13_@2>{freeze y$12_@1}</read $13_@2>
[9] Call mutate x$11_@0.push(read $15_@3)
[10] Goto bb1
bb1:
predecessor blocks: bb3 bb0
@@ -68,8 +68,8 @@ flowchart TB
subgraph bb3
bb3_instrs["
[7] Const mutate $13_@2 = 'div'
[8] Const mutate $15_@0[1:11] = JSX <read $13_@2>{freeze y$12_@1}</read $13_@2>
[9] Call mutate x$11_@0.push(read $15_@0)
[8] Const mutate $15_@3 = JSX <read $13_@2>{freeze y$12_@1}</read $13_@2>
[9] Call mutate x$11_@0.push(read $15_@3)
"]
bb3_instrs --> bb3_terminal(["Goto"])
end
@@ -47,7 +47,7 @@ function log$0() {}
```
bb0:
[1] Let mutate str$6_@2[0:9] = ""
[1] Let mutate str$6_@0[1:8] = ""
[2] If (read cond$5) then:bb2 else:bb3
bb2:
predecessor blocks: bb0
@@ -56,12 +56,12 @@ bb2:
[5] Goto bb1
bb3:
predecessor blocks: bb0
[6] Reassign mutate str$8_@2[0:9] = "fallthrough test"
[6] Reassign mutate str$8_@0[1:8] = "fallthrough test"
[7] Goto bb1
bb1:
predecessor blocks: bb2 bb3
str$10_@2[0:9]: phi(bb2: str$6_@2, bb3: str$8_@2)
[8] Call mutate log$4_@2(read str$10_@2)
str$10_@0[1:8]: phi(bb2: str$6_@0, bb3: str$8_@0)
[8] Call mutate log$4_@2(read str$10_@0)
[9] Return
```
@@ -72,7 +72,7 @@ flowchart TB
%% Basic Blocks
subgraph bb0
bb0_instrs["
[1] Let mutate str$6_@2[0:9] = ''
[1] Let mutate str$6_@0[1:8] = ''
"]
bb0_instrs --> bb0_terminal(["If (read cond$5)"])
end
@@ -85,13 +85,13 @@ flowchart TB
end
subgraph bb3
bb3_instrs["
[6] Reassign mutate str$8_@2[0:9] = 'fallthrough test'
[6] Reassign mutate str$8_@0[1:8] = 'fallthrough test'
"]
bb3_instrs --> bb3_terminal(["Goto"])
end
subgraph bb1
bb1_instrs["
[8] Call mutate log$4_@2(read str$10_@2)
[8] Call mutate log$4_@2(read str$10_@0)
"]
bb1_instrs --> bb1_terminal(["Return"])
end
@@ -39,23 +39,23 @@ bb0:
Default: bb2
bb5:
predecessor blocks: bb0
[7] Const mutate $15_@6[7:17] = 1
[8] Reassign mutate x$16_@6[7:17] = Binary read x$10_@0 + read $15_@6
[7] Const mutate $15_@5 = 1
[8] Reassign mutate x$16_@6[8:17] = Binary read x$10_@0 + read $15_@5
[9] Goto bb1
bb3:
predecessor blocks: bb0
[10] Const mutate $17_@6[7:17] = 2
[11] Reassign mutate x$18_@6[7:17] = Binary read x$10_@0 + read $17_@6
[10] Const mutate $17_@7 = 2
[11] Reassign mutate x$18_@6[8:17] = Binary read x$10_@0 + read $17_@7
[12] Goto bb1
bb2:
predecessor blocks: bb0
[13] Const mutate $19_@8 = 3
[14] Reassign mutate x$20_@6[7:17] = Binary read x$10_@0 + read $19_@8
[14] Reassign mutate x$20_@6[8:17] = Binary read x$10_@0 + read $19_@8
[15] Goto bb1
bb1:
predecessor blocks: bb5 bb3 bb2
x$21_@6[7:17]: phi(bb5: x$16_@6, bb3: x$18_@6, bb2: x$20_@6)
[16] Let mutate y$22_@6[7:17] = read x$21_@6
x$21_@6[8:17]: phi(bb5: x$16_@6, bb3: x$18_@6, bb2: x$20_@6)
[16] Let mutate y$22_@6[8:17] = read x$21_@6
[17] Return
```
@@ -76,28 +76,28 @@ flowchart TB
end
subgraph bb5
bb5_instrs["
[7] Const mutate $15_@6[7:17] = 1
[8] Reassign mutate x$16_@6[7:17] = Binary read x$10_@0 + read $15_@6
[7] Const mutate $15_@5 = 1
[8] Reassign mutate x$16_@6[8:17] = Binary read x$10_@0 + read $15_@5
"]
bb5_instrs --> bb5_terminal(["Goto"])
end
subgraph bb3
bb3_instrs["
[10] Const mutate $17_@6[7:17] = 2
[11] Reassign mutate x$18_@6[7:17] = Binary read x$10_@0 + read $17_@6
[10] Const mutate $17_@7 = 2
[11] Reassign mutate x$18_@6[8:17] = Binary read x$10_@0 + read $17_@7
"]
bb3_instrs --> bb3_terminal(["Goto"])
end
subgraph bb2
bb2_instrs["
[13] Const mutate $19_@8 = 3
[14] Reassign mutate x$20_@6[7:17] = Binary read x$10_@0 + read $19_@8
[14] Reassign mutate x$20_@6[8:17] = Binary read x$10_@0 + read $19_@8
"]
bb2_instrs --> bb2_terminal(["Goto"])
end
subgraph bb1
bb1_instrs["
[16] Let mutate y$22_@6[7:17] = read x$21_@6
[16] Let mutate y$22_@6[8:17] = read x$21_@6
"]
bb1_instrs --> bb1_terminal(["Return"])
end
@@ -27,8 +27,8 @@ bb1:
[5] If (read $8_@2) then:bb3 else:bb2
bb3:
predecessor blocks: bb1
[6] Const mutate $9_@0[0:9] = 1
[7] Reassign mutate x$10_@0[0:9] = Binary read x$7_@0 + read $9_@0
[6] Const mutate $9_@3 = 1
[7] Reassign mutate x$10_@0[0:9] = Binary read x$7_@0 + read $9_@3
[8] Goto(Continue) bb1
bb2:
predecessor blocks: bb1
@@ -55,8 +55,8 @@ flowchart TB
end
subgraph bb3
bb3_instrs["
[6] Const mutate $9_@0[0:9] = 1
[7] Reassign mutate x$10_@0[0:9] = Binary read x$7_@0 + read $9_@0
[6] Const mutate $9_@3 = 1
[7] Reassign mutate x$10_@0[0:9] = Binary read x$7_@0 + read $9_@3
"]
bb3_instrs --> bb3_terminal(["Goto"])
end