Home | History | Annotate | Download | only in interpreter
      1 // Copyright 2015 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-array-builder.h"
      8 #include "src/interpreter/bytecode-array-iterator.h"
      9 #include "test/unittests/test-utils.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace interpreter {
     14 
     15 class BytecodeArrayIteratorTest : public TestWithIsolateAndZone {
     16  public:
     17   BytecodeArrayIteratorTest() {}
     18   ~BytecodeArrayIteratorTest() override {}
     19 };
     20 
     21 
     22 TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
     23   // Use a builder to create an array with containing multiple bytecodes
     24   // with 0, 1 and 2 operands.
     25   BytecodeArrayBuilder builder(isolate(), zone(), 3, 3, 0);
     26   Factory* factory = isolate()->factory();
     27   Handle<HeapObject> heap_num_0 = factory->NewHeapNumber(2.718);
     28   Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(2147483647);
     29   Smi* zero = Smi::FromInt(0);
     30   Smi* smi_0 = Smi::FromInt(64);
     31   Smi* smi_1 = Smi::FromInt(-65536);
     32   Register reg_0(0);
     33   Register reg_1(1);
     34   Register param = Register::FromParameterIndex(2, builder.parameter_count());
     35   Handle<String> name = factory->NewStringFromStaticChars("abc");
     36   int name_index = 2;
     37   int feedback_slot = 97;
     38 
     39   builder.LoadLiteral(heap_num_0)
     40       .StoreAccumulatorInRegister(reg_0)
     41       .LoadLiteral(heap_num_1)
     42       .StoreAccumulatorInRegister(reg_0)
     43       .LoadLiteral(zero)
     44       .StoreAccumulatorInRegister(reg_0)
     45       .LoadLiteral(smi_0)
     46       .StoreAccumulatorInRegister(reg_0)
     47       .LoadLiteral(smi_1)
     48       .StoreAccumulatorInRegister(reg_1)
     49       .LoadAccumulatorWithRegister(reg_0)
     50       .BinaryOperation(Token::Value::ADD, reg_0)
     51       .StoreAccumulatorInRegister(reg_1)
     52       .LoadNamedProperty(reg_1, name, feedback_slot)
     53       .BinaryOperation(Token::Value::ADD, reg_0)
     54       .StoreAccumulatorInRegister(param)
     55       .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, param, 1, reg_0)
     56       .ForInPrepare(reg_0)
     57       .CallRuntime(Runtime::kLoadIC_Miss, reg_0, 1)
     58       .Debugger()
     59       .LoadGlobal(0x10000000, TypeofMode::NOT_INSIDE_TYPEOF)
     60       .Return();
     61 
     62   // Test iterator sees the expected output from the builder.
     63   BytecodeArrayIterator iterator(builder.ToBytecodeArray());
     64   const int kPrefixByteSize = 1;
     65   int offset = 0;
     66 
     67   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
     68   CHECK_EQ(iterator.current_offset(), offset);
     69   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
     70   CHECK(iterator.GetConstantForIndexOperand(0).is_identical_to(heap_num_0));
     71   CHECK(!iterator.done());
     72   offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
     73   iterator.Advance();
     74 
     75   CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
     76   CHECK_EQ(iterator.current_offset(), offset);
     77   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
     78   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
     79   CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
     80   CHECK(!iterator.done());
     81   offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
     82   iterator.Advance();
     83 
     84   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
     85   CHECK_EQ(iterator.current_offset(), offset);
     86   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
     87   CHECK(iterator.GetConstantForIndexOperand(0).is_identical_to(heap_num_1));
     88   CHECK(!iterator.done());
     89   offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
     90   iterator.Advance();
     91 
     92   CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
     93   CHECK_EQ(iterator.current_offset(), offset);
     94   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
     95   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
     96   CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
     97   CHECK(!iterator.done());
     98   offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
     99   iterator.Advance();
    100 
    101   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaZero);
    102   CHECK_EQ(iterator.current_offset(), offset);
    103   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    104   CHECK(!iterator.done());
    105   offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle);
    106   iterator.Advance();
    107 
    108   CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
    109   CHECK_EQ(iterator.current_offset(), offset);
    110   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    111   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
    112   CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
    113   CHECK(!iterator.done());
    114   offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
    115   iterator.Advance();
    116 
    117   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
    118   CHECK_EQ(iterator.current_offset(), offset);
    119   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    120   CHECK_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_0);
    121   CHECK(!iterator.done());
    122   offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle);
    123   iterator.Advance();
    124 
    125   CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
    126   CHECK_EQ(iterator.current_offset(), offset);
    127   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    128   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
    129   CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
    130   CHECK(!iterator.done());
    131   offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
    132   iterator.Advance();
    133 
    134   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
    135   CHECK_EQ(iterator.current_offset(), offset);
    136   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
    137   CHECK_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_1);
    138   CHECK(!iterator.done());
    139   offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kQuadruple) +
    140             kPrefixByteSize;
    141   iterator.Advance();
    142 
    143   CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
    144   CHECK_EQ(iterator.current_offset(), offset);
    145   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    146   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
    147   CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
    148   CHECK(!iterator.done());
    149   offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
    150   iterator.Advance();
    151 
    152   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdar);
    153   CHECK_EQ(iterator.current_offset(), offset);
    154   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    155   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
    156   CHECK(!iterator.done());
    157   offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle);
    158   iterator.Advance();
    159 
    160   CHECK_EQ(iterator.current_bytecode(), Bytecode::kAdd);
    161   CHECK_EQ(iterator.current_offset(), offset);
    162   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    163   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
    164   CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
    165   CHECK(!iterator.done());
    166   offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
    167   iterator.Advance();
    168 
    169   CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
    170   CHECK_EQ(iterator.current_offset(), offset);
    171   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    172   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
    173   CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
    174   CHECK(!iterator.done());
    175   offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
    176   iterator.Advance();
    177 
    178   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaNamedProperty);
    179   CHECK_EQ(iterator.current_offset(), offset);
    180   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    181   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
    182   CHECK_EQ(iterator.GetIndexOperand(1), name_index);
    183   CHECK_EQ(iterator.GetIndexOperand(2), feedback_slot);
    184   CHECK(!iterator.done());
    185   offset += Bytecodes::Size(Bytecode::kLdaNamedProperty, OperandScale::kSingle);
    186   iterator.Advance();
    187 
    188   CHECK_EQ(iterator.current_bytecode(), Bytecode::kAdd);
    189   CHECK_EQ(iterator.current_offset(), offset);
    190   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    191   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
    192   CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
    193   CHECK(!iterator.done());
    194   offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
    195   iterator.Advance();
    196 
    197   CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
    198   CHECK_EQ(iterator.current_offset(), offset);
    199   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    200   CHECK_EQ(iterator.GetRegisterOperand(0).index(), param.index());
    201   CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
    202   CHECK(!iterator.done());
    203   offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
    204   iterator.Advance();
    205 
    206   CHECK_EQ(iterator.current_bytecode(), Bytecode::kCallRuntimeForPair);
    207   CHECK_EQ(iterator.current_offset(), offset);
    208   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    209   CHECK_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadLookupSlotForCall);
    210   CHECK_EQ(iterator.GetRegisterOperand(1).index(), param.index());
    211   CHECK_EQ(iterator.GetRegisterOperandRange(1), 1);
    212   CHECK_EQ(iterator.GetRegisterCountOperand(2), 1);
    213   CHECK_EQ(iterator.GetRegisterOperand(3).index(), reg_0.index());
    214   CHECK_EQ(iterator.GetRegisterOperandRange(3), 2);
    215   CHECK(!iterator.done());
    216   offset +=
    217       Bytecodes::Size(Bytecode::kCallRuntimeForPair, OperandScale::kSingle);
    218   iterator.Advance();
    219 
    220   CHECK_EQ(iterator.current_bytecode(), Bytecode::kForInPrepare);
    221   CHECK_EQ(iterator.current_offset(), offset);
    222   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    223   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
    224   CHECK_EQ(iterator.GetRegisterOperandRange(0), 3);
    225   CHECK(!iterator.done());
    226   offset += Bytecodes::Size(Bytecode::kForInPrepare, OperandScale::kSingle);
    227   iterator.Advance();
    228 
    229   CHECK_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime);
    230   CHECK_EQ(iterator.current_offset(), offset);
    231   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    232   CHECK_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadIC_Miss);
    233   CHECK_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
    234   CHECK_EQ(iterator.GetRegisterCountOperand(2), 1);
    235   CHECK(!iterator.done());
    236   offset += Bytecodes::Size(Bytecode::kCallRuntime, OperandScale::kSingle);
    237   iterator.Advance();
    238 
    239   CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
    240   CHECK_EQ(iterator.current_offset(), offset);
    241   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    242   CHECK(!iterator.done());
    243   offset += Bytecodes::Size(Bytecode::kDebugger, OperandScale::kSingle);
    244   iterator.Advance();
    245 
    246   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaGlobal);
    247   CHECK_EQ(iterator.current_offset(), offset);
    248   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
    249   CHECK_EQ(iterator.current_bytecode_size(), 6);
    250   CHECK_EQ(iterator.GetIndexOperand(0), 0x10000000);
    251   offset += Bytecodes::Size(Bytecode::kLdaGlobal, OperandScale::kQuadruple) +
    252             kPrefixByteSize;
    253   iterator.Advance();
    254 
    255   CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
    256   CHECK_EQ(iterator.current_offset(), offset);
    257   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
    258   CHECK(!iterator.done());
    259   iterator.Advance();
    260   CHECK(iterator.done());
    261 }
    262 
    263 }  // namespace interpreter
    264 }  // namespace internal
    265 }  // namespace v8
    266