| 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 |