blob: 0fea985efee2911cb141fdc4857e2d021d42a407 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
9namespace v8 {
10namespace internal {
11namespace interpreter {
12
13BytecodeArrayIterator::BytecodeArrayIterator(
14 Handle<BytecodeArray> bytecode_array)
15 : bytecode_array_(bytecode_array), bytecode_offset_(0) {}
16
17
18void BytecodeArrayIterator::Advance() {
19 bytecode_offset_ += Bytecodes::Size(current_bytecode());
20}
21
22
23bool BytecodeArrayIterator::done() const {
24 return bytecode_offset_ >= bytecode_array()->length();
25}
26
27
28Bytecode 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
35int BytecodeArrayIterator::current_bytecode_size() const {
36 return Bytecodes::Size(current_bytecode());
37}
38
39
40uint32_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)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 case OperandSize::kByte:
51 return static_cast<uint32_t>(*operand_start);
52 case OperandSize::kShort:
53 return ReadUnalignedUInt16(operand_start);
Ben Murdoch097c5b22016-05-18 11:27:45 +010054 case OperandSize::kNone:
55 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 }
Ben Murdoch097c5b22016-05-18 11:27:45 +010057 return 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058}
59
60
61int8_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
Ben Murdoch097c5b22016-05-18 11:27:45 +010066int BytecodeArrayIterator::GetRegisterCountOperand(int operand_index) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 OperandSize size =
68 Bytecodes::GetOperandSize(current_bytecode(), operand_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +010069 OperandType type = (size == OperandSize::kByte) ? OperandType::kRegCount8
70 : OperandType::kRegCount16;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 uint32_t operand = GetRawOperand(operand_index, type);
72 return static_cast<int>(operand);
73}
74
75
76int BytecodeArrayIterator::GetIndexOperand(int operand_index) const {
77 OperandType operand_type =
78 Bytecodes::GetOperandType(current_bytecode(), operand_index);
79 DCHECK(operand_type == OperandType::kIdx8 ||
80 operand_type == OperandType::kIdx16);
81 uint32_t operand = GetRawOperand(operand_index, operand_type);
82 return static_cast<int>(operand);
83}
84
85
86Register BytecodeArrayIterator::GetRegisterOperand(int operand_index) const {
87 OperandType operand_type =
88 Bytecodes::GetOperandType(current_bytecode(), operand_index);
Ben Murdoch097c5b22016-05-18 11:27:45 +010089 DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 uint32_t operand = GetRawOperand(operand_index, operand_type);
Ben Murdoch097c5b22016-05-18 11:27:45 +010091 Register reg;
92 switch (Bytecodes::GetOperandSize(current_bytecode(), operand_index)) {
93 case OperandSize::kByte:
94 reg = Register::FromOperand(static_cast<uint8_t>(operand));
95 break;
96 case OperandSize::kShort:
97 reg = Register::FromWideOperand(static_cast<uint16_t>(operand));
98 break;
99 case OperandSize::kNone:
100 UNREACHABLE();
101 reg = Register::invalid_value();
102 break;
103 }
104 DCHECK_GE(reg.index(),
105 Register::FromParameterIndex(0, bytecode_array()->parameter_count())
106 .index());
107 DCHECK(reg.index() < bytecode_array()->register_count() ||
108 (reg.index() == 0 &&
109 Bytecodes::IsMaybeRegisterOperandType(
110 Bytecodes::GetOperandType(current_bytecode(), operand_index))));
111 return reg;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112}
113
Ben Murdoch097c5b22016-05-18 11:27:45 +0100114int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
115 interpreter::OperandType operand_type =
116 Bytecodes::GetOperandType(current_bytecode(), operand_index);
117 DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
118 switch (operand_type) {
119 case OperandType::kRegPair8:
120 case OperandType::kRegPair16:
121 case OperandType::kRegOutPair8:
122 case OperandType::kRegOutPair16:
123 return 2;
124 case OperandType::kRegOutTriple8:
125 case OperandType::kRegOutTriple16:
126 return 3;
127 default: {
128 if (operand_index + 1 !=
129 Bytecodes::NumberOfOperands(current_bytecode())) {
130 OperandType next_operand_type =
131 Bytecodes::GetOperandType(current_bytecode(), operand_index + 1);
132 if (Bytecodes::IsRegisterCountOperandType(next_operand_type)) {
133 return GetRegisterCountOperand(operand_index + 1);
134 }
135 }
136 return 1;
137 }
138 }
139}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140
141Handle<Object> BytecodeArrayIterator::GetConstantForIndexOperand(
142 int operand_index) const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100143 return FixedArray::get(bytecode_array()->constant_pool(),
144 GetIndexOperand(operand_index),
145 bytecode_array()->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000146}
147
148
149int BytecodeArrayIterator::GetJumpTargetOffset() const {
150 Bytecode bytecode = current_bytecode();
151 if (interpreter::Bytecodes::IsJumpImmediate(bytecode)) {
152 int relative_offset = GetImmediateOperand(0);
153 return current_offset() + relative_offset;
154 } else if (interpreter::Bytecodes::IsJumpConstant(bytecode) ||
155 interpreter::Bytecodes::IsJumpConstantWide(bytecode)) {
156 Smi* smi = Smi::cast(*GetConstantForIndexOperand(0));
157 return current_offset() + smi->value();
158 } else {
159 UNREACHABLE();
160 return kMinInt;
161 }
162}
163
164} // namespace interpreter
165} // namespace internal
166} // namespace v8