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/interpreter/bytecode-dead-code-optimizer.h" 8 #include "src/interpreter/bytecode-label.h" 9 #include "src/objects.h" 10 #include "test/unittests/test-utils.h" 11 12 namespace v8 { 13 namespace internal { 14 namespace interpreter { 15 16 class BytecodeDeadCodeOptimizerTest : public BytecodePipelineStage, 17 public TestWithIsolateAndZone { 18 public: 19 BytecodeDeadCodeOptimizerTest() : dead_code_optimizer_(this) {} 20 ~BytecodeDeadCodeOptimizerTest() override {} 21 22 void Write(BytecodeNode* node) override { 23 write_count_++; 24 last_written_.Clone(node); 25 } 26 27 void WriteJump(BytecodeNode* node, BytecodeLabel* label) override { 28 write_count_++; 29 last_written_.Clone(node); 30 } 31 32 void BindLabel(BytecodeLabel* label) override {} 33 void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override {} 34 Handle<BytecodeArray> ToBytecodeArray( 35 int fixed_register_count, int parameter_count, 36 Handle<FixedArray> handle_table) override { 37 return Handle<BytecodeArray>(); 38 } 39 40 BytecodeDeadCodeOptimizer* optimizer() { return &dead_code_optimizer_; } 41 42 int write_count() const { return write_count_; } 43 const BytecodeNode& last_written() const { return last_written_; } 44 45 private: 46 BytecodeDeadCodeOptimizer dead_code_optimizer_; 47 48 int write_count_ = 0; 49 BytecodeNode last_written_; 50 }; 51 52 TEST_F(BytecodeDeadCodeOptimizerTest, LiveCodeKept) { 53 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); 54 optimizer()->Write(&add); 55 CHECK_EQ(write_count(), 1); 56 CHECK_EQ(add, last_written()); 57 58 BytecodeLabel target; 59 BytecodeNode jump(Bytecode::kJump, 0); 60 optimizer()->WriteJump(&jump, &target); 61 CHECK_EQ(write_count(), 2); 62 CHECK_EQ(jump, last_written()); 63 } 64 65 TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterReturnEliminated) { 66 BytecodeNode ret(Bytecode::kReturn); 67 optimizer()->Write(&ret); 68 CHECK_EQ(write_count(), 1); 69 CHECK_EQ(ret, last_written()); 70 71 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); 72 optimizer()->Write(&add); 73 CHECK_EQ(write_count(), 1); 74 CHECK_EQ(ret, last_written()); 75 } 76 77 TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterThrowEliminated) { 78 BytecodeNode thrw(Bytecode::kThrow); 79 optimizer()->Write(&thrw); 80 CHECK_EQ(write_count(), 1); 81 CHECK_EQ(thrw, last_written()); 82 83 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); 84 optimizer()->Write(&add); 85 CHECK_EQ(write_count(), 1); 86 CHECK_EQ(thrw, last_written()); 87 } 88 89 TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterReThrowEliminated) { 90 BytecodeNode rethrow(Bytecode::kReThrow); 91 optimizer()->Write(&rethrow); 92 CHECK_EQ(write_count(), 1); 93 CHECK_EQ(rethrow, last_written()); 94 95 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); 96 optimizer()->Write(&add); 97 CHECK_EQ(write_count(), 1); 98 CHECK_EQ(rethrow, last_written()); 99 } 100 101 TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterJumpEliminated) { 102 BytecodeLabel target; 103 BytecodeNode jump(Bytecode::kJump, 0); 104 optimizer()->WriteJump(&jump, &target); 105 CHECK_EQ(write_count(), 1); 106 CHECK_EQ(jump, last_written()); 107 108 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); 109 optimizer()->Write(&add); 110 CHECK_EQ(write_count(), 1); 111 CHECK_EQ(jump, last_written()); 112 } 113 114 TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeStillDeadAfterConditinalJump) { 115 BytecodeNode ret(Bytecode::kReturn); 116 optimizer()->Write(&ret); 117 CHECK_EQ(write_count(), 1); 118 CHECK_EQ(ret, last_written()); 119 120 BytecodeLabel target; 121 BytecodeNode jump(Bytecode::kJumpIfTrue, 0); 122 optimizer()->WriteJump(&jump, &target); 123 CHECK_EQ(write_count(), 1); 124 CHECK_EQ(ret, last_written()); 125 126 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); 127 optimizer()->Write(&add); 128 CHECK_EQ(write_count(), 1); 129 CHECK_EQ(ret, last_written()); 130 } 131 132 TEST_F(BytecodeDeadCodeOptimizerTest, CodeLiveAfterLabelBind) { 133 BytecodeNode ret(Bytecode::kReturn); 134 optimizer()->Write(&ret); 135 CHECK_EQ(write_count(), 1); 136 CHECK_EQ(ret, last_written()); 137 138 BytecodeLabel target; 139 optimizer()->BindLabel(&target); 140 141 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); 142 optimizer()->Write(&add); 143 CHECK_EQ(write_count(), 2); 144 CHECK_EQ(add, last_written()); 145 } 146 147 } // namespace interpreter 148 } // namespace internal 149 } // namespace v8 150