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/interpreter/interpreter-intrinsics.h" 8 #include "src/objects-inl.h" 9 10 namespace v8 { 11 namespace internal { 12 namespace interpreter { 13 14 BytecodeArrayIterator::BytecodeArrayIterator( 15 Handle<BytecodeArray> bytecode_array) 16 : bytecode_array_(bytecode_array), 17 bytecode_offset_(0), 18 operand_scale_(OperandScale::kSingle), 19 prefix_offset_(0) { 20 UpdateOperandScale(); 21 } 22 23 void BytecodeArrayIterator::Advance() { 24 bytecode_offset_ += current_bytecode_size(); 25 UpdateOperandScale(); 26 } 27 28 void BytecodeArrayIterator::UpdateOperandScale() { 29 if (!done()) { 30 uint8_t current_byte = bytecode_array()->get(bytecode_offset_); 31 Bytecode current_bytecode = Bytecodes::FromByte(current_byte); 32 if (Bytecodes::IsPrefixScalingBytecode(current_bytecode)) { 33 operand_scale_ = 34 Bytecodes::PrefixBytecodeToOperandScale(current_bytecode); 35 prefix_offset_ = 1; 36 } else { 37 operand_scale_ = OperandScale::kSingle; 38 prefix_offset_ = 0; 39 } 40 } 41 } 42 43 bool BytecodeArrayIterator::done() const { 44 return bytecode_offset_ >= bytecode_array()->length(); 45 } 46 47 Bytecode BytecodeArrayIterator::current_bytecode() const { 48 DCHECK(!done()); 49 uint8_t current_byte = 50 bytecode_array()->get(bytecode_offset_ + current_prefix_offset()); 51 Bytecode current_bytecode = Bytecodes::FromByte(current_byte); 52 DCHECK(!Bytecodes::IsPrefixScalingBytecode(current_bytecode)); 53 return current_bytecode; 54 } 55 56 int BytecodeArrayIterator::current_bytecode_size() const { 57 return current_prefix_offset() + 58 Bytecodes::Size(current_bytecode(), current_operand_scale()); 59 } 60 61 uint32_t BytecodeArrayIterator::GetUnsignedOperand( 62 int operand_index, OperandType operand_type) const { 63 DCHECK_GE(operand_index, 0); 64 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(current_bytecode())); 65 DCHECK_EQ(operand_type, 66 Bytecodes::GetOperandType(current_bytecode(), operand_index)); 67 DCHECK(Bytecodes::IsUnsignedOperandType(operand_type)); 68 const uint8_t* operand_start = 69 bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ + 70 current_prefix_offset() + 71 Bytecodes::GetOperandOffset(current_bytecode(), operand_index, 72 current_operand_scale()); 73 return Bytecodes::DecodeUnsignedOperand(operand_start, operand_type, 74 current_operand_scale()); 75 } 76 77 int32_t BytecodeArrayIterator::GetSignedOperand( 78 int operand_index, OperandType operand_type) const { 79 DCHECK_GE(operand_index, 0); 80 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(current_bytecode())); 81 DCHECK_EQ(operand_type, 82 Bytecodes::GetOperandType(current_bytecode(), operand_index)); 83 DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type)); 84 const uint8_t* operand_start = 85 bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ + 86 current_prefix_offset() + 87 Bytecodes::GetOperandOffset(current_bytecode(), operand_index, 88 current_operand_scale()); 89 return Bytecodes::DecodeSignedOperand(operand_start, operand_type, 90 current_operand_scale()); 91 } 92 93 uint32_t BytecodeArrayIterator::GetFlagOperand(int operand_index) const { 94 DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index), 95 OperandType::kFlag8); 96 return GetUnsignedOperand(operand_index, OperandType::kFlag8); 97 } 98 99 int32_t BytecodeArrayIterator::GetImmediateOperand(int operand_index) const { 100 DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index), 101 OperandType::kImm); 102 return GetSignedOperand(operand_index, OperandType::kImm); 103 } 104 105 uint32_t BytecodeArrayIterator::GetRegisterCountOperand( 106 int operand_index) const { 107 DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index), 108 OperandType::kRegCount); 109 return GetUnsignedOperand(operand_index, OperandType::kRegCount); 110 } 111 112 uint32_t BytecodeArrayIterator::GetIndexOperand(int operand_index) const { 113 OperandType operand_type = 114 Bytecodes::GetOperandType(current_bytecode(), operand_index); 115 DCHECK_EQ(operand_type, OperandType::kIdx); 116 return GetUnsignedOperand(operand_index, operand_type); 117 } 118 119 Register BytecodeArrayIterator::GetRegisterOperand(int operand_index) const { 120 OperandType operand_type = 121 Bytecodes::GetOperandType(current_bytecode(), operand_index); 122 const uint8_t* operand_start = 123 bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ + 124 current_prefix_offset() + 125 Bytecodes::GetOperandOffset(current_bytecode(), operand_index, 126 current_operand_scale()); 127 return Bytecodes::DecodeRegisterOperand(operand_start, operand_type, 128 current_operand_scale()); 129 } 130 131 int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const { 132 DCHECK_LE(operand_index, Bytecodes::NumberOfOperands(current_bytecode())); 133 const OperandType* operand_types = 134 Bytecodes::GetOperandTypes(current_bytecode()); 135 DCHECK(Bytecodes::IsRegisterOperandType(operand_types[operand_index])); 136 if (operand_types[operand_index + 1] == OperandType::kRegCount) { 137 return GetRegisterCountOperand(operand_index + 1); 138 } else { 139 OperandType operand_type = operand_types[operand_index]; 140 return Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type); 141 } 142 } 143 144 Runtime::FunctionId BytecodeArrayIterator::GetRuntimeIdOperand( 145 int operand_index) const { 146 OperandType operand_type = 147 Bytecodes::GetOperandType(current_bytecode(), operand_index); 148 DCHECK(operand_type == OperandType::kRuntimeId); 149 uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type); 150 return static_cast<Runtime::FunctionId>(raw_id); 151 } 152 153 Runtime::FunctionId BytecodeArrayIterator::GetIntrinsicIdOperand( 154 int operand_index) const { 155 OperandType operand_type = 156 Bytecodes::GetOperandType(current_bytecode(), operand_index); 157 DCHECK(operand_type == OperandType::kIntrinsicId); 158 uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type); 159 return IntrinsicsHelper::ToRuntimeId( 160 static_cast<IntrinsicsHelper::IntrinsicId>(raw_id)); 161 } 162 163 Handle<Object> BytecodeArrayIterator::GetConstantForIndexOperand( 164 int operand_index) const { 165 return FixedArray::get(bytecode_array()->constant_pool(), 166 GetIndexOperand(operand_index), 167 bytecode_array()->GetIsolate()); 168 } 169 170 171 int BytecodeArrayIterator::GetJumpTargetOffset() const { 172 Bytecode bytecode = current_bytecode(); 173 if (interpreter::Bytecodes::IsJumpImmediate(bytecode)) { 174 int relative_offset = GetImmediateOperand(0); 175 return current_offset() + relative_offset + current_prefix_offset(); 176 } else if (interpreter::Bytecodes::IsJumpConstant(bytecode)) { 177 Smi* smi = Smi::cast(*GetConstantForIndexOperand(0)); 178 return current_offset() + smi->value() + current_prefix_offset(); 179 } else { 180 UNREACHABLE(); 181 return kMinInt; 182 } 183 } 184 185 } // namespace interpreter 186 } // namespace internal 187 } // namespace v8 188