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

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

Issue 2523893003: Reland of [ignition/turbo] Perform liveness analysis on the bytecodes (Closed)
Patch Set: Export handler table for tests Created 4 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/unittests/BUILD.gn ('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/v8.h"
6
7 #include "src/compiler/bytecode-analysis.h"
8 #include "src/interpreter/bytecode-array-builder.h"
9 #include "src/interpreter/bytecode-array-iterator.h"
10 #include "src/interpreter/bytecode-decoder.h"
11 #include "src/interpreter/bytecode-label.h"
12 #include "src/interpreter/control-flow-builders.h"
13 #include "test/unittests/test-utils.h"
14
15 namespace v8 {
16 namespace internal {
17 namespace compiler {
18
19 class BytecodeAnalysisTest : public TestWithIsolateAndZone {
20 public:
21 BytecodeAnalysisTest() {}
22 ~BytecodeAnalysisTest() override {}
23
24 static void SetUpTestCase() {
25 old_FLAG_ignition_peephole_ = i::FLAG_ignition_peephole;
26 i::FLAG_ignition_peephole = false;
27
28 old_FLAG_ignition_reo_ = i::FLAG_ignition_reo;
29 i::FLAG_ignition_reo = false;
30
31 TestWithIsolateAndZone::SetUpTestCase();
32 }
33
34 static void TearDownTestCase() {
35 TestWithIsolateAndZone::TearDownTestCase();
36 i::FLAG_ignition_peephole = old_FLAG_ignition_peephole_;
37 i::FLAG_ignition_reo = old_FLAG_ignition_reo_;
38 }
39
40 std::string ToLivenessString(const BitVector* liveness) const {
41 std::string out;
42 out.resize(liveness->length());
43 for (int i = 0; i < liveness->length(); ++i) {
44 if (liveness->Contains(i)) {
45 out[i] = 'L';
46 } else {
47 out[i] = '.';
48 }
49 }
50 return out;
51 }
52
53 void EnsureLivenessMatches(
54 Handle<BytecodeArray> bytecode,
55 const std::vector<std::pair<std::string, std::string>>&
56 expected_liveness) {
57 BytecodeAnalysis analysis(bytecode, zone(), true);
58 analysis.Analyze();
59
60 interpreter::BytecodeArrayIterator iterator(bytecode);
61 for (auto liveness : expected_liveness) {
62 std::stringstream ss;
63 ss << std::setw(4) << iterator.current_offset() << " : ";
64 iterator.PrintTo(ss);
65
66 EXPECT_EQ(liveness.first, ToLivenessString(analysis.GetInLivenessFor(
67 iterator.current_offset())))
68 << " at bytecode " << ss.str();
69
70 EXPECT_EQ(liveness.second, ToLivenessString(analysis.GetOutLivenessFor(
71 iterator.current_offset())))
72 << " at bytecode " << ss.str();
73
74 iterator.Advance();
75 }
76
77 EXPECT_TRUE(iterator.done());
78 }
79
80 private:
81 static bool old_FLAG_ignition_peephole_;
82 static bool old_FLAG_ignition_reo_;
83
84 DISALLOW_COPY_AND_ASSIGN(BytecodeAnalysisTest);
85 };
86
87 bool BytecodeAnalysisTest::old_FLAG_ignition_peephole_;
88 bool BytecodeAnalysisTest::old_FLAG_ignition_reo_;
89
90 TEST_F(BytecodeAnalysisTest, EmptyBlock) {
91 interpreter::BytecodeArrayBuilder builder(isolate(), zone(), 3, 0, 3);
92 std::vector<std::pair<std::string, std::string>> expected_liveness;
93
94 interpreter::Register reg_0(0);
95
96 builder.Return();
97 expected_liveness.emplace_back("...L", "....");
98
99 Handle<BytecodeArray> bytecode = builder.ToBytecodeArray(isolate());
100
101 EnsureLivenessMatches(bytecode, expected_liveness);
102 }
103
104 TEST_F(BytecodeAnalysisTest, SimpleLoad) {
105 interpreter::BytecodeArrayBuilder builder(isolate(), zone(), 3, 0, 3);
106 std::vector<std::pair<std::string, std::string>> expected_liveness;
107
108 interpreter::Register reg_0(0);
109
110 builder.LoadAccumulatorWithRegister(reg_0);
111 expected_liveness.emplace_back("L...", "...L");
112
113 builder.Return();
114 expected_liveness.emplace_back("...L", "....");
115
116 Handle<BytecodeArray> bytecode = builder.ToBytecodeArray(isolate());
117
118 EnsureLivenessMatches(bytecode, expected_liveness);
119 }
120
121 TEST_F(BytecodeAnalysisTest, StoreThenLoad) {
122 interpreter::BytecodeArrayBuilder builder(isolate(), zone(), 3, 0, 3);
123 std::vector<std::pair<std::string, std::string>> expected_liveness;
124
125 interpreter::Register reg_0(0);
126
127 builder.StoreAccumulatorInRegister(reg_0);
128 expected_liveness.emplace_back("...L", "L...");
129
130 builder.LoadNull();
131 expected_liveness.emplace_back("L...", "L...");
132
133 builder.LoadAccumulatorWithRegister(reg_0);
134 expected_liveness.emplace_back("L...", "...L");
135
136 builder.Return();
137 expected_liveness.emplace_back("...L", "....");
138
139 Handle<BytecodeArray> bytecode = builder.ToBytecodeArray(isolate());
140
141 EnsureLivenessMatches(bytecode, expected_liveness);
142 }
143
144 TEST_F(BytecodeAnalysisTest, DiamondLoad) {
145 interpreter::BytecodeArrayBuilder builder(isolate(), zone(), 3, 0, 3);
146 std::vector<std::pair<std::string, std::string>> expected_liveness;
147
148 interpreter::Register reg_0(0);
149 interpreter::Register reg_1(1);
150 interpreter::Register reg_2(2);
151
152 interpreter::BytecodeLabel ld1_label;
153 interpreter::BytecodeLabel end_label;
154
155 builder.JumpIfTrue(&ld1_label);
156 expected_liveness.emplace_back("LLLL", "LLL.");
157
158 builder.LoadAccumulatorWithRegister(reg_0);
159 expected_liveness.emplace_back("L.L.", "..L.");
160
161 builder.Jump(&end_label);
162 expected_liveness.emplace_back("..L.", "..L.");
163
164 builder.Bind(&ld1_label);
165 builder.LoadAccumulatorWithRegister(reg_1);
166 expected_liveness.emplace_back(".LL.", "..L.");
167
168 builder.Bind(&end_label);
169
170 builder.LoadAccumulatorWithRegister(reg_2);
171 expected_liveness.emplace_back("..L.", "...L");
172
173 builder.Return();
174 expected_liveness.emplace_back("...L", "....");
175
176 Handle<BytecodeArray> bytecode = builder.ToBytecodeArray(isolate());
177
178 EnsureLivenessMatches(bytecode, expected_liveness);
179 }
180
181 TEST_F(BytecodeAnalysisTest, DiamondLookupsAndBinds) {
182 interpreter::BytecodeArrayBuilder builder(isolate(), zone(), 3, 0, 3);
183 std::vector<std::pair<std::string, std::string>> expected_liveness;
184
185 interpreter::Register reg_0(0);
186 interpreter::Register reg_1(1);
187 interpreter::Register reg_2(2);
188
189 interpreter::BytecodeLabel ld1_label;
190 interpreter::BytecodeLabel end_label;
191
192 builder.StoreAccumulatorInRegister(reg_0);
193 expected_liveness.emplace_back(".LLL", "LLLL");
194
195 builder.JumpIfTrue(&ld1_label);
196 expected_liveness.emplace_back("LLLL", "LLL.");
197
198 {
199 builder.LoadAccumulatorWithRegister(reg_0);
200 expected_liveness.emplace_back("L...", "...L");
201
202 builder.StoreAccumulatorInRegister(reg_2);
203 expected_liveness.emplace_back("...L", "..L.");
204
205 builder.Jump(&end_label);
206 expected_liveness.emplace_back("..L.", "..L.");
207 }
208
209 builder.Bind(&ld1_label);
210 {
211 builder.LoadAccumulatorWithRegister(reg_1);
212 expected_liveness.emplace_back(".LL.", "..L.");
213 }
214
215 builder.Bind(&end_label);
216
217 builder.LoadAccumulatorWithRegister(reg_2);
218 expected_liveness.emplace_back("..L.", "...L");
219
220 builder.Return();
221 expected_liveness.emplace_back("...L", "....");
222
223 Handle<BytecodeArray> bytecode = builder.ToBytecodeArray(isolate());
224
225 EnsureLivenessMatches(bytecode, expected_liveness);
226 }
227
228 TEST_F(BytecodeAnalysisTest, SimpleLoop) {
229 interpreter::BytecodeArrayBuilder builder(isolate(), zone(), 3, 0, 3);
230 std::vector<std::pair<std::string, std::string>> expected_liveness;
231
232 interpreter::Register reg_0(0);
233 interpreter::Register reg_1(1);
234 interpreter::Register reg_2(2);
235
236 builder.StoreAccumulatorInRegister(reg_0);
237 expected_liveness.emplace_back("..LL", "L.LL");
238
239 interpreter::LoopBuilder loop_builder(&builder);
240 loop_builder.LoopHeader();
241 {
242 builder.JumpIfTrue(loop_builder.break_labels()->New());
243 expected_liveness.emplace_back("L.LL", "L.L.");
244
245 builder.LoadAccumulatorWithRegister(reg_0);
246 expected_liveness.emplace_back("L...", "L..L");
247
248 builder.StoreAccumulatorInRegister(reg_2);
249 expected_liveness.emplace_back("L..L", "L.LL");
250
251 loop_builder.BindContinueTarget();
252 loop_builder.JumpToHeader(0);
253 expected_liveness.emplace_back("L.LL", "L.LL");
254 }
255 loop_builder.EndLoop();
256
257 builder.LoadAccumulatorWithRegister(reg_2);
258 expected_liveness.emplace_back("..L.", "...L");
259
260 builder.Return();
261 expected_liveness.emplace_back("...L", "....");
262
263 Handle<BytecodeArray> bytecode = builder.ToBytecodeArray(isolate());
264
265 EnsureLivenessMatches(bytecode, expected_liveness);
266 }
267
268 TEST_F(BytecodeAnalysisTest, TryCatch) {
269 interpreter::BytecodeArrayBuilder builder(isolate(), zone(), 3, 0, 3);
270 std::vector<std::pair<std::string, std::string>> expected_liveness;
271
272 interpreter::Register reg_0(0);
273 interpreter::Register reg_1(1);
274 interpreter::Register reg_context(2);
275
276 builder.StoreAccumulatorInRegister(reg_0);
277 expected_liveness.emplace_back(".LLL", "LLL.");
278
279 interpreter::TryCatchBuilder try_builder(&builder, HandlerTable::CAUGHT);
280 try_builder.BeginTry(reg_context);
281 {
282 builder.LoadAccumulatorWithRegister(reg_0);
283 expected_liveness.emplace_back("LLL.", ".LLL");
284
285 builder.StoreAccumulatorInRegister(reg_0);
286 expected_liveness.emplace_back(".LLL", ".LL.");
287
288 builder.CallRuntime(Runtime::kThrow);
289 expected_liveness.emplace_back(".LL.", ".LLL");
290
291 builder.StoreAccumulatorInRegister(reg_0);
292 // Star can't throw, so doesn't take handler liveness
293 expected_liveness.emplace_back("...L", "...L");
294 }
295 try_builder.EndTry();
296 expected_liveness.emplace_back("...L", "...L");
297
298 // Catch
299 {
300 builder.LoadAccumulatorWithRegister(reg_1);
301 expected_liveness.emplace_back(".L..", "...L");
302 }
303 try_builder.EndCatch();
304
305 builder.Return();
306 expected_liveness.emplace_back("...L", "....");
307
308 Handle<BytecodeArray> bytecode = builder.ToBytecodeArray(isolate());
309
310 EnsureLivenessMatches(bytecode, expected_liveness);
311 }
312
313 TEST_F(BytecodeAnalysisTest, DiamondInLoop) {
314 interpreter::BytecodeArrayBuilder builder(isolate(), zone(), 3, 0, 3);
315 std::vector<std::pair<std::string, std::string>> expected_liveness;
316
317 interpreter::Register reg_0(0);
318 interpreter::Register reg_1(1);
319 interpreter::Register reg_2(2);
320
321 builder.StoreAccumulatorInRegister(reg_0);
322 expected_liveness.emplace_back("...L", "L..L");
323
324 interpreter::LoopBuilder loop_builder(&builder);
325 loop_builder.LoopHeader();
326 {
327 builder.JumpIfTrue(loop_builder.break_labels()->New());
328 expected_liveness.emplace_back("L..L", "L..L");
329
330 interpreter::BytecodeLabel ld1_label;
331 interpreter::BytecodeLabel end_label;
332 builder.JumpIfTrue(&ld1_label);
333 expected_liveness.emplace_back("L..L", "L..L");
334
335 {
336 builder.Jump(&end_label);
337 expected_liveness.emplace_back("L..L", "L..L");
338 }
339
340 builder.Bind(&ld1_label);
341 {
342 builder.LoadAccumulatorWithRegister(reg_0);
343 expected_liveness.emplace_back("L...", "L..L");
344 }
345
346 builder.Bind(&end_label);
347
348 loop_builder.BindContinueTarget();
349 loop_builder.JumpToHeader(0);
350 expected_liveness.emplace_back("L..L", "L..L");
351 }
352 loop_builder.EndLoop();
353
354 builder.Return();
355 expected_liveness.emplace_back("...L", "....");
356
357 Handle<BytecodeArray> bytecode = builder.ToBytecodeArray(isolate());
358
359 EnsureLivenessMatches(bytecode, expected_liveness);
360 }
361
362 TEST_F(BytecodeAnalysisTest, KillingLoopInsideLoop) {
363 interpreter::BytecodeArrayBuilder builder(isolate(), zone(), 3, 0, 3);
364 std::vector<std::pair<std::string, std::string>> expected_liveness;
365
366 interpreter::Register reg_0(0);
367 interpreter::Register reg_1(1);
368
369 builder.StoreAccumulatorInRegister(reg_0);
370 expected_liveness.emplace_back(".L.L", "LL..");
371
372 interpreter::LoopBuilder loop_builder(&builder);
373 loop_builder.LoopHeader();
374 {
375 builder.LoadAccumulatorWithRegister(reg_0);
376 expected_liveness.emplace_back("LL..", ".L..");
377
378 builder.LoadAccumulatorWithRegister(reg_1);
379 expected_liveness.emplace_back(".L..", ".L.L");
380
381 builder.JumpIfTrue(loop_builder.break_labels()->New());
382 expected_liveness.emplace_back(".L.L", ".L.L");
383
384 interpreter::LoopBuilder inner_loop_builder(&builder);
385 inner_loop_builder.LoopHeader();
386 {
387 builder.StoreAccumulatorInRegister(reg_0);
388 expected_liveness.emplace_back(".L.L", "LL.L");
389
390 builder.JumpIfTrue(inner_loop_builder.break_labels()->New());
391 expected_liveness.emplace_back("LL.L", "LL.L");
392
393 inner_loop_builder.BindContinueTarget();
394 inner_loop_builder.JumpToHeader(1);
395 expected_liveness.emplace_back(".L.L", ".L.L");
396 }
397 inner_loop_builder.EndLoop();
398
399 loop_builder.BindContinueTarget();
400 loop_builder.JumpToHeader(0);
401 expected_liveness.emplace_back("LL..", "LL..");
402 }
403 loop_builder.EndLoop();
404
405 builder.Return();
406 expected_liveness.emplace_back("...L", "....");
407
408 Handle<BytecodeArray> bytecode = builder.ToBytecodeArray(isolate());
409
410 EnsureLivenessMatches(bytecode, expected_liveness);
411 }
412
413 } // namespace compiler
414 } // namespace internal
415 } // namespace v8
OLDNEW
« no previous file with comments | « test/unittests/BUILD.gn ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698