blob: 671bdf88734f66cead3560772186855909975264 [file] [log] [blame]
Ben Murdochc5610432016-08-08 18:44:38 +01001// 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"
Ben Murdoch61f157c2016-09-16 13:49:30 +01008#include "src/interpreter/bytecode-label.h"
Ben Murdochc5610432016-08-08 18:44:38 +01009#include "src/interpreter/bytecode-peephole-optimizer.h"
10#include "src/interpreter/constant-array-builder.h"
11#include "src/objects-inl.h"
12#include "src/objects.h"
13#include "test/unittests/test-utils.h"
14
15namespace v8 {
16namespace internal {
17namespace interpreter {
18
19class BytecodePeepholeOptimizerTest : public BytecodePipelineStage,
20 public TestWithIsolateAndZone {
21 public:
22 BytecodePeepholeOptimizerTest()
23 : constant_array_builder_(isolate(), zone()),
24 peephole_optimizer_(&constant_array_builder_, this) {}
25 ~BytecodePeepholeOptimizerTest() override {}
26
Ben Murdochc5610432016-08-08 18:44:38 +010027 void Write(BytecodeNode* node) override {
28 write_count_++;
29 last_written_.Clone(node);
30 }
31
Ben Murdoch61f157c2016-09-16 13:49:30 +010032 void WriteJump(BytecodeNode* node, BytecodeLabel* label) override {
33 write_count_++;
34 last_written_.Clone(node);
35 }
36
37 void BindLabel(BytecodeLabel* label) override {}
38 void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override {}
39 Handle<BytecodeArray> ToBytecodeArray(
40 int fixed_register_count, int parameter_count,
41 Handle<FixedArray> handle_table) override {
42 return Handle<BytecodeArray>();
43 }
44
45 void Flush() {
46 optimizer()->ToBytecodeArray(0, 0, factory()->empty_fixed_array());
47 }
48
Ben Murdochc5610432016-08-08 18:44:38 +010049 BytecodePeepholeOptimizer* optimizer() { return &peephole_optimizer_; }
50 ConstantArrayBuilder* constant_array() { return &constant_array_builder_; }
51
Ben Murdochc5610432016-08-08 18:44:38 +010052 int write_count() const { return write_count_; }
53 const BytecodeNode& last_written() const { return last_written_; }
54
55 private:
56 ConstantArrayBuilder constant_array_builder_;
57 BytecodePeepholeOptimizer peephole_optimizer_;
58
Ben Murdochc5610432016-08-08 18:44:38 +010059 int write_count_ = 0;
60 BytecodeNode last_written_;
61};
62
63// Sanity tests.
64
Ben Murdoch61f157c2016-09-16 13:49:30 +010065TEST_F(BytecodePeepholeOptimizerTest, FlushOnJump) {
66 CHECK_EQ(write_count(), 0);
67
68 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
69 optimizer()->Write(&add);
70 CHECK_EQ(write_count(), 0);
71
72 BytecodeLabel target;
73 BytecodeNode jump(Bytecode::kJump, 0);
74 optimizer()->WriteJump(&jump, &target);
75 CHECK_EQ(write_count(), 2);
76 CHECK_EQ(jump, last_written());
Ben Murdochc5610432016-08-08 18:44:38 +010077}
78
Ben Murdoch61f157c2016-09-16 13:49:30 +010079TEST_F(BytecodePeepholeOptimizerTest, FlushOnBind) {
Ben Murdochc5610432016-08-08 18:44:38 +010080 CHECK_EQ(write_count(), 0);
Ben Murdochc5610432016-08-08 18:44:38 +010081
Ben Murdoch61f157c2016-09-16 13:49:30 +010082 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
83 optimizer()->Write(&add);
Ben Murdochc5610432016-08-08 18:44:38 +010084 CHECK_EQ(write_count(), 0);
Ben Murdochc5610432016-08-08 18:44:38 +010085
Ben Murdoch61f157c2016-09-16 13:49:30 +010086 BytecodeLabel target;
87 optimizer()->BindLabel(&target);
Ben Murdochc5610432016-08-08 18:44:38 +010088 CHECK_EQ(write_count(), 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +010089 CHECK_EQ(add, last_written());
90}
91
92// Nop elimination tests.
93
94TEST_F(BytecodePeepholeOptimizerTest, ElideEmptyNop) {
95 BytecodeNode nop(Bytecode::kNop);
96 optimizer()->Write(&nop);
97 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
98 optimizer()->Write(&add);
99 Flush();
100 CHECK_EQ(write_count(), 1);
101 CHECK_EQ(add, last_written());
102}
103
104TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) {
105 BytecodeNode nop(Bytecode::kNop);
106 nop.source_info().MakeExpressionPosition(3);
107 optimizer()->Write(&nop);
108 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
109 optimizer()->Write(&add);
110 Flush();
111 CHECK_EQ(write_count(), 1);
112 CHECK_EQ(add, last_written());
113}
114
115TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) {
116 BytecodeNode nop(Bytecode::kNop);
117 nop.source_info().MakeStatementPosition(3);
118 optimizer()->Write(&nop);
119 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
120 add.source_info().MakeExpressionPosition(3);
121 optimizer()->Write(&add);
122 Flush();
123 CHECK_EQ(write_count(), 2);
124 CHECK_EQ(add, last_written());
Ben Murdochc5610432016-08-08 18:44:38 +0100125}
126
127// Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode().
128
129TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) {
130 BytecodeNode first(Bytecode::kLdaNull);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100131 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3);
Ben Murdochc5610432016-08-08 18:44:38 +0100132 optimizer()->Write(&first);
133 CHECK_EQ(write_count(), 0);
134 optimizer()->Write(&second);
135 CHECK_EQ(write_count(), 1);
136 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100137 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100138 CHECK_EQ(write_count(), 2);
139 CHECK_EQ(last_written(), second);
140}
141
142TEST_F(BytecodePeepholeOptimizerTest, ElideJumpIfToBooleanTrue) {
143 BytecodeNode first(Bytecode::kLdaTrue);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100144 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3);
Ben Murdochc5610432016-08-08 18:44:38 +0100145 optimizer()->Write(&first);
146 CHECK_EQ(write_count(), 0);
147 optimizer()->Write(&second);
148 CHECK_EQ(write_count(), 1);
149 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100150 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100151 CHECK_EQ(write_count(), 2);
152 CHECK_EQ(last_written().bytecode(), Bytecode::kJumpIfTrue);
153 CHECK_EQ(last_written().operand(0), second.operand(0));
154}
155
156TEST_F(BytecodePeepholeOptimizerTest, KeepToBooleanLogicalNot) {
157 BytecodeNode first(Bytecode::kLdaNull);
158 BytecodeNode second(Bytecode::kToBooleanLogicalNot);
159 optimizer()->Write(&first);
160 CHECK_EQ(write_count(), 0);
161 optimizer()->Write(&second);
162 CHECK_EQ(write_count(), 1);
163 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100164 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100165 CHECK_EQ(write_count(), 2);
166 CHECK_EQ(last_written(), second);
167}
168
169TEST_F(BytecodePeepholeOptimizerTest, ElideToBooleanLogicalNot) {
170 BytecodeNode first(Bytecode::kLdaTrue);
171 BytecodeNode second(Bytecode::kToBooleanLogicalNot);
172 optimizer()->Write(&first);
173 CHECK_EQ(write_count(), 0);
174 optimizer()->Write(&second);
175 CHECK_EQ(write_count(), 1);
176 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100177 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100178 CHECK_EQ(write_count(), 2);
179 CHECK_EQ(last_written().bytecode(), Bytecode::kLogicalNot);
180}
181
182// Tests covering BytecodePeepholeOptimizer::CanElideCurrent().
183
Ben Murdoch61f157c2016-09-16 13:49:30 +0100184TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRy) {
185 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
186 BytecodeNode second(Bytecode::kLdar, Register(1).ToOperand());
Ben Murdochc5610432016-08-08 18:44:38 +0100187 optimizer()->Write(&first);
Ben Murdochc5610432016-08-08 18:44:38 +0100188 CHECK_EQ(write_count(), 0);
189 optimizer()->Write(&second);
190 CHECK_EQ(write_count(), 1);
191 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100192 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100193 CHECK_EQ(write_count(), 2);
194 CHECK_EQ(last_written(), second);
195}
196
Ben Murdoch61f157c2016-09-16 13:49:30 +0100197TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRx) {
198 BytecodeLabel label;
199 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
200 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand());
Ben Murdochc5610432016-08-08 18:44:38 +0100201 optimizer()->Write(&first);
202 CHECK_EQ(write_count(), 0);
Ben Murdochc5610432016-08-08 18:44:38 +0100203 optimizer()->Write(&second);
204 CHECK_EQ(write_count(), 1);
205 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100206 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100207 CHECK_EQ(write_count(), 1);
208}
209
Ben Murdoch61f157c2016-09-16 13:49:30 +0100210TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatement) {
211 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
212 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand());
213 second.source_info().MakeStatementPosition(0);
Ben Murdochc5610432016-08-08 18:44:38 +0100214 optimizer()->Write(&first);
215 CHECK_EQ(write_count(), 0);
Ben Murdochc5610432016-08-08 18:44:38 +0100216 optimizer()->Write(&second);
217 CHECK_EQ(write_count(), 1);
218 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100219 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100220 CHECK_EQ(write_count(), 2);
221 CHECK_EQ(last_written().bytecode(), Bytecode::kNop);
222 CHECK_EQ(last_written().source_info(), second.source_info());
223}
224
Ben Murdoch61f157c2016-09-16 13:49:30 +0100225TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatementStarRy) {
226 BytecodeLabel label;
227 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
228 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand());
229 BytecodeNode third(Bytecode::kStar, Register(3).ToOperand());
230 second.source_info().MakeStatementPosition(0);
Ben Murdochc5610432016-08-08 18:44:38 +0100231 optimizer()->Write(&first);
232 CHECK_EQ(write_count(), 0);
Ben Murdochc5610432016-08-08 18:44:38 +0100233 optimizer()->Write(&second);
234 CHECK_EQ(write_count(), 1);
235 CHECK_EQ(last_written(), first);
236 optimizer()->Write(&third);
237 CHECK_EQ(write_count(), 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100238 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100239 CHECK_EQ(write_count(), 2);
Ben Murdochc5610432016-08-08 18:44:38 +0100240 CHECK_EQ(last_written(), third);
241}
242
243TEST_F(BytecodePeepholeOptimizerTest, LdarToName) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100244 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand());
Ben Murdochc5610432016-08-08 18:44:38 +0100245 BytecodeNode second(Bytecode::kToName);
246 optimizer()->Write(&first);
247 CHECK_EQ(write_count(), 0);
248 optimizer()->Write(&second);
249 CHECK_EQ(write_count(), 1);
250 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100251 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100252 CHECK_EQ(write_count(), 2);
253 CHECK_EQ(last_written(), second);
254}
255
256TEST_F(BytecodePeepholeOptimizerTest, ToNameToName) {
257 BytecodeNode first(Bytecode::kToName);
258 BytecodeNode second(Bytecode::kToName);
259 optimizer()->Write(&first);
260 CHECK_EQ(write_count(), 0);
261 optimizer()->Write(&second);
262 CHECK_EQ(write_count(), 1);
263 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100264 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100265 CHECK_EQ(write_count(), 1);
266}
267
268TEST_F(BytecodePeepholeOptimizerTest, TypeOfToName) {
269 BytecodeNode first(Bytecode::kTypeOf);
270 BytecodeNode second(Bytecode::kToName);
271 optimizer()->Write(&first);
272 CHECK_EQ(write_count(), 0);
273 optimizer()->Write(&second);
274 CHECK_EQ(write_count(), 1);
275 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100276 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100277 CHECK_EQ(write_count(), 1);
278}
279
280TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) {
281 Handle<Object> word =
282 isolate()->factory()->NewStringFromStaticChars("optimizing");
283 size_t index = constant_array()->Insert(word);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100284 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index));
Ben Murdochc5610432016-08-08 18:44:38 +0100285 BytecodeNode second(Bytecode::kToName);
286 optimizer()->Write(&first);
287 CHECK_EQ(write_count(), 0);
288 optimizer()->Write(&second);
289 CHECK_EQ(write_count(), 1);
290 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100291 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100292 CHECK_EQ(write_count(), 1);
293}
294
295TEST_F(BytecodePeepholeOptimizerTest, LdaConstantNumberToName) {
296 Handle<Object> word = isolate()->factory()->NewNumber(0.380);
297 size_t index = constant_array()->Insert(word);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100298 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index));
Ben Murdochc5610432016-08-08 18:44:38 +0100299 BytecodeNode second(Bytecode::kToName);
300 optimizer()->Write(&first);
301 CHECK_EQ(write_count(), 0);
302 optimizer()->Write(&second);
303 CHECK_EQ(write_count(), 1);
304 CHECK_EQ(last_written(), first);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100305 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100306 CHECK_EQ(write_count(), 2);
307 CHECK_EQ(last_written(), second);
308}
309
310// Tests covering BytecodePeepholeOptimizer::CanElideLast().
311
Ben Murdochc5610432016-08-08 18:44:38 +0100312TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalse) {
313 BytecodeNode first(Bytecode::kLdaTrue);
314 BytecodeNode second(Bytecode::kLdaFalse);
315 optimizer()->Write(&first);
316 CHECK_EQ(write_count(), 0);
317 optimizer()->Write(&second);
318 CHECK_EQ(write_count(), 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100319 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100320 CHECK_EQ(write_count(), 1);
321 CHECK_EQ(last_written(), second);
322}
323
324TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) {
325 BytecodeNode first(Bytecode::kLdaTrue);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100326 first.source_info().MakeExpressionPosition(3);
Ben Murdochc5610432016-08-08 18:44:38 +0100327 BytecodeNode second(Bytecode::kLdaFalse);
328 optimizer()->Write(&first);
329 CHECK_EQ(write_count(), 0);
330 optimizer()->Write(&second);
331 CHECK_EQ(write_count(), 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100332 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100333 CHECK_EQ(write_count(), 1);
Ben Murdochc5610432016-08-08 18:44:38 +0100334 CHECK_EQ(last_written(), second);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100335 CHECK(second.source_info().is_expression());
336 CHECK_EQ(second.source_info().source_position(), 3);
Ben Murdochc5610432016-08-08 18:44:38 +0100337}
338
339TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) {
340 BytecodeNode first(Bytecode::kNop);
341 BytecodeNode second(Bytecode::kStackCheck);
342 optimizer()->Write(&first);
343 CHECK_EQ(write_count(), 0);
344 optimizer()->Write(&second);
345 CHECK_EQ(write_count(), 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100346 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100347 CHECK_EQ(write_count(), 1);
348 CHECK_EQ(last_written(), second);
349}
350
351TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) {
352 BytecodeNode first(Bytecode::kNop);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100353 first.source_info().MakeExpressionPosition(3);
Ben Murdochc5610432016-08-08 18:44:38 +0100354 BytecodeNode second(Bytecode::kStackCheck);
355 optimizer()->Write(&first);
356 CHECK_EQ(write_count(), 0);
357 optimizer()->Write(&second);
358 CHECK_EQ(write_count(), 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100359 Flush();
Ben Murdochc5610432016-08-08 18:44:38 +0100360 CHECK_EQ(write_count(), 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100361 second.source_info().MakeExpressionPosition(
362 first.source_info().source_position());
Ben Murdochc5610432016-08-08 18:44:38 +0100363 CHECK_EQ(last_written(), second);
364}
365
Ben Murdoch61f157c2016-09-16 13:49:30 +0100366// Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes().
367
368TEST_F(BytecodePeepholeOptimizerTest, MergeLoadICStar) {
369 const uint32_t operands[] = {
370 static_cast<uint32_t>(Register(31).ToOperand()), 32, 33,
371 static_cast<uint32_t>(Register(256).ToOperand())};
372 const int expected_operand_count = static_cast<int>(arraysize(operands));
373
374 BytecodeNode first(Bytecode::kLdaNamedProperty, operands[0], operands[1],
375 operands[2]);
376 BytecodeNode second(Bytecode::kStar, operands[3]);
377 BytecodeNode third(Bytecode::kReturn);
378 optimizer()->Write(&first);
379 optimizer()->Write(&second);
380 CHECK_EQ(write_count(), 1);
381 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrNamedProperty);
382 CHECK_EQ(last_written().operand_count(), expected_operand_count);
383 for (int i = 0; i < expected_operand_count; ++i) {
384 CHECK_EQ(last_written().operand(i), operands[i]);
385 }
386 optimizer()->Write(&third);
387 CHECK_EQ(write_count(), 2);
388 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
389 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
390 Flush();
391 CHECK_EQ(last_written().bytecode(), third.bytecode());
392}
393
394TEST_F(BytecodePeepholeOptimizerTest, MergeLdaKeyedPropertyStar) {
395 const uint32_t operands[] = {static_cast<uint32_t>(Register(31).ToOperand()),
396 9999997,
397 static_cast<uint32_t>(Register(1).ToOperand())};
398 const int expected_operand_count = static_cast<int>(arraysize(operands));
399
400 BytecodeNode first(Bytecode::kLdaKeyedProperty, operands[0], operands[1]);
401 BytecodeNode second(Bytecode::kStar, operands[2]);
402 BytecodeNode third(Bytecode::kReturn);
403 optimizer()->Write(&first);
404 optimizer()->Write(&second);
405 CHECK_EQ(write_count(), 1);
406 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrKeyedProperty);
407 CHECK_EQ(last_written().operand_count(), expected_operand_count);
408 for (int i = 0; i < expected_operand_count; ++i) {
409 CHECK_EQ(last_written().operand(i), operands[i]);
410 }
411 optimizer()->Write(&third);
412 CHECK_EQ(write_count(), 2);
413 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
414 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
415 Flush();
416 CHECK_EQ(last_written().bytecode(), third.bytecode());
417}
418
419TEST_F(BytecodePeepholeOptimizerTest, MergeLdaGlobalStar) {
420 const uint32_t operands[] = {19191,
421 static_cast<uint32_t>(Register(1).ToOperand())};
422 const int expected_operand_count = static_cast<int>(arraysize(operands));
423
424 BytecodeNode first(Bytecode::kLdaGlobal, operands[0]);
425 BytecodeNode second(Bytecode::kStar, operands[1]);
426 BytecodeNode third(Bytecode::kReturn);
427 optimizer()->Write(&first);
428 optimizer()->Write(&second);
429 CHECK_EQ(write_count(), 1);
430 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrGlobal);
431 CHECK_EQ(last_written().operand_count(), expected_operand_count);
432 for (int i = 0; i < expected_operand_count; ++i) {
433 CHECK_EQ(last_written().operand(i), operands[i]);
434 }
435 optimizer()->Write(&third);
436 CHECK_EQ(write_count(), 2);
437 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
438 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
439 Flush();
440 CHECK_EQ(last_written().bytecode(), third.bytecode());
441}
442
443TEST_F(BytecodePeepholeOptimizerTest, MergeLdaContextSlotStar) {
444 const uint32_t operands[] = {
445 static_cast<uint32_t>(Register(200000).ToOperand()), 55005500,
446 static_cast<uint32_t>(Register(1).ToOperand())};
447 const int expected_operand_count = static_cast<int>(arraysize(operands));
448
449 BytecodeNode first(Bytecode::kLdaContextSlot, operands[0], operands[1]);
450 BytecodeNode second(Bytecode::kStar, operands[2]);
451 BytecodeNode third(Bytecode::kReturn);
452 optimizer()->Write(&first);
453 optimizer()->Write(&second);
454 CHECK_EQ(write_count(), 1);
455 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrContextSlot);
456 CHECK_EQ(last_written().operand_count(), expected_operand_count);
457 for (int i = 0; i < expected_operand_count; ++i) {
458 CHECK_EQ(last_written().operand(i), operands[i]);
459 }
460 optimizer()->Write(&third);
461 CHECK_EQ(write_count(), 2);
462 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
463 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
464 Flush();
465 CHECK_EQ(last_written().bytecode(), third.bytecode());
466}
467
468TEST_F(BytecodePeepholeOptimizerTest, MergeLdaUndefinedStar) {
469 const uint32_t operands[] = {
470 static_cast<uint32_t>(Register(100000).ToOperand())};
471 const int expected_operand_count = static_cast<int>(arraysize(operands));
472
473 BytecodeNode first(Bytecode::kLdaUndefined);
474 BytecodeNode second(Bytecode::kStar, operands[0]);
475 BytecodeNode third(Bytecode::kReturn);
476 optimizer()->Write(&first);
477 optimizer()->Write(&second);
478 CHECK_EQ(write_count(), 1);
479 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrUndefined);
480 CHECK_EQ(last_written().operand_count(), expected_operand_count);
481 for (int i = 0; i < expected_operand_count; ++i) {
482 CHECK_EQ(last_written().operand(i), operands[i]);
483 }
484 optimizer()->Write(&third);
485 CHECK_EQ(write_count(), 2);
486 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
487 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
488 Flush();
489 CHECK_EQ(last_written().bytecode(), third.bytecode());
490}
491
Ben Murdochc5610432016-08-08 18:44:38 +0100492} // namespace interpreter
493} // namespace internal
494} // namespace v8