OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/factory.h" | 7 #include "src/factory.h" |
8 #include "src/interpreter/bytecode-label.h" | 8 #include "src/interpreter/bytecode-label.h" |
9 #include "src/interpreter/bytecode-peephole-optimizer.h" | 9 #include "src/interpreter/bytecode-peephole-optimizer.h" |
10 #include "src/interpreter/constant-array-builder.h" | 10 #include "src/interpreter/constant-array-builder.h" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 | 63 |
64 int write_count_ = 0; | 64 int write_count_ = 0; |
65 BytecodeNode last_written_; | 65 BytecodeNode last_written_; |
66 }; | 66 }; |
67 | 67 |
68 // Sanity tests. | 68 // Sanity tests. |
69 | 69 |
70 TEST_F(BytecodePeepholeOptimizerTest, FlushOnJump) { | 70 TEST_F(BytecodePeepholeOptimizerTest, FlushOnJump) { |
71 CHECK_EQ(write_count(), 0); | 71 CHECK_EQ(write_count(), 0); |
72 | 72 |
73 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); | 73 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), 1); |
74 optimizer()->Write(&add); | 74 optimizer()->Write(&add); |
75 CHECK_EQ(write_count(), 0); | 75 CHECK_EQ(write_count(), 0); |
76 | 76 |
77 BytecodeLabel target; | 77 BytecodeLabel target; |
78 BytecodeNode jump(Bytecode::kJump, 0); | 78 BytecodeNode jump(Bytecode::kJump, 0); |
79 optimizer()->WriteJump(&jump, &target); | 79 optimizer()->WriteJump(&jump, &target); |
80 CHECK_EQ(write_count(), 2); | 80 CHECK_EQ(write_count(), 2); |
81 CHECK_EQ(jump, last_written()); | 81 CHECK_EQ(jump, last_written()); |
82 } | 82 } |
83 | 83 |
84 TEST_F(BytecodePeepholeOptimizerTest, FlushOnBind) { | 84 TEST_F(BytecodePeepholeOptimizerTest, FlushOnBind) { |
85 CHECK_EQ(write_count(), 0); | 85 CHECK_EQ(write_count(), 0); |
86 | 86 |
87 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); | 87 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), 1); |
88 optimizer()->Write(&add); | 88 optimizer()->Write(&add); |
89 CHECK_EQ(write_count(), 0); | 89 CHECK_EQ(write_count(), 0); |
90 | 90 |
91 BytecodeLabel target; | 91 BytecodeLabel target; |
92 optimizer()->BindLabel(&target); | 92 optimizer()->BindLabel(&target); |
93 CHECK_EQ(write_count(), 1); | 93 CHECK_EQ(write_count(), 1); |
94 CHECK_EQ(add, last_written()); | 94 CHECK_EQ(add, last_written()); |
95 } | 95 } |
96 | 96 |
97 // Nop elimination tests. | 97 // Nop elimination tests. |
98 | 98 |
99 TEST_F(BytecodePeepholeOptimizerTest, ElideEmptyNop) { | 99 TEST_F(BytecodePeepholeOptimizerTest, ElideEmptyNop) { |
100 BytecodeNode nop(Bytecode::kNop); | 100 BytecodeNode nop(Bytecode::kNop); |
101 optimizer()->Write(&nop); | 101 optimizer()->Write(&nop); |
102 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); | 102 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), 1); |
103 optimizer()->Write(&add); | 103 optimizer()->Write(&add); |
104 Flush(); | 104 Flush(); |
105 CHECK_EQ(write_count(), 1); | 105 CHECK_EQ(write_count(), 1); |
106 CHECK_EQ(add, last_written()); | 106 CHECK_EQ(add, last_written()); |
107 } | 107 } |
108 | 108 |
109 TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) { | 109 TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) { |
110 BytecodeNode nop(Bytecode::kNop); | 110 BytecodeNode nop(Bytecode::kNop); |
111 nop.source_info().MakeExpressionPosition(3); | 111 nop.source_info().MakeExpressionPosition(3); |
112 optimizer()->Write(&nop); | 112 optimizer()->Write(&nop); |
113 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); | 113 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), 1); |
114 optimizer()->Write(&add); | 114 optimizer()->Write(&add); |
115 Flush(); | 115 Flush(); |
116 CHECK_EQ(write_count(), 1); | 116 CHECK_EQ(write_count(), 1); |
117 CHECK_EQ(add, last_written()); | 117 CHECK_EQ(add, last_written()); |
118 } | 118 } |
119 | 119 |
120 TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) { | 120 TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) { |
121 BytecodeNode nop(Bytecode::kNop); | 121 BytecodeNode nop(Bytecode::kNop); |
122 nop.source_info().MakeStatementPosition(3); | 122 nop.source_info().MakeStatementPosition(3); |
123 optimizer()->Write(&nop); | 123 optimizer()->Write(&nop); |
124 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); | 124 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), 1); |
125 add.source_info().MakeExpressionPosition(3); | 125 add.source_info().MakeExpressionPosition(3); |
126 optimizer()->Write(&add); | 126 optimizer()->Write(&add); |
127 Flush(); | 127 Flush(); |
128 CHECK_EQ(write_count(), 2); | 128 CHECK_EQ(write_count(), 2); |
129 CHECK_EQ(add, last_written()); | 129 CHECK_EQ(add, last_written()); |
130 } | 130 } |
131 | 131 |
132 // Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode(). | 132 // Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode(). |
133 | 133 |
134 TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) { | 134 TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) { |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 {Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi}, | 487 {Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi}, |
488 {Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi}, | 488 {Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi}, |
489 {Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi}, | 489 {Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi}, |
490 {Bytecode::kShiftRight, Bytecode::kShiftRightSmi}}; | 490 {Bytecode::kShiftRight, Bytecode::kShiftRightSmi}}; |
491 | 491 |
492 for (auto operator_replacement : operator_replacement_pairs) { | 492 for (auto operator_replacement : operator_replacement_pairs) { |
493 uint32_t imm_operand = 17; | 493 uint32_t imm_operand = 17; |
494 BytecodeNode first(Bytecode::kLdaSmi, imm_operand); | 494 BytecodeNode first(Bytecode::kLdaSmi, imm_operand); |
495 first.source_info().Clone({3, true}); | 495 first.source_info().Clone({3, true}); |
496 uint32_t reg_operand = Register(0).ToOperand(); | 496 uint32_t reg_operand = Register(0).ToOperand(); |
497 BytecodeNode second(operator_replacement[0], reg_operand); | 497 BytecodeNode second(operator_replacement[0], reg_operand, 1); |
498 optimizer()->Write(&first); | 498 optimizer()->Write(&first); |
499 optimizer()->Write(&second); | 499 optimizer()->Write(&second); |
500 Flush(); | 500 Flush(); |
501 CHECK_EQ(write_count(), 1); | 501 CHECK_EQ(write_count(), 1); |
502 CHECK_EQ(last_written().bytecode(), operator_replacement[1]); | 502 CHECK_EQ(last_written().bytecode(), operator_replacement[1]); |
503 CHECK_EQ(last_written().operand_count(), 2); | 503 CHECK_EQ(last_written().operand_count(), 2); |
504 CHECK_EQ(last_written().operand(0), imm_operand); | 504 CHECK_EQ(last_written().operand(0), imm_operand); |
505 CHECK_EQ(last_written().operand(1), reg_operand); | 505 CHECK_EQ(last_written().operand(1), reg_operand); |
506 CHECK_EQ(last_written().source_info(), first.source_info()); | 506 CHECK_EQ(last_written().source_info(), first.source_info()); |
507 Reset(); | 507 Reset(); |
508 } | 508 } |
509 } | 509 } |
510 | 510 |
511 TEST_F(BytecodePeepholeOptimizerTest, NotMergingLdaSmiWithBinaryOp) { | 511 TEST_F(BytecodePeepholeOptimizerTest, NotMergingLdaSmiWithBinaryOp) { |
512 Bytecode operator_replacement_pairs[][2] = { | 512 Bytecode operator_replacement_pairs[][2] = { |
513 {Bytecode::kAdd, Bytecode::kAddSmi}, | 513 {Bytecode::kAdd, Bytecode::kAddSmi}, |
514 {Bytecode::kSub, Bytecode::kSubSmi}, | 514 {Bytecode::kSub, Bytecode::kSubSmi}, |
515 {Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi}, | 515 {Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi}, |
516 {Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi}, | 516 {Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi}, |
517 {Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi}, | 517 {Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi}, |
518 {Bytecode::kShiftRight, Bytecode::kShiftRightSmi}}; | 518 {Bytecode::kShiftRight, Bytecode::kShiftRightSmi}}; |
519 | 519 |
520 for (auto operator_replacement : operator_replacement_pairs) { | 520 for (auto operator_replacement : operator_replacement_pairs) { |
521 uint32_t imm_operand = 17; | 521 uint32_t imm_operand = 17; |
522 BytecodeNode first(Bytecode::kLdaSmi, imm_operand); | 522 BytecodeNode first(Bytecode::kLdaSmi, imm_operand); |
523 first.source_info().Clone({3, true}); | 523 first.source_info().Clone({3, true}); |
524 uint32_t reg_operand = Register(0).ToOperand(); | 524 uint32_t reg_operand = Register(0).ToOperand(); |
525 BytecodeNode second(operator_replacement[0], reg_operand); | 525 BytecodeNode second(operator_replacement[0], reg_operand, 1); |
526 second.source_info().Clone({4, true}); | 526 second.source_info().Clone({4, true}); |
527 optimizer()->Write(&first); | 527 optimizer()->Write(&first); |
528 optimizer()->Write(&second); | 528 optimizer()->Write(&second); |
529 CHECK_EQ(last_written(), first); | 529 CHECK_EQ(last_written(), first); |
530 Flush(); | 530 Flush(); |
531 CHECK_EQ(last_written(), second); | 531 CHECK_EQ(last_written(), second); |
532 Reset(); | 532 Reset(); |
533 } | 533 } |
534 } | 534 } |
535 | 535 |
536 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaZeroWithBinaryOp) { | 536 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaZeroWithBinaryOp) { |
537 Bytecode operator_replacement_pairs[][2] = { | 537 Bytecode operator_replacement_pairs[][2] = { |
538 {Bytecode::kAdd, Bytecode::kAddSmi}, | 538 {Bytecode::kAdd, Bytecode::kAddSmi}, |
539 {Bytecode::kSub, Bytecode::kSubSmi}, | 539 {Bytecode::kSub, Bytecode::kSubSmi}, |
540 {Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi}, | 540 {Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi}, |
541 {Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi}, | 541 {Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi}, |
542 {Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi}, | 542 {Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi}, |
543 {Bytecode::kShiftRight, Bytecode::kShiftRightSmi}}; | 543 {Bytecode::kShiftRight, Bytecode::kShiftRightSmi}}; |
544 | 544 |
545 for (auto operator_replacement : operator_replacement_pairs) { | 545 for (auto operator_replacement : operator_replacement_pairs) { |
546 BytecodeNode first(Bytecode::kLdaZero); | 546 BytecodeNode first(Bytecode::kLdaZero); |
547 uint32_t reg_operand = Register(0).ToOperand(); | 547 uint32_t reg_operand = Register(0).ToOperand(); |
548 BytecodeNode second(operator_replacement[0], reg_operand); | 548 BytecodeNode second(operator_replacement[0], reg_operand, 1); |
549 optimizer()->Write(&first); | 549 optimizer()->Write(&first); |
550 optimizer()->Write(&second); | 550 optimizer()->Write(&second); |
551 Flush(); | 551 Flush(); |
552 CHECK_EQ(write_count(), 1); | 552 CHECK_EQ(write_count(), 1); |
553 CHECK_EQ(last_written().bytecode(), operator_replacement[1]); | 553 CHECK_EQ(last_written().bytecode(), operator_replacement[1]); |
554 CHECK_EQ(last_written().operand_count(), 2); | 554 CHECK_EQ(last_written().operand_count(), 2); |
555 CHECK_EQ(last_written().operand(0), 0); | 555 CHECK_EQ(last_written().operand(0), 0); |
556 CHECK_EQ(last_written().operand(1), reg_operand); | 556 CHECK_EQ(last_written().operand(1), reg_operand); |
557 Reset(); | 557 Reset(); |
558 } | 558 } |
559 } | 559 } |
560 | 560 |
561 } // namespace interpreter | 561 } // namespace interpreter |
562 } // namespace internal | 562 } // namespace internal |
563 } // namespace v8 | 563 } // namespace v8 |
OLD | NEW |