11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-array-iterator.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-decoder.h"
81cb0ef41Sopenharmony_ci#include "src/interpreter/interpreter-intrinsics.h"
91cb0ef41Sopenharmony_ci#include "src/objects/code-inl.h"
101cb0ef41Sopenharmony_ci#include "src/objects/feedback-vector.h"
111cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_cinamespace internal {
151cb0ef41Sopenharmony_cinamespace interpreter {
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciBytecodeArrayIterator::BytecodeArrayIterator(
181cb0ef41Sopenharmony_ci    Handle<BytecodeArray> bytecode_array, int initial_offset)
191cb0ef41Sopenharmony_ci    : bytecode_array_(bytecode_array),
201cb0ef41Sopenharmony_ci      start_(reinterpret_cast<uint8_t*>(
211cb0ef41Sopenharmony_ci          bytecode_array_->GetFirstBytecodeAddress())),
221cb0ef41Sopenharmony_ci      end_(start_ + bytecode_array_->length()),
231cb0ef41Sopenharmony_ci      cursor_(start_ + initial_offset),
241cb0ef41Sopenharmony_ci      operand_scale_(OperandScale::kSingle),
251cb0ef41Sopenharmony_ci      prefix_size_(0),
261cb0ef41Sopenharmony_ci      local_heap_(LocalHeap::Current()
271cb0ef41Sopenharmony_ci                      ? LocalHeap::Current()
281cb0ef41Sopenharmony_ci                      : Isolate::Current()->main_thread_local_heap()) {
291cb0ef41Sopenharmony_ci  local_heap_->AddGCEpilogueCallback(UpdatePointersCallback, this);
301cb0ef41Sopenharmony_ci  UpdateOperandScale();
311cb0ef41Sopenharmony_ci}
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciBytecodeArrayIterator::~BytecodeArrayIterator() {
341cb0ef41Sopenharmony_ci  local_heap_->RemoveGCEpilogueCallback(UpdatePointersCallback, this);
351cb0ef41Sopenharmony_ci}
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_civoid BytecodeArrayIterator::SetOffset(int offset) {
381cb0ef41Sopenharmony_ci  if (offset < 0) return;
391cb0ef41Sopenharmony_ci  cursor_ = reinterpret_cast<uint8_t*>(
401cb0ef41Sopenharmony_ci      bytecode_array()->GetFirstBytecodeAddress() + offset);
411cb0ef41Sopenharmony_ci  UpdateOperandScale();
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_civoid BytecodeArrayIterator::ApplyDebugBreak() {
451cb0ef41Sopenharmony_ci  // Get the raw bytecode from the bytecode array. This may give us a
461cb0ef41Sopenharmony_ci  // scaling prefix, which we can patch with the matching debug-break
471cb0ef41Sopenharmony_ci  // variant.
481cb0ef41Sopenharmony_ci  uint8_t* cursor = cursor_ - prefix_size_;
491cb0ef41Sopenharmony_ci  interpreter::Bytecode bytecode = interpreter::Bytecodes::FromByte(*cursor);
501cb0ef41Sopenharmony_ci  if (interpreter::Bytecodes::IsDebugBreak(bytecode)) return;
511cb0ef41Sopenharmony_ci  interpreter::Bytecode debugbreak =
521cb0ef41Sopenharmony_ci      interpreter::Bytecodes::GetDebugBreak(bytecode);
531cb0ef41Sopenharmony_ci  *cursor = interpreter::Bytecodes::ToByte(debugbreak);
541cb0ef41Sopenharmony_ci}
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ciuint32_t BytecodeArrayIterator::GetUnsignedOperand(
571cb0ef41Sopenharmony_ci    int operand_index, OperandType operand_type) const {
581cb0ef41Sopenharmony_ci  DCHECK_GE(operand_index, 0);
591cb0ef41Sopenharmony_ci  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
601cb0ef41Sopenharmony_ci  DCHECK_EQ(operand_type,
611cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(current_bytecode(), operand_index));
621cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
631cb0ef41Sopenharmony_ci  Address operand_start =
641cb0ef41Sopenharmony_ci      reinterpret_cast<Address>(cursor_) +
651cb0ef41Sopenharmony_ci      Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
661cb0ef41Sopenharmony_ci                                  current_operand_scale());
671cb0ef41Sopenharmony_ci  return BytecodeDecoder::DecodeUnsignedOperand(operand_start, operand_type,
681cb0ef41Sopenharmony_ci                                                current_operand_scale());
691cb0ef41Sopenharmony_ci}
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ciint32_t BytecodeArrayIterator::GetSignedOperand(
721cb0ef41Sopenharmony_ci    int operand_index, OperandType operand_type) const {
731cb0ef41Sopenharmony_ci  DCHECK_GE(operand_index, 0);
741cb0ef41Sopenharmony_ci  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
751cb0ef41Sopenharmony_ci  DCHECK_EQ(operand_type,
761cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(current_bytecode(), operand_index));
771cb0ef41Sopenharmony_ci  DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
781cb0ef41Sopenharmony_ci  Address operand_start =
791cb0ef41Sopenharmony_ci      reinterpret_cast<Address>(cursor_) +
801cb0ef41Sopenharmony_ci      Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
811cb0ef41Sopenharmony_ci                                  current_operand_scale());
821cb0ef41Sopenharmony_ci  return BytecodeDecoder::DecodeSignedOperand(operand_start, operand_type,
831cb0ef41Sopenharmony_ci                                              current_operand_scale());
841cb0ef41Sopenharmony_ci}
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ciuint32_t BytecodeArrayIterator::GetFlagOperand(int operand_index) const {
871cb0ef41Sopenharmony_ci  DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
881cb0ef41Sopenharmony_ci            OperandType::kFlag8);
891cb0ef41Sopenharmony_ci  return GetUnsignedOperand(operand_index, OperandType::kFlag8);
901cb0ef41Sopenharmony_ci}
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ciuint32_t BytecodeArrayIterator::GetUnsignedImmediateOperand(
931cb0ef41Sopenharmony_ci    int operand_index) const {
941cb0ef41Sopenharmony_ci  DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
951cb0ef41Sopenharmony_ci            OperandType::kUImm);
961cb0ef41Sopenharmony_ci  return GetUnsignedOperand(operand_index, OperandType::kUImm);
971cb0ef41Sopenharmony_ci}
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ciint32_t BytecodeArrayIterator::GetImmediateOperand(int operand_index) const {
1001cb0ef41Sopenharmony_ci  DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
1011cb0ef41Sopenharmony_ci            OperandType::kImm);
1021cb0ef41Sopenharmony_ci  return GetSignedOperand(operand_index, OperandType::kImm);
1031cb0ef41Sopenharmony_ci}
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ciuint32_t BytecodeArrayIterator::GetRegisterCountOperand(
1061cb0ef41Sopenharmony_ci    int operand_index) const {
1071cb0ef41Sopenharmony_ci  DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
1081cb0ef41Sopenharmony_ci            OperandType::kRegCount);
1091cb0ef41Sopenharmony_ci  return GetUnsignedOperand(operand_index, OperandType::kRegCount);
1101cb0ef41Sopenharmony_ci}
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ciuint32_t BytecodeArrayIterator::GetIndexOperand(int operand_index) const {
1131cb0ef41Sopenharmony_ci  OperandType operand_type =
1141cb0ef41Sopenharmony_ci      Bytecodes::GetOperandType(current_bytecode(), operand_index);
1151cb0ef41Sopenharmony_ci  DCHECK_EQ(operand_type, OperandType::kIdx);
1161cb0ef41Sopenharmony_ci  return GetUnsignedOperand(operand_index, operand_type);
1171cb0ef41Sopenharmony_ci}
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ciFeedbackSlot BytecodeArrayIterator::GetSlotOperand(int operand_index) const {
1201cb0ef41Sopenharmony_ci  int index = GetIndexOperand(operand_index);
1211cb0ef41Sopenharmony_ci  return FeedbackVector::ToSlot(index);
1221cb0ef41Sopenharmony_ci}
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ciRegister BytecodeArrayIterator::GetReceiver() const {
1251cb0ef41Sopenharmony_ci  return Register::FromParameterIndex(0);
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ciRegister BytecodeArrayIterator::GetParameter(int parameter_index) const {
1291cb0ef41Sopenharmony_ci  DCHECK_GE(parameter_index, 0);
1301cb0ef41Sopenharmony_ci  // The parameter indices are shifted by 1 (receiver is the
1311cb0ef41Sopenharmony_ci  // first entry).
1321cb0ef41Sopenharmony_ci  return Register::FromParameterIndex(parameter_index + 1);
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ciRegister BytecodeArrayIterator::GetRegisterOperand(int operand_index) const {
1361cb0ef41Sopenharmony_ci  OperandType operand_type =
1371cb0ef41Sopenharmony_ci      Bytecodes::GetOperandType(current_bytecode(), operand_index);
1381cb0ef41Sopenharmony_ci  Address operand_start =
1391cb0ef41Sopenharmony_ci      reinterpret_cast<Address>(cursor_) +
1401cb0ef41Sopenharmony_ci      Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
1411cb0ef41Sopenharmony_ci                                  current_operand_scale());
1421cb0ef41Sopenharmony_ci  return BytecodeDecoder::DecodeRegisterOperand(operand_start, operand_type,
1431cb0ef41Sopenharmony_ci                                                current_operand_scale());
1441cb0ef41Sopenharmony_ci}
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_cistd::pair<Register, Register> BytecodeArrayIterator::GetRegisterPairOperand(
1471cb0ef41Sopenharmony_ci    int operand_index) const {
1481cb0ef41Sopenharmony_ci  Register first = GetRegisterOperand(operand_index);
1491cb0ef41Sopenharmony_ci  Register second(first.index() + 1);
1501cb0ef41Sopenharmony_ci  return std::make_pair(first, second);
1511cb0ef41Sopenharmony_ci}
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ciRegisterList BytecodeArrayIterator::GetRegisterListOperand(
1541cb0ef41Sopenharmony_ci    int operand_index) const {
1551cb0ef41Sopenharmony_ci  Register first = GetRegisterOperand(operand_index);
1561cb0ef41Sopenharmony_ci  uint32_t count = GetRegisterCountOperand(operand_index + 1);
1571cb0ef41Sopenharmony_ci  return RegisterList(first.index(), count);
1581cb0ef41Sopenharmony_ci}
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ciint BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
1611cb0ef41Sopenharmony_ci  DCHECK_LE(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
1621cb0ef41Sopenharmony_ci  const OperandType* operand_types =
1631cb0ef41Sopenharmony_ci      Bytecodes::GetOperandTypes(current_bytecode());
1641cb0ef41Sopenharmony_ci  OperandType operand_type = operand_types[operand_index];
1651cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
1661cb0ef41Sopenharmony_ci  if (operand_type == OperandType::kRegList ||
1671cb0ef41Sopenharmony_ci      operand_type == OperandType::kRegOutList) {
1681cb0ef41Sopenharmony_ci    return GetRegisterCountOperand(operand_index + 1);
1691cb0ef41Sopenharmony_ci  } else {
1701cb0ef41Sopenharmony_ci    return Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type);
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci}
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ciRuntime::FunctionId BytecodeArrayIterator::GetRuntimeIdOperand(
1751cb0ef41Sopenharmony_ci    int operand_index) const {
1761cb0ef41Sopenharmony_ci  OperandType operand_type =
1771cb0ef41Sopenharmony_ci      Bytecodes::GetOperandType(current_bytecode(), operand_index);
1781cb0ef41Sopenharmony_ci  DCHECK_EQ(operand_type, OperandType::kRuntimeId);
1791cb0ef41Sopenharmony_ci  uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
1801cb0ef41Sopenharmony_ci  return static_cast<Runtime::FunctionId>(raw_id);
1811cb0ef41Sopenharmony_ci}
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ciuint32_t BytecodeArrayIterator::GetNativeContextIndexOperand(
1841cb0ef41Sopenharmony_ci    int operand_index) const {
1851cb0ef41Sopenharmony_ci  OperandType operand_type =
1861cb0ef41Sopenharmony_ci      Bytecodes::GetOperandType(current_bytecode(), operand_index);
1871cb0ef41Sopenharmony_ci  DCHECK_EQ(operand_type, OperandType::kNativeContextIndex);
1881cb0ef41Sopenharmony_ci  return GetUnsignedOperand(operand_index, operand_type);
1891cb0ef41Sopenharmony_ci}
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ciRuntime::FunctionId BytecodeArrayIterator::GetIntrinsicIdOperand(
1921cb0ef41Sopenharmony_ci    int operand_index) const {
1931cb0ef41Sopenharmony_ci  OperandType operand_type =
1941cb0ef41Sopenharmony_ci      Bytecodes::GetOperandType(current_bytecode(), operand_index);
1951cb0ef41Sopenharmony_ci  DCHECK_EQ(operand_type, OperandType::kIntrinsicId);
1961cb0ef41Sopenharmony_ci  uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
1971cb0ef41Sopenharmony_ci  return IntrinsicsHelper::ToRuntimeId(
1981cb0ef41Sopenharmony_ci      static_cast<IntrinsicsHelper::IntrinsicId>(raw_id));
1991cb0ef41Sopenharmony_ci}
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_citemplate <typename IsolateT>
2021cb0ef41Sopenharmony_ciHandle<Object> BytecodeArrayIterator::GetConstantAtIndex(
2031cb0ef41Sopenharmony_ci    int index, IsolateT* isolate) const {
2041cb0ef41Sopenharmony_ci  return handle(bytecode_array()->constant_pool().get(index), isolate);
2051cb0ef41Sopenharmony_ci}
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_cibool BytecodeArrayIterator::IsConstantAtIndexSmi(int index) const {
2081cb0ef41Sopenharmony_ci  return bytecode_array()->constant_pool().get(index).IsSmi();
2091cb0ef41Sopenharmony_ci}
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ciSmi BytecodeArrayIterator::GetConstantAtIndexAsSmi(int index) const {
2121cb0ef41Sopenharmony_ci  return Smi::cast(bytecode_array()->constant_pool().get(index));
2131cb0ef41Sopenharmony_ci}
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_citemplate <typename IsolateT>
2161cb0ef41Sopenharmony_ciHandle<Object> BytecodeArrayIterator::GetConstantForIndexOperand(
2171cb0ef41Sopenharmony_ci    int operand_index, IsolateT* isolate) const {
2181cb0ef41Sopenharmony_ci  return GetConstantAtIndex(GetIndexOperand(operand_index), isolate);
2191cb0ef41Sopenharmony_ci}
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_citemplate EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
2221cb0ef41Sopenharmony_ci    Handle<Object> BytecodeArrayIterator::GetConstantForIndexOperand(
2231cb0ef41Sopenharmony_ci        int operand_index, Isolate* isolate) const;
2241cb0ef41Sopenharmony_citemplate Handle<Object> BytecodeArrayIterator::GetConstantForIndexOperand(
2251cb0ef41Sopenharmony_ci    int operand_index, LocalIsolate* isolate) const;
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ciint BytecodeArrayIterator::GetRelativeJumpTargetOffset() const {
2281cb0ef41Sopenharmony_ci  Bytecode bytecode = current_bytecode();
2291cb0ef41Sopenharmony_ci  if (interpreter::Bytecodes::IsJumpImmediate(bytecode)) {
2301cb0ef41Sopenharmony_ci    int relative_offset = GetUnsignedImmediateOperand(0);
2311cb0ef41Sopenharmony_ci    if (bytecode == Bytecode::kJumpLoop) {
2321cb0ef41Sopenharmony_ci      relative_offset = -relative_offset;
2331cb0ef41Sopenharmony_ci    }
2341cb0ef41Sopenharmony_ci    return relative_offset;
2351cb0ef41Sopenharmony_ci  } else if (interpreter::Bytecodes::IsJumpConstant(bytecode)) {
2361cb0ef41Sopenharmony_ci    Smi smi = GetConstantAtIndexAsSmi(GetIndexOperand(0));
2371cb0ef41Sopenharmony_ci    return smi.value();
2381cb0ef41Sopenharmony_ci  } else {
2391cb0ef41Sopenharmony_ci    UNREACHABLE();
2401cb0ef41Sopenharmony_ci  }
2411cb0ef41Sopenharmony_ci}
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ciint BytecodeArrayIterator::GetJumpTargetOffset() const {
2441cb0ef41Sopenharmony_ci  return GetAbsoluteOffset(GetRelativeJumpTargetOffset());
2451cb0ef41Sopenharmony_ci}
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ciJumpTableTargetOffsets BytecodeArrayIterator::GetJumpTableTargetOffsets()
2481cb0ef41Sopenharmony_ci    const {
2491cb0ef41Sopenharmony_ci  uint32_t table_start, table_size;
2501cb0ef41Sopenharmony_ci  int32_t case_value_base;
2511cb0ef41Sopenharmony_ci  if (current_bytecode() == Bytecode::kSwitchOnGeneratorState) {
2521cb0ef41Sopenharmony_ci    table_start = GetIndexOperand(1);
2531cb0ef41Sopenharmony_ci    table_size = GetUnsignedImmediateOperand(2);
2541cb0ef41Sopenharmony_ci    case_value_base = 0;
2551cb0ef41Sopenharmony_ci  } else {
2561cb0ef41Sopenharmony_ci    DCHECK_EQ(current_bytecode(), Bytecode::kSwitchOnSmiNoFeedback);
2571cb0ef41Sopenharmony_ci    table_start = GetIndexOperand(0);
2581cb0ef41Sopenharmony_ci    table_size = GetUnsignedImmediateOperand(1);
2591cb0ef41Sopenharmony_ci    case_value_base = GetImmediateOperand(2);
2601cb0ef41Sopenharmony_ci  }
2611cb0ef41Sopenharmony_ci  return JumpTableTargetOffsets(this, table_start, table_size, case_value_base);
2621cb0ef41Sopenharmony_ci}
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ciint BytecodeArrayIterator::GetAbsoluteOffset(int relative_offset) const {
2651cb0ef41Sopenharmony_ci  return current_offset() + relative_offset + prefix_size_;
2661cb0ef41Sopenharmony_ci}
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_cistd::ostream& BytecodeArrayIterator::PrintTo(std::ostream& os) const {
2691cb0ef41Sopenharmony_ci  return BytecodeDecoder::Decode(os, cursor_ - prefix_size_);
2701cb0ef41Sopenharmony_ci}
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_civoid BytecodeArrayIterator::UpdatePointers() {
2731cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
2741cb0ef41Sopenharmony_ci  uint8_t* start =
2751cb0ef41Sopenharmony_ci      reinterpret_cast<uint8_t*>(bytecode_array_->GetFirstBytecodeAddress());
2761cb0ef41Sopenharmony_ci  if (start != start_) {
2771cb0ef41Sopenharmony_ci    start_ = start;
2781cb0ef41Sopenharmony_ci    uint8_t* end = start + bytecode_array_->length();
2791cb0ef41Sopenharmony_ci    size_t distance_to_end = end_ - cursor_;
2801cb0ef41Sopenharmony_ci    cursor_ = end - distance_to_end;
2811cb0ef41Sopenharmony_ci    end_ = end;
2821cb0ef41Sopenharmony_ci  }
2831cb0ef41Sopenharmony_ci}
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ciJumpTableTargetOffsets::JumpTableTargetOffsets(
2861cb0ef41Sopenharmony_ci    const BytecodeArrayIterator* iterator, int table_start, int table_size,
2871cb0ef41Sopenharmony_ci    int case_value_base)
2881cb0ef41Sopenharmony_ci    : iterator_(iterator),
2891cb0ef41Sopenharmony_ci      table_start_(table_start),
2901cb0ef41Sopenharmony_ci      table_size_(table_size),
2911cb0ef41Sopenharmony_ci      case_value_base_(case_value_base) {}
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ciJumpTableTargetOffsets::iterator JumpTableTargetOffsets::begin() const {
2941cb0ef41Sopenharmony_ci  return iterator(case_value_base_, table_start_, table_start_ + table_size_,
2951cb0ef41Sopenharmony_ci                  iterator_);
2961cb0ef41Sopenharmony_ci}
2971cb0ef41Sopenharmony_ciJumpTableTargetOffsets::iterator JumpTableTargetOffsets::end() const {
2981cb0ef41Sopenharmony_ci  return iterator(case_value_base_ + table_size_, table_start_ + table_size_,
2991cb0ef41Sopenharmony_ci                  table_start_ + table_size_, iterator_);
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ciint JumpTableTargetOffsets::size() const {
3021cb0ef41Sopenharmony_ci  int ret = 0;
3031cb0ef41Sopenharmony_ci  // TODO(leszeks): Is there a more efficient way of doing this than iterating?
3041cb0ef41Sopenharmony_ci  for (JumpTableTargetOffset entry : *this) {
3051cb0ef41Sopenharmony_ci    USE(entry);
3061cb0ef41Sopenharmony_ci    ret++;
3071cb0ef41Sopenharmony_ci  }
3081cb0ef41Sopenharmony_ci  return ret;
3091cb0ef41Sopenharmony_ci}
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ciJumpTableTargetOffsets::iterator::iterator(
3121cb0ef41Sopenharmony_ci    int case_value, int table_offset, int table_end,
3131cb0ef41Sopenharmony_ci    const BytecodeArrayIterator* iterator)
3141cb0ef41Sopenharmony_ci    : iterator_(iterator),
3151cb0ef41Sopenharmony_ci      current_(Smi::zero()),
3161cb0ef41Sopenharmony_ci      index_(case_value),
3171cb0ef41Sopenharmony_ci      table_offset_(table_offset),
3181cb0ef41Sopenharmony_ci      table_end_(table_end) {
3191cb0ef41Sopenharmony_ci  UpdateAndAdvanceToValid();
3201cb0ef41Sopenharmony_ci}
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ciJumpTableTargetOffset JumpTableTargetOffsets::iterator::operator*() {
3231cb0ef41Sopenharmony_ci  DCHECK_LT(table_offset_, table_end_);
3241cb0ef41Sopenharmony_ci  return {index_, iterator_->GetAbsoluteOffset(Smi::ToInt(current_))};
3251cb0ef41Sopenharmony_ci}
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ciJumpTableTargetOffsets::iterator&
3281cb0ef41Sopenharmony_ciJumpTableTargetOffsets::iterator::operator++() {
3291cb0ef41Sopenharmony_ci  DCHECK_LT(table_offset_, table_end_);
3301cb0ef41Sopenharmony_ci  ++table_offset_;
3311cb0ef41Sopenharmony_ci  ++index_;
3321cb0ef41Sopenharmony_ci  UpdateAndAdvanceToValid();
3331cb0ef41Sopenharmony_ci  return *this;
3341cb0ef41Sopenharmony_ci}
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_cibool JumpTableTargetOffsets::iterator::operator!=(
3371cb0ef41Sopenharmony_ci    const JumpTableTargetOffsets::iterator& other) {
3381cb0ef41Sopenharmony_ci  DCHECK_EQ(iterator_, other.iterator_);
3391cb0ef41Sopenharmony_ci  DCHECK_EQ(table_end_, other.table_end_);
3401cb0ef41Sopenharmony_ci  DCHECK_EQ(index_ - other.index_, table_offset_ - other.table_offset_);
3411cb0ef41Sopenharmony_ci  return index_ != other.index_;
3421cb0ef41Sopenharmony_ci}
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_civoid JumpTableTargetOffsets::iterator::UpdateAndAdvanceToValid() {
3451cb0ef41Sopenharmony_ci  while (table_offset_ < table_end_ &&
3461cb0ef41Sopenharmony_ci         !iterator_->IsConstantAtIndexSmi(table_offset_)) {
3471cb0ef41Sopenharmony_ci    ++table_offset_;
3481cb0ef41Sopenharmony_ci    ++index_;
3491cb0ef41Sopenharmony_ci  }
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_ci  // Make sure we haven't reached the end of the table with a hole in current.
3521cb0ef41Sopenharmony_ci  if (table_offset_ < table_end_) {
3531cb0ef41Sopenharmony_ci    DCHECK(iterator_->IsConstantAtIndexSmi(table_offset_));
3541cb0ef41Sopenharmony_ci    current_ = iterator_->GetConstantAtIndexAsSmi(table_offset_);
3551cb0ef41Sopenharmony_ci  }
3561cb0ef41Sopenharmony_ci}
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci}  // namespace interpreter
3591cb0ef41Sopenharmony_ci}  // namespace internal
3601cb0ef41Sopenharmony_ci}  // namespace v8
361