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/interpreter/bytecode-array-iterator.h"
      6 
      7 #include "src/objects-inl.h"
      8 
      9 namespace v8 {
     10 namespace internal {
     11 namespace interpreter {
     12 
     13 BytecodeArrayIterator::BytecodeArrayIterator(
     14     Handle<BytecodeArray> bytecode_array)
     15     : bytecode_array_(bytecode_array), bytecode_offset_(0) {}
     16 
     17 
     18 void BytecodeArrayIterator::Advance() {
     19   bytecode_offset_ += Bytecodes::Size(current_bytecode());
     20 }
     21 
     22 
     23 bool BytecodeArrayIterator::done() const {
     24   return bytecode_offset_ >= bytecode_array()->length();
     25 }
     26 
     27 
     28 Bytecode BytecodeArrayIterator::current_bytecode() const {
     29   DCHECK(!done());
     30   uint8_t current_byte = bytecode_array()->get(bytecode_offset_);
     31   return interpreter::Bytecodes::FromByte(current_byte);
     32 }
     33 
     34 
     35 int BytecodeArrayIterator::current_bytecode_size() const {
     36   return Bytecodes::Size(current_bytecode());
     37 }
     38 
     39 
     40 uint32_t BytecodeArrayIterator::GetRawOperand(int operand_index,
     41                                               OperandType operand_type) const {
     42   DCHECK_GE(operand_index, 0);
     43   DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
     44   DCHECK_EQ(operand_type,
     45             Bytecodes::GetOperandType(current_bytecode(), operand_index));
     46   uint8_t* operand_start =
     47       bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ +
     48       Bytecodes::GetOperandOffset(current_bytecode(), operand_index);
     49   switch (Bytecodes::SizeOfOperand(operand_type)) {
     50     default:
     51     case OperandSize::kNone:
     52       UNREACHABLE();
     53     case OperandSize::kByte:
     54       return static_cast<uint32_t>(*operand_start);
     55     case OperandSize::kShort:
     56       return ReadUnalignedUInt16(operand_start);
     57   }
     58 }
     59 
     60 
     61 int8_t BytecodeArrayIterator::GetImmediateOperand(int operand_index) const {
     62   uint32_t operand = GetRawOperand(operand_index, OperandType::kImm8);
     63   return static_cast<int8_t>(operand);
     64 }
     65 
     66 
     67 int BytecodeArrayIterator::GetCountOperand(int operand_index) const {
     68   OperandSize size =
     69       Bytecodes::GetOperandSize(current_bytecode(), operand_index);
     70   OperandType type = (size == OperandSize::kByte) ? OperandType::kCount8
     71                                                   : OperandType::kCount16;
     72   uint32_t operand = GetRawOperand(operand_index, type);
     73   return static_cast<int>(operand);
     74 }
     75 
     76 
     77 int BytecodeArrayIterator::GetIndexOperand(int operand_index) const {
     78   OperandType operand_type =
     79       Bytecodes::GetOperandType(current_bytecode(), operand_index);
     80   DCHECK(operand_type == OperandType::kIdx8 ||
     81          operand_type == OperandType::kIdx16);
     82   uint32_t operand = GetRawOperand(operand_index, operand_type);
     83   return static_cast<int>(operand);
     84 }
     85 
     86 
     87 Register BytecodeArrayIterator::GetRegisterOperand(int operand_index) const {
     88   OperandType operand_type =
     89       Bytecodes::GetOperandType(current_bytecode(), operand_index);
     90   DCHECK(operand_type == OperandType::kReg8 ||
     91          operand_type == OperandType::kRegPair8 ||
     92          operand_type == OperandType::kMaybeReg8 ||
     93          operand_type == OperandType::kReg16);
     94   uint32_t operand = GetRawOperand(operand_index, operand_type);
     95   return Register::FromOperand(operand);
     96 }
     97 
     98 
     99 Handle<Object> BytecodeArrayIterator::GetConstantForIndexOperand(
    100     int operand_index) const {
    101   Handle<FixedArray> constants = handle(bytecode_array()->constant_pool());
    102   return FixedArray::get(constants, GetIndexOperand(operand_index));
    103 }
    104 
    105 
    106 int BytecodeArrayIterator::GetJumpTargetOffset() const {
    107   Bytecode bytecode = current_bytecode();
    108   if (interpreter::Bytecodes::IsJumpImmediate(bytecode)) {
    109     int relative_offset = GetImmediateOperand(0);
    110     return current_offset() + relative_offset;
    111   } else if (interpreter::Bytecodes::IsJumpConstant(bytecode) ||
    112              interpreter::Bytecodes::IsJumpConstantWide(bytecode)) {
    113     Smi* smi = Smi::cast(*GetConstantForIndexOperand(0));
    114     return current_offset() + smi->value();
    115   } else {
    116     UNREACHABLE();
    117     return kMinInt;
    118   }
    119 }
    120 
    121 }  // namespace interpreter
    122 }  // namespace internal
    123 }  // namespace v8
    124