Home | History | Annotate | Download | only in interpreter
      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