Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(303)

Side by Side Diff: test/unittests/compiler/escape-analysis-unittest.cc

Issue 1457683003: [turbofan] Initial support for escape analysis. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add more DCHECKS Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/bit-vector.h"
6 #include "src/compiler/escape-analysis.h"
7 #include "src/compiler/escape-analysis-reducer.h"
8 #include "src/compiler/graph-visualizer.h"
9 #include "src/compiler/node-properties.h"
10 #include "src/compiler/simplified-operator.h"
11 #include "src/types-inl.h"
12 #include "src/zone-containers.h"
13 #include "test/unittests/compiler/graph-unittest.h"
14
15 namespace v8 {
16 namespace internal {
17 namespace compiler {
18
19 class EscapeAnalysisTest : public GraphTest {
20 public:
21 EscapeAnalysisTest()
22 : simplified_(zone()),
23 jsgraph_(isolate(), graph(), nullptr, nullptr, nullptr, nullptr),
24 escape_status_(graph(), zone()),
25 escape_objects_(graph(), common(), zone()),
26 effect_(graph()->start()),
27 control_(graph()->start()) {}
28
29 ~EscapeAnalysisTest() {}
30
31 EscapeStatusAnalysis* escape_status() { return &escape_status_; }
32 EscapeObjectAnalysis* escape_objects() { return &escape_objects_; }
33
34 protected:
35 void Analysis() {
36 escape_status_.Run();
37 escape_objects_.Run();
38 }
39
40 void Transformation() {
41 GraphReducer graph_reducer(zone(), graph());
42 EscapeAnalysisReducer escape_reducer(
43 &graph_reducer, &jsgraph_, &escape_status_, &escape_objects_, zone());
44 graph_reducer.AddReducer(&escape_reducer);
45 graph_reducer.ReduceGraph();
46 }
47
48 // ---------------------------------Node Creation Helper----------------------
49
50 Node* BeginRegion(Node* effect = nullptr) {
51 if (!effect) {
52 effect = effect_;
53 }
54
55 return effect_ = graph()->NewNode(common()->BeginRegion(), effect);
56 }
57
58 Node* FinishRegion(Node* value, Node* effect = nullptr) {
59 if (!effect) {
60 effect = effect_;
61 }
62 return effect_ = graph()->NewNode(common()->FinishRegion(), value, effect);
63 }
64
65 Node* Allocate(Node* size, Node* effect = nullptr, Node* control = nullptr) {
66 if (!effect) {
67 effect = effect_;
68 }
69 if (!control) {
70 control = control_;
71 }
72 return effect_ = graph()->NewNode(simplified()->Allocate(), size, effect,
73 control);
74 }
75
76 Node* Constant(int num) {
77 return graph()->NewNode(common()->NumberConstant(num));
78 }
79
80 Node* Store(const FieldAccess& access, Node* allocation, Node* value,
81 Node* effect = nullptr, Node* control = nullptr) {
82 if (!effect) {
83 effect = effect_;
84 }
85 if (!control) {
86 control = control_;
87 }
88 return effect_ = graph()->NewNode(simplified()->StoreField(access),
89 allocation, value, effect, control);
90 }
91
92 Node* Load(const FieldAccess& access, Node* from, Node* effect = nullptr,
93 Node* control = nullptr) {
94 if (!effect) {
95 effect = effect_;
96 }
97 if (!control) {
98 control = control_;
99 }
100 return graph()->NewNode(simplified()->LoadField(access), from, effect,
101 control);
102 }
103
104 Node* Return(Node* value, Node* effect = nullptr, Node* control = nullptr) {
105 if (!effect) {
106 effect = effect_;
107 }
108 if (!control) {
109 control = control_;
110 }
111 return control_ =
112 graph()->NewNode(common()->Return(), value, effect, control);
113 }
114
115 void EndGraph() {
116 for (Edge edge : graph()->end()->input_edges()) {
117 if (NodeProperties::IsControlEdge(edge)) {
118 edge.UpdateTo(control_);
119 }
120 }
121 }
122
123 Node* Branch() {
124 return control_ =
125 graph()->NewNode(common()->Branch(), Constant(0), control_);
126 }
127
128 Node* IfTrue() {
129 return control_ = graph()->NewNode(common()->IfTrue(), control_);
130 }
131
132 Node* IfFalse() { return graph()->NewNode(common()->IfFalse(), control_); }
133
134 Node* Merge2(Node* control1, Node* control2) {
135 return control_ = graph()->NewNode(common()->Merge(2), control1, control2);
136 }
137
138 FieldAccess AccessAtIndex(int offset) {
139 FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(),
140 kMachAnyTagged};
141 return access;
142 }
143
144 // ---------------------------------Assertion Helper--------------------------
145
146 void ExpectRepresentation(Node* node, Node* rep) {
147 EXPECT_EQ(rep, escape_objects()->GetReplacement(node, node->id()));
148 }
149
150 void ExpectRepresentationPhi(Node* node, Node* left, Node* right) {
151 Node* rep = escape_objects()->GetReplacement(node, node->id());
152 ASSERT_NE(nullptr, rep);
153 ASSERT_EQ(IrOpcode::kPhi, rep->opcode());
154 EXPECT_EQ(left, NodeProperties::GetValueInput(rep, 0));
155 EXPECT_EQ(right, NodeProperties::GetValueInput(rep, 1));
156 }
157
158 void ExpectVirtual(Node* node) {
159 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate ||
160 node->opcode() == IrOpcode::kFinishRegion);
161 EXPECT_TRUE(escape_status()->IsVirtual(node));
162 }
163
164 void ExpectEscaped(Node* node) {
165 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate ||
166 node->opcode() == IrOpcode::kFinishRegion);
167 EXPECT_TRUE(escape_status()->IsEscaped(node));
168 }
169
170 SimplifiedOperatorBuilder* simplified() { return &simplified_; }
171
172 Node* effect() { return effect_; }
173
174 private:
175 SimplifiedOperatorBuilder simplified_;
176 JSGraph jsgraph_;
177 EscapeStatusAnalysis escape_status_;
178 EscapeObjectAnalysis escape_objects_;
179
180 Node* effect_;
181 Node* control_;
182 };
183
184
185 // -----------------------------------------------------------------------------
186 // Test cases.
187
188
189 TEST_F(EscapeAnalysisTest, StraightNonEscape) {
190 Node* object1 = Constant(1);
191 BeginRegion();
192 Node* allocation = Allocate(Constant(8));
193 Store(AccessAtIndex(0), allocation, object1);
194 Node* finish = FinishRegion(allocation);
195 Node* load = Load(AccessAtIndex(0), finish);
196 Node* result = Return(load);
197 EndGraph();
198 Analysis();
199
200 ExpectVirtual(allocation);
201 ExpectRepresentation(load, object1);
202
203 Transformation();
204
205 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0));
206 }
207
208
209 TEST_F(EscapeAnalysisTest, StraightEscape) {
210 Node* object1 = Constant(1);
211 BeginRegion();
212 Node* allocation = Allocate(Constant(8));
213 Store(AccessAtIndex(0), allocation, object1);
214 Node* finish = FinishRegion(allocation);
215 Node* load = Load(AccessAtIndex(0), finish);
216 Node* result = Return(allocation);
217 EndGraph();
218 Analysis();
219
220 ExpectEscaped(allocation);
221 ExpectRepresentation(load, object1);
222
223 Transformation();
224
225 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0));
226 }
227
228
229 TEST_F(EscapeAnalysisTest, BranchNonEscape) {
230 Node* object1 = Constant(1);
231 Node* object2 = Constant(2);
232 BeginRegion();
233 Node* allocation = Allocate(Constant(8));
234 Store(AccessAtIndex(0), allocation, object1);
235 Node* finish = FinishRegion(allocation);
236 Branch();
237 Node* ifFalse = IfFalse();
238 Node* ifTrue = IfTrue();
239 Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish, ifFalse);
240 Node* effect2 = Store(AccessAtIndex(0), allocation, object2, finish, ifTrue);
241 Node* merge = Merge2(ifFalse, ifTrue);
242 Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge);
243 Node* load = Load(AccessAtIndex(0), finish, phi, merge);
244 Node* result = Return(load, phi);
245 EndGraph();
246 Analysis();
247
248 ExpectVirtual(allocation);
249 ExpectRepresentationPhi(load, object1, object2);
250 Node* replacement_phi = escape_objects()->GetReplacement(load, load->id());
251
252 Transformation();
253
254 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 0));
255 }
256
257
258 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) {
259 Node* object1 = Constant(1);
260 Node* object2 = Constant(2);
261 Node* allocation = Allocate(Constant(8));
262 Node* store1 = Store(AccessAtIndex(0), allocation, object1);
263 Node* load1 = Load(AccessAtIndex(0), allocation);
264 Store(AccessAtIndex(0), allocation, object2);
265 Node* load2 = Load(AccessAtIndex(0), allocation, store1);
266 Node* result = Return(load2);
267 EndGraph();
268
269 Analysis();
270
271 ExpectVirtual(allocation);
272 ExpectRepresentation(load1, object1);
273 ExpectRepresentation(load2, object1);
274
275 Transformation();
276
277 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0));
278 }
279
280 } // namespace compiler
281 } // namespace internal
282 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698