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

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: Rebase 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
« no previous file with comments | « test/mjsunit/mjsunit.status ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/js-graph.h"
10 #include "src/compiler/node-properties.h"
11 #include "src/compiler/simplified-operator.h"
12 #include "src/types-inl.h"
13 #include "src/zone-containers.h"
14 #include "test/unittests/compiler/graph-unittest.h"
15
16 namespace v8 {
17 namespace internal {
18 namespace compiler {
19
20 class EscapeAnalysisTest : public GraphTest {
21 public:
22 EscapeAnalysisTest()
23 : simplified_(zone()),
24 jsgraph_(isolate(), graph(), common(), nullptr, nullptr, nullptr),
25 escape_objects_(graph(), common(), zone()),
26 escape_status_(&escape_objects_, graph(), zone()),
27 effect_(graph()->start()),
28 control_(graph()->start()) {}
29
30 ~EscapeAnalysisTest() {}
31
32 EscapeStatusAnalysis* escape_status() { return &escape_status_; }
33 EscapeObjectAnalysis* escape_objects() { return &escape_objects_; }
34
35 protected:
36 void Analysis() {
37 escape_objects_.Run();
38 escape_status_.Run();
39 }
40
41 void Transformation() {
42 GraphReducer graph_reducer(zone(), graph());
43 EscapeAnalysisReducer escape_reducer(
44 &graph_reducer, &jsgraph_, &escape_status_, &escape_objects_, zone());
45 graph_reducer.AddReducer(&escape_reducer);
46 graph_reducer.ReduceGraph();
47 }
48
49 // ---------------------------------Node Creation Helper----------------------
50
51 Node* BeginRegion(Node* effect = nullptr) {
52 if (!effect) {
53 effect = effect_;
54 }
55
56 return effect_ = graph()->NewNode(common()->BeginRegion(), effect);
57 }
58
59 Node* FinishRegion(Node* value, Node* effect = nullptr) {
60 if (!effect) {
61 effect = effect_;
62 }
63 return effect_ = graph()->NewNode(common()->FinishRegion(), value, effect);
64 }
65
66 Node* Allocate(Node* size, Node* effect = nullptr, Node* control = nullptr) {
67 if (!effect) {
68 effect = effect_;
69 }
70 if (!control) {
71 control = control_;
72 }
73 return effect_ = graph()->NewNode(simplified()->Allocate(), size, effect,
74 control);
75 }
76
77 Node* Constant(int num) {
78 return graph()->NewNode(common()->NumberConstant(num));
79 }
80
81 Node* Store(const FieldAccess& access, Node* allocation, Node* value,
82 Node* effect = nullptr, Node* control = nullptr) {
83 if (!effect) {
84 effect = effect_;
85 }
86 if (!control) {
87 control = control_;
88 }
89 return effect_ = graph()->NewNode(simplified()->StoreField(access),
90 allocation, value, effect, control);
91 }
92
93 Node* Load(const FieldAccess& access, Node* from, Node* effect = nullptr,
94 Node* control = nullptr) {
95 if (!effect) {
96 effect = effect_;
97 }
98 if (!control) {
99 control = control_;
100 }
101 return graph()->NewNode(simplified()->LoadField(access), from, effect,
102 control);
103 }
104
105 Node* Return(Node* value, Node* effect = nullptr, Node* control = nullptr) {
106 if (!effect) {
107 effect = effect_;
108 }
109 if (!control) {
110 control = control_;
111 }
112 return control_ =
113 graph()->NewNode(common()->Return(), value, effect, control);
114 }
115
116 void EndGraph() {
117 for (Edge edge : graph()->end()->input_edges()) {
118 if (NodeProperties::IsControlEdge(edge)) {
119 edge.UpdateTo(control_);
120 }
121 }
122 }
123
124 Node* Branch() {
125 return control_ =
126 graph()->NewNode(common()->Branch(), Constant(0), control_);
127 }
128
129 Node* IfTrue() {
130 return control_ = graph()->NewNode(common()->IfTrue(), control_);
131 }
132
133 Node* IfFalse() { return graph()->NewNode(common()->IfFalse(), control_); }
134
135 Node* Merge2(Node* control1, Node* control2) {
136 return control_ = graph()->NewNode(common()->Merge(2), control1, control2);
137 }
138
139 FieldAccess AccessAtIndex(int offset) {
140 FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(),
141 kMachAnyTagged};
142 return access;
143 }
144
145 // ---------------------------------Assertion Helper--------------------------
146
147 void ExpectReplacement(Node* node, Node* rep) {
148 EXPECT_EQ(rep, escape_objects()->GetReplacement(node, node->id()));
149 }
150
151 void ExpectReplacementPhi(Node* node, Node* left, Node* right) {
152 Node* rep = escape_objects()->GetReplacement(node, node->id());
153 ASSERT_NE(nullptr, rep);
154 ASSERT_EQ(IrOpcode::kPhi, rep->opcode());
155 EXPECT_EQ(left, NodeProperties::GetValueInput(rep, 0));
156 EXPECT_EQ(right, NodeProperties::GetValueInput(rep, 1));
157 }
158
159 void ExpectVirtual(Node* node) {
160 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate ||
161 node->opcode() == IrOpcode::kFinishRegion);
162 EXPECT_TRUE(escape_status()->IsVirtual(node));
163 }
164
165 void ExpectEscaped(Node* node) {
166 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate ||
167 node->opcode() == IrOpcode::kFinishRegion);
168 EXPECT_TRUE(escape_status()->IsEscaped(node));
169 }
170
171 SimplifiedOperatorBuilder* simplified() { return &simplified_; }
172
173 Node* effect() { return effect_; }
174
175 private:
176 SimplifiedOperatorBuilder simplified_;
177 JSGraph jsgraph_;
178 EscapeObjectAnalysis escape_objects_;
179 EscapeStatusAnalysis escape_status_;
180
181 Node* effect_;
182 Node* control_;
183 };
184
185
186 // -----------------------------------------------------------------------------
187 // Test cases.
188
189
190 TEST_F(EscapeAnalysisTest, StraightNonEscape) {
191 Node* object1 = Constant(1);
192 BeginRegion();
193 Node* allocation = Allocate(Constant(kPointerSize));
194 Store(AccessAtIndex(0), allocation, object1);
195 Node* finish = FinishRegion(allocation);
196 Node* load = Load(AccessAtIndex(0), finish);
197 Node* result = Return(load);
198 EndGraph();
199 Analysis();
200
201 ExpectVirtual(allocation);
202 ExpectReplacement(load, object1);
203
204 Transformation();
205
206 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0));
207 }
208
209
210 TEST_F(EscapeAnalysisTest, StraightEscape) {
211 Node* object1 = Constant(1);
212 BeginRegion();
213 Node* allocation = Allocate(Constant(kPointerSize));
214 Store(AccessAtIndex(0), allocation, object1);
215 Node* finish = FinishRegion(allocation);
216 Node* load = Load(AccessAtIndex(0), finish);
217 Node* result = Return(allocation);
218 EndGraph();
219 Analysis();
220
221 ExpectEscaped(allocation);
222 ExpectReplacement(load, object1);
223
224 Transformation();
225
226 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0));
227 }
228
229
230 TEST_F(EscapeAnalysisTest, StoreLoadEscape) {
231 Node* object1 = Constant(1);
232
233 BeginRegion();
234 Node* allocation1 = Allocate(Constant(kPointerSize));
235 Store(AccessAtIndex(0), allocation1, object1);
236 Node* finish1 = FinishRegion(allocation1);
237
238 BeginRegion();
239 Node* allocation2 = Allocate(Constant(kPointerSize));
240 Store(AccessAtIndex(0), allocation2, finish1);
241 Node* finish2 = FinishRegion(allocation2);
242
243 Node* load = Load(AccessAtIndex(0), finish2);
244 Node* result = Return(load);
245 EndGraph();
246 Analysis();
247
248 ExpectEscaped(allocation1);
249 ExpectVirtual(allocation2);
250 ExpectReplacement(load, finish1);
251
252 Transformation();
253
254 ASSERT_EQ(finish1, NodeProperties::GetValueInput(result, 0));
255 }
256
257
258 TEST_F(EscapeAnalysisTest, BranchNonEscape) {
259 Node* object1 = Constant(1);
260 Node* object2 = Constant(2);
261 BeginRegion();
262 Node* allocation = Allocate(Constant(kPointerSize));
263 Store(AccessAtIndex(0), allocation, object1);
264 Node* finish = FinishRegion(allocation);
265 Branch();
266 Node* ifFalse = IfFalse();
267 Node* ifTrue = IfTrue();
268 Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish, ifFalse);
269 Node* effect2 = Store(AccessAtIndex(0), allocation, object2, finish, ifTrue);
270 Node* merge = Merge2(ifFalse, ifTrue);
271 Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge);
272 Node* load = Load(AccessAtIndex(0), finish, phi, merge);
273 Node* result = Return(load, phi);
274 EndGraph();
275 Analysis();
276
277 ExpectVirtual(allocation);
278 ExpectReplacementPhi(load, object1, object2);
279 Node* replacement_phi = escape_objects()->GetReplacement(load, load->id());
280
281 Transformation();
282
283 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 0));
284 }
285
286
287 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) {
288 Node* object1 = Constant(1);
289 Node* object2 = Constant(2);
290 Node* allocation = Allocate(Constant(kPointerSize));
291 Node* store1 = Store(AccessAtIndex(0), allocation, object1);
292 Node* load1 = Load(AccessAtIndex(0), allocation);
293 Store(AccessAtIndex(0), allocation, object2);
294 Node* load2 = Load(AccessAtIndex(0), allocation, store1);
295 Node* result = Return(load2);
296 EndGraph();
297
298 Analysis();
299
300 ExpectVirtual(allocation);
301 ExpectReplacement(load1, object1);
302 ExpectReplacement(load2, object1);
303
304 Transformation();
305
306 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0));
307 }
308
309 } // namespace compiler
310 } // namespace internal
311 } // namespace v8
OLDNEW
« no previous file with comments | « test/mjsunit/mjsunit.status ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698