Line data Source code
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-accessor.h"
6 :
7 : #include "src/interpreter/bytecode-decoder.h"
8 : #include "src/interpreter/interpreter-intrinsics.h"
9 : #include "src/objects-inl.h"
10 : #include "src/objects/code-inl.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 : namespace interpreter {
15 :
16 1020200 : BytecodeArrayAccessor::BytecodeArrayAccessor(
17 : Handle<BytecodeArray> bytecode_array, int initial_offset)
18 : : bytecode_array_(bytecode_array),
19 : bytecode_offset_(initial_offset),
20 : operand_scale_(OperandScale::kSingle),
21 1020200 : prefix_offset_(0) {
22 1020200 : UpdateOperandScale();
23 1020202 : }
24 :
25 51327241 : void BytecodeArrayAccessor::SetOffset(int offset) {
26 51327241 : bytecode_offset_ = offset;
27 51327241 : UpdateOperandScale();
28 51327258 : }
29 :
30 52347432 : void BytecodeArrayAccessor::UpdateOperandScale() {
31 52347432 : if (OffsetInBounds()) {
32 : uint8_t current_byte = bytecode_array()->get(bytecode_offset_);
33 : Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
34 51331518 : if (Bytecodes::IsPrefixScalingBytecode(current_bytecode)) {
35 : operand_scale_ =
36 4958302 : Bytecodes::PrefixBytecodeToOperandScale(current_bytecode);
37 4958302 : prefix_offset_ = 1;
38 : } else {
39 46373216 : operand_scale_ = OperandScale::kSingle;
40 46373216 : prefix_offset_ = 0;
41 : }
42 : }
43 52347432 : }
44 :
45 0 : bool BytecodeArrayAccessor::OffsetInBounds() const {
46 104694867 : return bytecode_offset_ >= 0 && bytecode_offset_ < bytecode_array()->length();
47 : }
48 :
49 96316756 : Bytecode BytecodeArrayAccessor::current_bytecode() const {
50 : DCHECK(OffsetInBounds());
51 : uint8_t current_byte =
52 173236652 : bytecode_array()->get(bytecode_offset_ + current_prefix_offset());
53 : Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
54 : DCHECK(!Bytecodes::IsPrefixScalingBytecode(current_bytecode));
55 32419066 : return current_bytecode;
56 : }
57 :
58 32608893 : int BytecodeArrayAccessor::current_bytecode_size() const {
59 : return current_prefix_offset() +
60 32608893 : Bytecodes::Size(current_bytecode(), current_operand_scale());
61 : }
62 :
63 11831868 : uint32_t BytecodeArrayAccessor::GetUnsignedOperand(
64 35495600 : int operand_index, OperandType operand_type) const {
65 : DCHECK_GE(operand_index, 0);
66 : DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
67 : DCHECK_EQ(operand_type,
68 : Bytecodes::GetOperandType(current_bytecode(), operand_index));
69 : DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
70 : const uint8_t* operand_start =
71 11831868 : bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ +
72 23663736 : current_prefix_offset() +
73 : Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
74 11831868 : current_operand_scale());
75 : return BytecodeDecoder::DecodeUnsignedOperand(operand_start, operand_type,
76 11831864 : current_operand_scale());
77 : }
78 :
79 1000511 : int32_t BytecodeArrayAccessor::GetSignedOperand(
80 3001533 : int operand_index, OperandType operand_type) const {
81 : DCHECK_GE(operand_index, 0);
82 : DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
83 : DCHECK_EQ(operand_type,
84 : Bytecodes::GetOperandType(current_bytecode(), operand_index));
85 : DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
86 : const uint8_t* operand_start =
87 1000511 : bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ +
88 2001022 : current_prefix_offset() +
89 : Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
90 1000511 : current_operand_scale());
91 : return BytecodeDecoder::DecodeSignedOperand(operand_start, operand_type,
92 1000511 : current_operand_scale());
93 : }
94 :
95 754317 : uint32_t BytecodeArrayAccessor::GetFlagOperand(int operand_index) const {
96 : DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
97 : OperandType::kFlag8);
98 754317 : return GetUnsignedOperand(operand_index, OperandType::kFlag8);
99 : }
100 :
101 131489 : uint32_t BytecodeArrayAccessor::GetUnsignedImmediateOperand(
102 : int operand_index) const {
103 : DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
104 : OperandType::kUImm);
105 1777099 : return GetUnsignedOperand(operand_index, OperandType::kUImm);
106 : }
107 :
108 985435 : int32_t BytecodeArrayAccessor::GetImmediateOperand(int operand_index) const {
109 : DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
110 : OperandType::kImm);
111 1000511 : return GetSignedOperand(operand_index, OperandType::kImm);
112 : }
113 :
114 630874 : uint32_t BytecodeArrayAccessor::GetRegisterCountOperand(
115 : int operand_index) const {
116 : DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
117 : OperandType::kRegCount);
118 630878 : return GetUnsignedOperand(operand_index, OperandType::kRegCount);
119 : }
120 :
121 8486927 : uint32_t BytecodeArrayAccessor::GetIndexOperand(int operand_index) const {
122 : OperandType operand_type =
123 : Bytecodes::GetOperandType(current_bytecode(), operand_index);
124 : DCHECK_EQ(operand_type, OperandType::kIdx);
125 8486927 : return GetUnsignedOperand(operand_index, operand_type);
126 : }
127 :
128 63473669 : Register BytecodeArrayAccessor::GetRegisterOperand(int operand_index) const {
129 : OperandType operand_type =
130 : Bytecodes::GetOperandType(current_bytecode(), operand_index);
131 : const uint8_t* operand_start =
132 21157890 : bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ +
133 21157890 : current_prefix_offset() +
134 : Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
135 21157890 : current_operand_scale());
136 : return BytecodeDecoder::DecodeRegisterOperand(operand_start, operand_type,
137 21157889 : current_operand_scale());
138 : }
139 :
140 40 : int BytecodeArrayAccessor::GetRegisterOperandRange(int operand_index) const {
141 : DCHECK_LE(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
142 : const OperandType* operand_types =
143 : Bytecodes::GetOperandTypes(current_bytecode());
144 40 : OperandType operand_type = operand_types[operand_index];
145 : DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
146 80 : if (operand_type == OperandType::kRegList ||
147 40 : operand_type == OperandType::kRegOutList) {
148 8 : return GetRegisterCountOperand(operand_index + 1);
149 : } else {
150 36 : return Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type);
151 : }
152 : }
153 :
154 128885 : Runtime::FunctionId BytecodeArrayAccessor::GetRuntimeIdOperand(
155 : int operand_index) const {
156 : OperandType operand_type =
157 : Bytecodes::GetOperandType(current_bytecode(), operand_index);
158 : DCHECK_EQ(operand_type, OperandType::kRuntimeId);
159 128885 : uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
160 128885 : return static_cast<Runtime::FunctionId>(raw_id);
161 : }
162 :
163 9799 : uint32_t BytecodeArrayAccessor::GetNativeContextIndexOperand(
164 : int operand_index) const {
165 : OperandType operand_type =
166 : Bytecodes::GetOperandType(current_bytecode(), operand_index);
167 : DCHECK_EQ(operand_type, OperandType::kNativeContextIndex);
168 9799 : return GetUnsignedOperand(operand_index, operand_type);
169 : }
170 :
171 43988 : Runtime::FunctionId BytecodeArrayAccessor::GetIntrinsicIdOperand(
172 : int operand_index) const {
173 : OperandType operand_type =
174 : Bytecodes::GetOperandType(current_bytecode(), operand_index);
175 : DCHECK_EQ(operand_type, OperandType::kIntrinsicId);
176 43988 : uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
177 : return IntrinsicsHelper::ToRuntimeId(
178 43988 : static_cast<IntrinsicsHelper::IntrinsicId>(raw_id));
179 : }
180 :
181 3153728 : Handle<Object> BytecodeArrayAccessor::GetConstantAtIndex(int index) const {
182 : return FixedArray::get(bytecode_array()->constant_pool(), index,
183 3153728 : bytecode_array()->GetIsolate());
184 : }
185 :
186 3103381 : Handle<Object> BytecodeArrayAccessor::GetConstantForIndexOperand(
187 : int operand_index) const {
188 3103381 : return GetConstantAtIndex(GetIndexOperand(operand_index));
189 : }
190 :
191 1651095 : int BytecodeArrayAccessor::GetJumpTargetOffset() const {
192 : Bytecode bytecode = current_bytecode();
193 1651095 : if (interpreter::Bytecodes::IsJumpImmediate(bytecode)) {
194 1630534 : int relative_offset = GetUnsignedImmediateOperand(0);
195 1630534 : if (bytecode == Bytecode::kJumpLoop) {
196 167279 : relative_offset = -relative_offset;
197 : }
198 1630534 : return GetAbsoluteOffset(relative_offset);
199 20561 : } else if (interpreter::Bytecodes::IsJumpConstant(bytecode)) {
200 41122 : Smi* smi = Smi::cast(*GetConstantForIndexOperand(0));
201 20561 : return GetAbsoluteOffset(smi->value());
202 : } else {
203 0 : UNREACHABLE();
204 : }
205 : }
206 :
207 15076 : JumpTableTargetOffsets BytecodeArrayAccessor::GetJumpTableTargetOffsets()
208 : const {
209 : DCHECK_EQ(current_bytecode(), Bytecode::kSwitchOnSmiNoFeedback);
210 :
211 15076 : uint32_t table_start = GetIndexOperand(0);
212 : uint32_t table_size = GetUnsignedImmediateOperand(1);
213 : int32_t case_value_base = GetImmediateOperand(2);
214 :
215 30152 : return JumpTableTargetOffsets(this, table_start, table_size, case_value_base);
216 : }
217 :
218 3370578 : int BytecodeArrayAccessor::GetAbsoluteOffset(int relative_offset) const {
219 3370578 : return current_offset() + relative_offset + current_prefix_offset();
220 : }
221 :
222 0 : bool BytecodeArrayAccessor::OffsetWithinBytecode(int offset) const {
223 0 : return current_offset() <= offset &&
224 0 : offset < current_offset() + current_bytecode_size();
225 : }
226 :
227 54 : std::ostream& BytecodeArrayAccessor::PrintTo(std::ostream& os) const {
228 : return BytecodeDecoder::Decode(
229 54 : os, bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_,
230 54 : bytecode_array()->parameter_count());
231 : }
232 :
233 0 : JumpTableTargetOffsets::JumpTableTargetOffsets(
234 : const BytecodeArrayAccessor* accessor, int table_start, int table_size,
235 : int case_value_base)
236 : : accessor_(accessor),
237 : table_start_(table_start),
238 : table_size_(table_size),
239 15076 : case_value_base_(case_value_base) {}
240 :
241 15076 : JumpTableTargetOffsets::iterator JumpTableTargetOffsets::begin() const {
242 : return iterator(case_value_base_, table_start_, table_start_ + table_size_,
243 37158 : accessor_);
244 : }
245 15076 : JumpTableTargetOffsets::iterator JumpTableTargetOffsets::end() const {
246 : return iterator(case_value_base_ + table_size_, table_start_ + table_size_,
247 37158 : table_start_ + table_size_, accessor_);
248 : }
249 7006 : int JumpTableTargetOffsets::size() const {
250 : int ret = 0;
251 : // TODO(leszeks): Is there a more efficient way of doing this than iterating?
252 23104 : for (const auto& entry : *this) {
253 : USE(entry);
254 16098 : ret++;
255 : }
256 7006 : return ret;
257 : }
258 :
259 0 : JumpTableTargetOffsets::iterator::iterator(
260 : int case_value, int table_offset, int table_end,
261 : const BytecodeArrayAccessor* accessor)
262 : : accessor_(accessor),
263 : index_(case_value),
264 : table_offset_(table_offset),
265 88328 : table_end_(table_end) {
266 44164 : UpdateAndAdvanceToValid();
267 0 : }
268 :
269 34194 : JumpTableTargetOffset JumpTableTargetOffsets::iterator::operator*() {
270 : DCHECK_LT(table_offset_, table_end_);
271 : DCHECK(current_->IsSmi());
272 102582 : return {index_, accessor_->GetAbsoluteOffset(Smi::ToInt(*current_))};
273 : }
274 :
275 34194 : JumpTableTargetOffsets::iterator& JumpTableTargetOffsets::iterator::
276 : operator++() {
277 : DCHECK_LT(table_offset_, table_end_);
278 50292 : ++table_offset_;
279 50292 : ++index_;
280 50292 : UpdateAndAdvanceToValid();
281 34194 : return *this;
282 : }
283 :
284 49270 : bool JumpTableTargetOffsets::iterator::operator!=(
285 : const JumpTableTargetOffsets::iterator& other) {
286 : DCHECK_EQ(accessor_, other.accessor_);
287 : DCHECK_EQ(table_end_, other.table_end_);
288 : DCHECK_EQ(index_ - other.index_, table_offset_ - other.table_offset_);
289 72374 : return index_ != other.index_;
290 : }
291 :
292 94456 : void JumpTableTargetOffsets::iterator::UpdateAndAdvanceToValid() {
293 188912 : if (table_offset_ >= table_end_) return;
294 :
295 50292 : current_ = accessor_->GetConstantAtIndex(table_offset_);
296 50292 : Isolate* isolate = accessor_->bytecode_array()->GetIsolate();
297 100638 : while (current_->IsTheHole(isolate)) {
298 54 : ++table_offset_;
299 54 : ++index_;
300 54 : current_ = accessor_->GetConstantAtIndex(table_offset_);
301 : }
302 : }
303 :
304 : } // namespace interpreter
305 : } // namespace internal
306 : } // namespace v8
|