@samitouri / QOS-React-2 / commits / 7bdd0f03cb

[hir] Perform alias analysis for aggregate rvalues

Maintain and use abstract memory to peform more refined aliasing of member expressions.

Sathya Gunasekaran committed Dec 1, 2022 at 19:03 UTC 7bdd0f03cb529f673a632e2a774b6a9de4fec5e4
2 files changed +85 -26
compiler/forget/src/HIR/BuildAliasSets.ts
+59
@@ -37,6 +37,65 @@ class AbstractState {
37 if (value.kind !== "Primitive") {
38 this.aliases.union([lvalue.place.identifier, alias.identifier]);
39 }
40 + return;
41 + }
42 +
43 + // Complex alias:
44 + // lvalue = alias.memberPath;
45 + if (alias.memberPath.length > 1) {
46 + // TODO(gsn): Handle nested member paths
47 + return;
48 + }
49 +
50 + let object = this.#values.get(alias.identifier);
51 +
52 + // Don't know what this, let's default to an Object conservatively.
53 + if (object === undefined) {
54 + object = { kind: "Object", values: new Map() };
55 + }
56 +
57 + // We're doing a member lookup on a non object.
58 + //
59 + // alias = 1;
60 + // lvalue = alias.memberPath;
61 + if (object.kind !== "Object") {
62 + // Conservatively type the value as object.
63 + //
64 + // NOTE(gsn): Should this be an AbstractUnknown rather than an
65 + // AbstractObject?
66 + this.#values.set(lvalue.place.identifier, {
67 + kind: "Object",
68 + values: new Map(),
69 + });
70 + this.aliases.union([lvalue.place.identifier, alias.identifier]);
71 + return;
72 + }
73 +
74 + let value = object.values.get(alias.memberPath[0]);
75 +
76 + // We don't have a value for this member path.
77 + //
78 + // alias = {};
79 + // lvalue = alias.memberPath;
80 + if (value === undefined) {
81 + // Conservatively type the value as object.
82 + this.#values.set(lvalue.place.identifier, {
83 + kind: "Object",
84 + values: new Map(),
85 + });
86 + this.aliases.union([lvalue.place.identifier, alias.identifier]);
87 + return;
88 + }
89 +
90 + // We have a value for this memberPath!
91 + //
92 + // alias.memberPath = value;
93 + // lvalue = alias.memberPath;
94 + this.#values.set(lvalue.place.identifier, value);
95 +
96 + // No need to alias Primitives.
97 + if (value.kind !== "Primitive") {
98 + this.aliases.union([lvalue.place.identifier, alias.identifier]);
99 }
100 }
101
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+26 -26
@@ -37,7 +37,7 @@ function Component(props) {
37 bb0:
38 [1] Const mutate items$27_@0 = read props$26.items
39 [2] Const mutate maxItems$28_@1 = read props$26.maxItems
40 - [3] Const mutate renderedItems$29_@2[3:22] = Array []
40 + [3] Const mutate renderedItems$29_@2[3:26] = Array []
41 [4] Const mutate seen$30_@3[0:19] = New mutate Set$6_@3()
42 [5] Const mutate $31_@4 = 0
43 [6] Const mutate max$32_@5[0:7] = Call mutate Math$8_@5.max(read $31_@4, read maxItems$28_@1)
@@ -71,23 +71,23 @@ bb4:
71 [19] Const mutate $43_@7 = "div"
72 [20] Const mutate $44_@8 = JSX <read $43_@7>{read item$10_@3}</read $43_@7>
73 [21] Call mutate renderedItems$29_@2.push(read $44_@8)
74 - [22] Const mutate $49_@9 = Binary read renderedItems$29_@2.length >= read max$32_@5
75 - [23] If (read $49_@9) then:bb2 else:bb10
74 + [22] Const mutate $49_@2[3:26] = Binary read renderedItems$29_@2.length >= read max$32_@5
75 + [23] If (read $49_@2) then:bb2 else:bb10
76 bb10:
77 predecessor blocks: bb4
78 [24] Goto(Continue) bb1
79 bb2:
80 predecessor blocks: bb4 bb1
81 - [25] Const mutate count$52_@10 = read renderedItems$29_@2.length
82 - [26] Const mutate $53_@11 = "div"
83 - [27] Const mutate $54_@12 = "\n "
84 - [28] Const mutate $55_@13 = "h1"
85 - [29] Const mutate $56_@14 = " Items"
86 - [30] Const mutate $57_@15 = JSX <read $55_@13>{freeze count$52_@10}{read $56_@14}</read $55_@13>
87 - [31] Const mutate $58_@16 = "\n "
88 - [32] Const mutate $59_@17 = "\n "
89 - [33] Const mutate $60_@18 = JSX <read $53_@11>{read $54_@12}{read $57_@15}{read $58_@16}{freeze renderedItems$29_@2}{read $59_@17}</read $53_@11>
90 - [34] Return read $60_@18
81 + [25] Const mutate count$52_@2[3:26] = read renderedItems$29_@2.length
82 + [26] Const mutate $53_@9 = "div"
83 + [27] Const mutate $54_@10 = "\n "
84 + [28] Const mutate $55_@11 = "h1"
85 + [29] Const mutate $56_@12 = " Items"
86 + [30] Const mutate $57_@13 = JSX <read $55_@11>{freeze count$52_@2}{read $56_@12}</read $55_@11>
87 + [31] Const mutate $58_@14 = "\n "
88 + [32] Const mutate $59_@15 = "\n "
89 + [33] Const mutate $60_@16 = JSX <read $53_@9>{read $54_@10}{read $57_@13}{read $58_@14}{freeze renderedItems$29_@2}{read $59_@15}</read $53_@9>
90 + [34] Return read $60_@16
91 scope0 [1:2]:
92 - read props$26.items
93 scope1 [2:3]:
@@ -103,7 +103,7 @@ flowchart TB
103 bb0_instrs["
104 [1] Const mutate items$27_@0 = read props$26.items
105 [2] Const mutate maxItems$28_@1 = read props$26.maxItems
106 - [3] Const mutate renderedItems$29_@2[3:22] = Array []
106 + [3] Const mutate renderedItems$29_@2[3:26] = Array []
107 [4] Const mutate seen$30_@3[0:19] = New mutate Set$6_@3()
108 [5] Const mutate $31_@4 = 0
109 [6] Const mutate max$32_@5[0:7] = Call mutate Math$8_@5.max(read $31_@4, read maxItems$28_@1)
@@ -144,26 +144,26 @@ flowchart TB
144 [19] Const mutate $43_@7 = 'div'
145 [20] Const mutate $44_@8 = JSX <read $43_@7>{read item$10_@3}</read $43_@7>
146 [21] Call mutate renderedItems$29_@2.push(read $44_@8)
147 - [22] Const mutate $49_@9 = Binary read renderedItems$29_@2.length >= read max$32_@5
147 + [22] Const mutate $49_@2[3:26] = Binary read renderedItems$29_@2.length >= read max$32_@5
148 "]
149 - bb4_instrs --> bb4_terminal(["If (read $49_@9)"])
149 + bb4_instrs --> bb4_terminal(["If (read $49_@2)"])
150 end
151 subgraph bb10
152 bb10_terminal(["Goto"])
153 end
154 subgraph bb2
155 bb2_instrs["
156 - [25] Const mutate count$52_@10 = read renderedItems$29_@2.length
157 - [26] Const mutate $53_@11 = 'div'
158 - [27] Const mutate $54_@12 = '\n '
159 - [28] Const mutate $55_@13 = 'h1'
160 - [29] Const mutate $56_@14 = ' Items'
161 - [30] Const mutate $57_@15 = JSX <read $55_@13>{freeze count$52_@10}{read $56_@14}</read $55_@13>
162 - [31] Const mutate $58_@16 = '\n '
163 - [32] Const mutate $59_@17 = '\n '
164 - [33] Const mutate $60_@18 = JSX <read $53_@11>{read $54_@12}{read $57_@15}{read $58_@16}{freeze renderedItems$29_@2}{read $59_@17}</read $53_@11>
156 + [25] Const mutate count$52_@2[3:26] = read renderedItems$29_@2.length
157 + [26] Const mutate $53_@9 = 'div'
158 + [27] Const mutate $54_@10 = '\n '
159 + [28] Const mutate $55_@11 = 'h1'
160 + [29] Const mutate $56_@12 = ' Items'
161 + [30] Const mutate $57_@13 = JSX <read $55_@11>{freeze count$52_@2}{read $56_@12}</read $55_@11>
162 + [31] Const mutate $58_@14 = '\n '
163 + [32] Const mutate $59_@15 = '\n '
164 + [33] Const mutate $60_@16 = JSX <read $53_@9>{read $54_@10}{read $57_@13}{read $58_@14}{freeze renderedItems$29_@2}{read $59_@15}</read $53_@9>
165 "]
166 - bb2_instrs --> bb2_terminal(["Return read $60_@18"])
166 + bb2_instrs --> bb2_terminal(["Return read $60_@16"])
167 end
168
169 %% Jumps