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

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: 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_(nullptr),
25 escape_objects_(nullptr),
26 effect_(graph()->start()),
27 control_(graph()->start()) {}
28
29 ~EscapeAnalysisTest() {
30 if (escape_status_) {
31 delete escape_status_;
32 }
33 if (escape_objects_) {
34 delete escape_objects_;
35 }
36 }
37
38 EscapeStatusAnalysis* escape_status() { return escape_status_; }
39 EscapeObjectAnalysis* escape_objects() { return escape_objects_; }
40
41 protected:
42 void Analysis() {
43 escape_status_ = new EscapeStatusAnalysis(graph(), zone());
Michael Starzinger 2015/11/30 10:05:39 Would it be possible to just embed these two class
sigurds 2015/11/30 13:50:24 Done.
44 escape_status_->Run();
45 escape_objects_ = new EscapeObjectAnalysis(graph(), common(), zone());
46 escape_objects_->Run();
47 }
48
49 void Transformation() {
50 GraphReducer graph_reducer(zone(), graph());
51 EscapeAnalysisReducer red(&graph_reducer, &jsgraph_, escape_status_,
52 escape_objects_, zone());
53 graph_reducer.AddReducer(&red);
54 graph_reducer.ReduceGraph();
55 }
56
57 // ---------------------------------Node Creation Helper----------------------
58
59 Node* BeginRegion(Node* effect = nullptr) {
60 if (!effect) {
61 effect = effect_;
62 }
63
64 return effect_ = graph()->NewNode(common()->BeginRegion(), effect);
65 }
66
67 Node* FinishRegion(Node* value, Node* effect = nullptr) {
68 if (!effect) {
69 effect = effect_;
70 }
71 return effect_ = graph()->NewNode(common()->FinishRegion(), value, effect);
72 }
73
74 Node* Allocate(Node* size, Node* effect = nullptr, Node* control = nullptr) {
75 if (!effect) {
76 effect = effect_;
77 }
78 if (!control) {
79 control = control_;
80 }
81 return effect_ = graph()->NewNode(simplified()->Allocate(), size, effect,
82 control);
83 }
84
85 Node* Constant(int num) {
86 return graph()->NewNode(common()->NumberConstant(num));
87 }
88
89 Node* Store(const FieldAccess& access, Node* allocation, Node* value,
90 Node* effect = nullptr, Node* control = nullptr) {
91 if (!effect) {
92 effect = effect_;
93 }
94 if (!control) {
95 control = control_;
96 }
97 return effect_ = graph()->NewNode(simplified()->StoreField(access),
98 allocation, value, effect, control);
99 }
100
101 Node* Load(const FieldAccess& access, Node* from, Node* effect = nullptr,
102 Node* control = nullptr) {
103 if (!effect) {
104 effect = effect_;
105 }
106 if (!control) {
107 control = control_;
108 }
109 return graph()->NewNode(simplified()->LoadField(access), from, effect,
110 control);
111 }
112
113 Node* Return(Node* value, Node* effect = nullptr, Node* control = nullptr) {
114 if (!effect) {
115 effect = effect_;
116 }
117 if (!control) {
118 control = control_;
119 }
120 return control_ =
121 graph()->NewNode(common()->Return(), value, effect, control);
122 }
123
124 void EndGraph() {
125 for (Edge edge : graph()->end()->input_edges()) {
126 if (NodeProperties::IsControlEdge(edge)) {
127 edge.UpdateTo(control_);
128 }
129 }
130 }
131
132 Node* Branch() {
133 return control_ =
134 graph()->NewNode(common()->Branch(), Constant(0), control_);
135 }
136
137 Node* IfTrue() {
138 return control_ = graph()->NewNode(common()->IfTrue(), control_);
139 }
140
141 Node* IfFalse() { return graph()->NewNode(common()->IfFalse(), control_); }
142
143 Node* Merge2(Node* control1, Node* control2) {
144 return control_ = graph()->NewNode(common()->Merge(2), control1, control2);
145 }
146
147 FieldAccess AccessAtIndex(int offset) {
148 FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(),
149 kMachAnyTagged};
150 return access;
151 }
152
153 // ---------------------------------Assertion Helper--------------------------
154
155 void ExpectRepresentation(Node* node, Node* rep) {
156 EXPECT_EQ(rep, escape_objects()->representation(node, node->id()));
157 }
158
159 void ExpectRepresentationPhi(Node* node, Node* left, Node* right) {
160 Node* rep = escape_objects()->representation(node, node->id());
161 ASSERT_NE(nullptr, rep);
162 ASSERT_EQ(IrOpcode::kPhi, rep->opcode());
163 EXPECT_EQ(left, NodeProperties::GetValueInput(rep, 0));
164 EXPECT_EQ(right, NodeProperties::GetValueInput(rep, 1));
165 }
166
167 void ExpectVirtual(Node* node) {
168 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate ||
169 node->opcode() == IrOpcode::kFinishRegion);
170 EXPECT_TRUE(escape_status()->IsVirtual(node));
171 }
172
173 void ExpectEscaped(Node* node) {
174 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate ||
175 node->opcode() == IrOpcode::kFinishRegion);
176 EXPECT_TRUE(escape_status()->IsEscaped(node));
177 }
178
179 SimplifiedOperatorBuilder* simplified() { return &simplified_; }
180
181 Node* effect() { return effect_; }
182
183 private:
184 SimplifiedOperatorBuilder simplified_;
185 JSGraph jsgraph_;
186 EscapeStatusAnalysis* escape_status_;
187 EscapeObjectAnalysis* escape_objects_;
188
189 Node* effect_;
190 Node* control_;
191 };
192
193
194 // -----------------------------------------------------------------------------
195 // Test cases.
196
197
198 TEST_F(EscapeAnalysisTest, StraightNonEscape) {
199 Node* object1 = Constant(1);
200 BeginRegion();
201 Node* allocation = Allocate(Constant(8));
202 Store(AccessAtIndex(0), allocation, object1);
203 Node* finish = FinishRegion(allocation);
204 Node* load = Load(AccessAtIndex(0), finish);
205 Node* result = Return(load);
206 EndGraph();
207 Analysis();
208
209 ExpectVirtual(allocation);
210 ExpectRepresentation(load, object1);
211
212 Transformation();
213
214 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0));
215 }
216
217
218 TEST_F(EscapeAnalysisTest, StraightEscape) {
219 Node* object1 = Constant(1);
220 BeginRegion();
221 Node* allocation = Allocate(Constant(8));
222 Store(AccessAtIndex(0), allocation, object1);
223 Node* finish = FinishRegion(allocation);
224 Node* load = Load(AccessAtIndex(0), finish);
225 Node* result = Return(allocation);
226 EndGraph();
227 Analysis();
228
229 ExpectEscaped(allocation);
230 ExpectRepresentation(load, object1);
231
232 Transformation();
233
234 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0));
235 }
236
237
238 TEST_F(EscapeAnalysisTest, BranchNonEscape) {
239 Node* object1 = Constant(1);
240 Node* object2 = Constant(2);
241 BeginRegion();
242 Node* allocation = Allocate(Constant(8));
243 Store(AccessAtIndex(0), allocation, object1);
244 Node* finish = FinishRegion(allocation);
245 Branch();
246 Node* ifFalse = IfFalse();
247 Node* ifTrue = IfTrue();
248 Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish, ifFalse);
249 Node* effect2 = Store(AccessAtIndex(0), allocation, object2, finish, ifTrue);
250 Node* merge = Merge2(ifFalse, ifTrue);
251 Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge);
252 Node* load = Load(AccessAtIndex(0), finish, phi, merge);
253 Node* result = Return(load, phi);
254 EndGraph();
255 Analysis();
256
257 ExpectVirtual(allocation);
258 ExpectRepresentationPhi(load, object1, object2);
259 Node* replacement_phi = escape_objects()->representation(load, load->id());
260
261 Transformation();
262
263 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 0));
264 }
265
266
267 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) {
268 Node* object1 = Constant(1);
269 Node* object2 = Constant(2);
270 Node* allocation = Allocate(Constant(8));
271 Node* store1 = Store(AccessAtIndex(0), allocation, object1);
272 Node* load1 = Load(AccessAtIndex(0), allocation);
273 Store(AccessAtIndex(0), allocation, object2);
274 Node* load2 = Load(AccessAtIndex(0), allocation, store1);
275 Node* result = Return(load2);
276 EndGraph();
277
278 Analysis();
279
280 ExpectVirtual(allocation);
281 ExpectRepresentation(load1, object1);
282 ExpectRepresentation(load2, object1);
283
284 Transformation();
285
286 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0));
287 }
288
289 } // namespace compiler
290 } // namespace internal
291 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698