Index: test/unittests/interpreter/bytecode-dead-code-optimizer-unittest.cc |
diff --git a/test/unittests/interpreter/bytecode-dead-code-optimizer-unittest.cc b/test/unittests/interpreter/bytecode-dead-code-optimizer-unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..915c23dad394c12115b2d84bb4472de255410ed7 |
--- /dev/null |
+++ b/test/unittests/interpreter/bytecode-dead-code-optimizer-unittest.cc |
@@ -0,0 +1,149 @@ |
+// Copyright 2016 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "src/v8.h" |
+ |
+#include "src/interpreter/bytecode-dead-code-optimizer.h" |
+#include "src/interpreter/bytecode-label.h" |
+#include "src/objects.h" |
+#include "test/unittests/test-utils.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace interpreter { |
+ |
+class BytecodeDeadCodeOptimizerTest : public BytecodePipelineStage, |
+ public TestWithIsolateAndZone { |
+ public: |
+ BytecodeDeadCodeOptimizerTest() : dead_code_optimizer_(this) {} |
+ ~BytecodeDeadCodeOptimizerTest() override {} |
+ |
+ void Write(BytecodeNode* node) override { |
+ write_count_++; |
+ last_written_.Clone(node); |
+ } |
+ |
+ void WriteJump(BytecodeNode* node, BytecodeLabel* label) override { |
+ write_count_++; |
+ last_written_.Clone(node); |
+ } |
+ |
+ void BindLabel(BytecodeLabel* label) override {} |
+ void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override {} |
+ Handle<BytecodeArray> ToBytecodeArray( |
+ int fixed_register_count, int parameter_count, |
+ Handle<FixedArray> handle_table) override { |
+ return Handle<BytecodeArray>(); |
+ } |
+ |
+ BytecodeDeadCodeOptimizer* optimizer() { return &dead_code_optimizer_; } |
+ |
+ int write_count() const { return write_count_; } |
+ const BytecodeNode& last_written() const { return last_written_; } |
+ |
+ private: |
+ BytecodeDeadCodeOptimizer dead_code_optimizer_; |
+ |
+ int write_count_ = 0; |
+ BytecodeNode last_written_; |
+}; |
+ |
+TEST_F(BytecodeDeadCodeOptimizerTest, LiveCodeKept) { |
+ BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
+ optimizer()->Write(&add); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(add, last_written()); |
+ |
+ BytecodeLabel target; |
+ BytecodeNode jump(Bytecode::kJump, 0); |
+ optimizer()->WriteJump(&jump, &target); |
+ CHECK_EQ(write_count(), 2); |
+ CHECK_EQ(jump, last_written()); |
+} |
+ |
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterReturnEliminated) { |
+ BytecodeNode ret(Bytecode::kReturn); |
+ optimizer()->Write(&ret); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(ret, last_written()); |
+ |
+ BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
+ optimizer()->Write(&add); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(ret, last_written()); |
+} |
+ |
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterThrowEliminated) { |
+ BytecodeNode thrw(Bytecode::kThrow); |
+ optimizer()->Write(&thrw); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(thrw, last_written()); |
+ |
+ BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
+ optimizer()->Write(&add); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(thrw, last_written()); |
+} |
+ |
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterReThrowEliminated) { |
+ BytecodeNode rethrow(Bytecode::kReThrow); |
+ optimizer()->Write(&rethrow); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(rethrow, last_written()); |
+ |
+ BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
+ optimizer()->Write(&add); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(rethrow, last_written()); |
+} |
+ |
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterJumpEliminated) { |
+ BytecodeLabel target; |
+ BytecodeNode jump(Bytecode::kJump, 0); |
+ optimizer()->WriteJump(&jump, &target); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(jump, last_written()); |
+ |
+ BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
+ optimizer()->Write(&add); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(jump, last_written()); |
+} |
+ |
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeStillDeadAfterConditinalJump) { |
+ BytecodeNode ret(Bytecode::kReturn); |
+ optimizer()->Write(&ret); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(ret, last_written()); |
+ |
+ BytecodeLabel target; |
+ BytecodeNode jump(Bytecode::kJumpIfTrue, 0); |
+ optimizer()->WriteJump(&jump, &target); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(ret, last_written()); |
+ |
+ BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
+ optimizer()->Write(&add); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(ret, last_written()); |
+} |
+ |
+TEST_F(BytecodeDeadCodeOptimizerTest, CodeLiveAfterLabelBind) { |
+ BytecodeNode ret(Bytecode::kReturn); |
+ optimizer()->Write(&ret); |
+ CHECK_EQ(write_count(), 1); |
+ CHECK_EQ(ret, last_written()); |
+ |
+ BytecodeLabel target; |
+ optimizer()->BindLabel(&target); |
+ |
+ BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
+ optimizer()->Write(&add); |
+ CHECK_EQ(write_count(), 2); |
+ CHECK_EQ(add, last_written()); |
+} |
+ |
+} // namespace interpreter |
+} // namespace internal |
+} // namespace v8 |