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

Side by Side Diff: test/unittests/interpreter/bytecode-peephole-optimizer-unittest.cc

Issue 1947403002: [interpreter] Introduce bytecode generation pipeline. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 7 months 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 2016 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/factory.h"
8 #include "src/interpreter/bytecode-peephole-optimizer.h"
9 #include "src/interpreter/constant-array-builder.h"
10 #include "src/objects-inl.h"
11 #include "src/objects.h"
12 #include "test/unittests/test-utils.h"
13
14 namespace v8 {
15 namespace internal {
16 namespace interpreter {
17
18 class BytecodePeepholeOptimizerTest : public BytecodePipelineStage,
19 public TestWithIsolateAndZone {
20 public:
21 BytecodePeepholeOptimizerTest()
22 : constant_array_builder_(isolate(), zone()),
23 peephole_optimizer_(&constant_array_builder_, this) {}
24 ~BytecodePeepholeOptimizerTest() override {}
25
26 size_t FlushForOffset() override {
27 flush_for_offset_count_++;
28 return 0;
29 };
30
31 void FlushBasicBlock() override { flush_basic_block_count_++; }
32
33 void Write(BytecodeNode* node) override {
34 write_count_++;
35 last_written_.Clone(node);
36 }
37
38 BytecodePeepholeOptimizer* optimizer() { return &peephole_optimizer_; }
39 ConstantArrayBuilder* constant_array() { return &constant_array_builder_; }
40
41 int flush_for_offset_count() const { return flush_for_offset_count_; }
42 int flush_basic_block_count() const { return flush_basic_block_count_; }
43 int write_count() const { return write_count_; }
44 const BytecodeNode& last_written() const { return last_written_; }
45
46 private:
47 ConstantArrayBuilder constant_array_builder_;
48 BytecodePeepholeOptimizer peephole_optimizer_;
49
50 int flush_for_offset_count_ = 0;
51 int flush_basic_block_count_ = 0;
52 int write_count_ = 0;
53 BytecodeNode last_written_;
54 };
55
56 // Sanity tests.
57
58 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetPassThrough) {
59 CHECK_EQ(flush_for_offset_count(), 0);
60 CHECK_EQ(optimizer()->FlushForOffset(), 0);
61 CHECK_EQ(flush_for_offset_count(), 1);
62 }
63
64 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetRightSize) {
65 BytecodeNode node(Bytecode::kAdd, Register(0).ToOperand(),
66 OperandScale::kQuadruple);
67 optimizer()->Write(&node);
68 CHECK_EQ(optimizer()->FlushForOffset(), node.Size());
69 CHECK_EQ(flush_for_offset_count(), 1);
70 CHECK_EQ(write_count(), 0);
71 }
72
73 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetNop) {
74 BytecodeNode node(Bytecode::kNop);
75 optimizer()->Write(&node);
76 CHECK_EQ(optimizer()->FlushForOffset(), 0);
77 CHECK_EQ(flush_for_offset_count(), 1);
78 CHECK_EQ(write_count(), 0);
79 }
80
81 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetNopExpression) {
82 BytecodeNode node(Bytecode::kNop);
83 node.source_info().Update({3, false});
84 optimizer()->Write(&node);
85 CHECK_EQ(optimizer()->FlushForOffset(), 0);
86 CHECK_EQ(flush_for_offset_count(), 1);
87 CHECK_EQ(write_count(), 0);
88 }
89
90 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetNopStatement) {
91 BytecodeNode node(Bytecode::kNop);
92 node.source_info().Update({3, true});
93 optimizer()->Write(&node);
94 CHECK_EQ(optimizer()->FlushForOffset(), node.Size());
95 CHECK_EQ(flush_for_offset_count(), 1);
96 CHECK_EQ(write_count(), 0);
97 }
98
99 TEST_F(BytecodePeepholeOptimizerTest, FlushBasicBlockPassThrough) {
100 CHECK_EQ(flush_basic_block_count(), 0);
101 optimizer()->FlushBasicBlock();
102 CHECK_EQ(flush_basic_block_count(), 1);
103 CHECK_EQ(write_count(), 0);
104 }
105
106 TEST_F(BytecodePeepholeOptimizerTest, WriteOneFlushBasicBlock) {
107 BytecodeNode node(Bytecode::kAdd, Register(0).ToOperand(),
108 OperandScale::kQuadruple);
109 optimizer()->Write(&node);
110 CHECK_EQ(write_count(), 0);
111 optimizer()->FlushBasicBlock();
112 CHECK_EQ(write_count(), 1);
113 CHECK_EQ(node, last_written());
114 }
115
116 // Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode().
117
118 TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) {
119 BytecodeNode first(Bytecode::kLdaNull);
120 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle);
121 optimizer()->Write(&first);
122 CHECK_EQ(write_count(), 0);
123 optimizer()->Write(&second);
124 CHECK_EQ(write_count(), 1);
125 CHECK_EQ(last_written(), first);
126 optimizer()->FlushBasicBlock();
127 CHECK_EQ(write_count(), 2);
128 CHECK_EQ(last_written(), second);
129 }
130
131 TEST_F(BytecodePeepholeOptimizerTest, ElideJumpIfToBooleanTrue) {
132 BytecodeNode first(Bytecode::kLdaTrue);
133 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle);
134 optimizer()->Write(&first);
135 CHECK_EQ(write_count(), 0);
136 optimizer()->Write(&second);
137 CHECK_EQ(write_count(), 1);
138 CHECK_EQ(last_written(), first);
139 optimizer()->FlushBasicBlock();
140 CHECK_EQ(write_count(), 2);
141 CHECK_EQ(last_written().bytecode(), Bytecode::kJumpIfTrue);
142 CHECK_EQ(last_written().operand(0), second.operand(0));
143 }
144
145 // Tests covering BytecodePeepholeOptimizer::CanElideCurrent().
146
147 TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRy) {
148 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
149 OperandScale::kSingle);
150 BytecodeNode second(Bytecode::kLdar, Register(1).ToOperand(),
151 OperandScale::kSingle);
152 optimizer()->Write(&first);
153 optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
154 CHECK_EQ(write_count(), 0);
155 optimizer()->Write(&second);
156 CHECK_EQ(write_count(), 1);
157 CHECK_EQ(last_written(), first);
158 optimizer()->FlushBasicBlock();
159 CHECK_EQ(write_count(), 2);
160 CHECK_EQ(last_written(), second);
161 }
162
163 TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRx) {
164 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
165 OperandScale::kSingle);
166 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(),
167 OperandScale::kSingle);
168 optimizer()->Write(&first);
169 CHECK_EQ(write_count(), 0);
170 optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
171 optimizer()->Write(&second);
172 CHECK_EQ(write_count(), 1);
173 CHECK_EQ(last_written(), first);
174 optimizer()->FlushBasicBlock();
175 CHECK_EQ(write_count(), 1);
176 }
177
178 TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRxStatement) {
179 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
180 OperandScale::kSingle);
181 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(),
182 OperandScale::kSingle);
183 second.source_info().Update({0, true});
184 optimizer()->Write(&first);
185 CHECK_EQ(write_count(), 0);
186 optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
187 optimizer()->Write(&second);
188 CHECK_EQ(write_count(), 1);
189 CHECK_EQ(last_written(), first);
190 optimizer()->FlushBasicBlock();
191 CHECK_EQ(write_count(), 2);
192 CHECK_EQ(last_written().bytecode(), Bytecode::kNop);
193 CHECK_EQ(last_written().source_info(), second.source_info());
194 }
195
196 TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRxStatementStarRy) {
197 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
198 OperandScale::kSingle);
199 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(),
200 OperandScale::kSingle);
201 BytecodeNode third(Bytecode::kStar, Register(3).ToOperand(),
202 OperandScale::kSingle);
203 second.source_info().Update({0, true});
204 optimizer()->Write(&first);
205 CHECK_EQ(write_count(), 0);
206 optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
207 optimizer()->Write(&second);
208 CHECK_EQ(write_count(), 1);
209 CHECK_EQ(last_written(), first);
210 optimizer()->Write(&third);
211 CHECK_EQ(write_count(), 1);
212 optimizer()->FlushBasicBlock();
213 CHECK_EQ(write_count(), 2);
214 // Source position should move |second| to |third| when |second| is elided.
215 third.source_info().Update(second.source_info());
216 CHECK_EQ(last_written(), third);
217 }
218
219 TEST_F(BytecodePeepholeOptimizerTest, LdarToName) {
220 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
221 OperandScale::kSingle);
222 BytecodeNode second(Bytecode::kToName);
223 optimizer()->Write(&first);
224 CHECK_EQ(write_count(), 0);
225 optimizer()->Write(&second);
226 CHECK_EQ(write_count(), 1);
227 CHECK_EQ(last_written(), first);
228 optimizer()->FlushBasicBlock();
229 CHECK_EQ(write_count(), 2);
230 CHECK_EQ(last_written(), second);
231 }
232
233 TEST_F(BytecodePeepholeOptimizerTest, ToNameToName) {
234 BytecodeNode first(Bytecode::kToName);
235 BytecodeNode second(Bytecode::kToName);
236 optimizer()->Write(&first);
237 CHECK_EQ(write_count(), 0);
238 optimizer()->Write(&second);
239 CHECK_EQ(write_count(), 1);
240 CHECK_EQ(last_written(), first);
241 optimizer()->FlushBasicBlock();
242 CHECK_EQ(write_count(), 1);
243 }
244
245 TEST_F(BytecodePeepholeOptimizerTest, TypeOfToName) {
246 BytecodeNode first(Bytecode::kTypeOf);
247 BytecodeNode second(Bytecode::kToName);
248 optimizer()->Write(&first);
249 CHECK_EQ(write_count(), 0);
250 optimizer()->Write(&second);
251 CHECK_EQ(write_count(), 1);
252 CHECK_EQ(last_written(), first);
253 optimizer()->FlushBasicBlock();
254 CHECK_EQ(write_count(), 1);
255 }
256
257 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) {
258 Handle<Object> word =
259 isolate()->factory()->NewStringFromStaticChars("optimizing");
260 size_t index = constant_array()->Insert(word);
261 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index),
262 OperandScale::kSingle);
263 BytecodeNode second(Bytecode::kToName);
264 optimizer()->Write(&first);
265 CHECK_EQ(write_count(), 0);
266 optimizer()->Write(&second);
267 CHECK_EQ(write_count(), 1);
268 CHECK_EQ(last_written(), first);
269 optimizer()->FlushBasicBlock();
270 CHECK_EQ(write_count(), 1);
271 }
272
273 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantNumberToName) {
274 Handle<Object> word = isolate()->factory()->NewNumber(0.380);
275 size_t index = constant_array()->Insert(word);
276 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index),
277 OperandScale::kSingle);
278 BytecodeNode second(Bytecode::kToName);
279 optimizer()->Write(&first);
280 CHECK_EQ(write_count(), 0);
281 optimizer()->Write(&second);
282 CHECK_EQ(write_count(), 1);
283 CHECK_EQ(last_written(), first);
284 optimizer()->FlushBasicBlock();
285 CHECK_EQ(write_count(), 2);
286 CHECK_EQ(last_written(), second);
287 }
288
289 // Tests covering BytecodePeepholeOptimizer::CanElideLast().
290
291 TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalseNotDiscardable) {
292 BytecodeNode first(Bytecode::kLdaTrue);
293 BytecodeNode second(Bytecode::kLdaFalse);
294 optimizer()->Write(&first);
295 optimizer()->FlushForOffset(); // Prevent discarding of |first|.
296 CHECK_EQ(write_count(), 0);
297 optimizer()->Write(&second);
298 CHECK_EQ(write_count(), 1);
299 CHECK_EQ(last_written(), first);
300 optimizer()->FlushBasicBlock();
301 CHECK_EQ(write_count(), 2);
302 CHECK_EQ(last_written(), second);
303 }
304
305 TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalse) {
306 BytecodeNode first(Bytecode::kLdaTrue);
307 BytecodeNode second(Bytecode::kLdaFalse);
308 optimizer()->Write(&first);
309 CHECK_EQ(write_count(), 0);
310 optimizer()->Write(&second);
311 CHECK_EQ(write_count(), 0);
312 optimizer()->FlushBasicBlock();
313 CHECK_EQ(write_count(), 1);
314 CHECK_EQ(last_written(), second);
315 }
316
317 TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) {
318 BytecodeNode first(Bytecode::kLdaTrue);
319 first.source_info().Update({3, false});
320 BytecodeNode second(Bytecode::kLdaFalse);
321 optimizer()->Write(&first);
322 CHECK_EQ(write_count(), 0);
323 optimizer()->Write(&second);
324 CHECK_EQ(write_count(), 0);
325 optimizer()->FlushBasicBlock();
326 CHECK_EQ(write_count(), 1);
327 second.source_info().Update(first.source_info());
328 CHECK_EQ(last_written(), second);
329 }
330
331 TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) {
332 BytecodeNode first(Bytecode::kNop);
333 BytecodeNode second(Bytecode::kStackCheck);
334 optimizer()->Write(&first);
335 CHECK_EQ(write_count(), 0);
336 optimizer()->Write(&second);
337 CHECK_EQ(write_count(), 0);
338 optimizer()->FlushBasicBlock();
339 CHECK_EQ(write_count(), 1);
340 CHECK_EQ(last_written(), second);
341 }
342
343 TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) {
344 BytecodeNode first(Bytecode::kNop);
345 first.source_info().Update({3, false});
346 BytecodeNode second(Bytecode::kStackCheck);
347 optimizer()->Write(&first);
348 CHECK_EQ(write_count(), 0);
349 optimizer()->Write(&second);
350 CHECK_EQ(write_count(), 0);
351 optimizer()->FlushBasicBlock();
352 CHECK_EQ(write_count(), 1);
353 second.source_info().Update(first.source_info());
354 CHECK_EQ(last_written(), second);
355 }
356
357 } // namespace interpreter
358 } // namespace internal
359 } // namespace v8
OLDNEW
« no previous file with comments | « test/unittests/interpreter/bytecode-array-writer-unittest.cc ('k') | test/unittests/interpreter/bytecode-pipeline-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698