11cb0ef41Sopenharmony_ci// Copyright 2016 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#ifndef V8_INTERPRETER_BYTECODE_ARRAY_ITERATOR_H_
61cb0ef41Sopenharmony_ci#define V8_INTERPRETER_BYTECODE_ARRAY_ITERATOR_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <memory>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/base/optional.h"
111cb0ef41Sopenharmony_ci#include "src/common/globals.h"
121cb0ef41Sopenharmony_ci#include "src/handles/handles.h"
131cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-register.h"
141cb0ef41Sopenharmony_ci#include "src/interpreter/bytecodes.h"
151cb0ef41Sopenharmony_ci#include "src/objects/objects.h"
161cb0ef41Sopenharmony_ci#include "src/objects/smi.h"
171cb0ef41Sopenharmony_ci#include "src/runtime/runtime.h"
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cinamespace v8 {
201cb0ef41Sopenharmony_cinamespace internal {
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ciclass BytecodeArray;
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cinamespace interpreter {
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciclass BytecodeArrayIterator;
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_cistruct V8_EXPORT_PRIVATE JumpTableTargetOffset {
291cb0ef41Sopenharmony_ci  int case_value;
301cb0ef41Sopenharmony_ci  int target_offset;
311cb0ef41Sopenharmony_ci};
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE JumpTableTargetOffsets final {
341cb0ef41Sopenharmony_ci public:
351cb0ef41Sopenharmony_ci  // Minimal iterator implementation for use in ranged-for.
361cb0ef41Sopenharmony_ci  class V8_EXPORT_PRIVATE iterator final {
371cb0ef41Sopenharmony_ci   public:
381cb0ef41Sopenharmony_ci    iterator(int case_value, int table_offset, int table_end,
391cb0ef41Sopenharmony_ci             const BytecodeArrayIterator* iterator);
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci    JumpTableTargetOffset operator*();
421cb0ef41Sopenharmony_ci    iterator& operator++();
431cb0ef41Sopenharmony_ci    bool operator!=(const iterator& other);
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci   private:
461cb0ef41Sopenharmony_ci    void UpdateAndAdvanceToValid();
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci    const BytecodeArrayIterator* iterator_;
491cb0ef41Sopenharmony_ci    Smi current_;
501cb0ef41Sopenharmony_ci    int index_;
511cb0ef41Sopenharmony_ci    int table_offset_;
521cb0ef41Sopenharmony_ci    int table_end_;
531cb0ef41Sopenharmony_ci  };
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  JumpTableTargetOffsets(const BytecodeArrayIterator* iterator, int table_start,
561cb0ef41Sopenharmony_ci                         int table_size, int case_value_base);
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  iterator begin() const;
591cb0ef41Sopenharmony_ci  iterator end() const;
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  int size() const;
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci private:
641cb0ef41Sopenharmony_ci  const BytecodeArrayIterator* iterator_;
651cb0ef41Sopenharmony_ci  int table_start_;
661cb0ef41Sopenharmony_ci  int table_size_;
671cb0ef41Sopenharmony_ci  int case_value_base_;
681cb0ef41Sopenharmony_ci};
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE BytecodeArrayIterator {
711cb0ef41Sopenharmony_ci public:
721cb0ef41Sopenharmony_ci  BytecodeArrayIterator(Handle<BytecodeArray> bytecode_array,
731cb0ef41Sopenharmony_ci                        int initial_offset = 0);
741cb0ef41Sopenharmony_ci  ~BytecodeArrayIterator();
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  BytecodeArrayIterator(const BytecodeArrayIterator&) = delete;
771cb0ef41Sopenharmony_ci  BytecodeArrayIterator& operator=(const BytecodeArrayIterator&) = delete;
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  inline void Advance() {
801cb0ef41Sopenharmony_ci    cursor_ += current_bytecode_size_without_prefix();
811cb0ef41Sopenharmony_ci    UpdateOperandScale();
821cb0ef41Sopenharmony_ci  }
831cb0ef41Sopenharmony_ci  void SetOffset(int offset);
841cb0ef41Sopenharmony_ci  void Reset() { SetOffset(0); }
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  void ApplyDebugBreak();
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  inline Bytecode current_bytecode() const {
891cb0ef41Sopenharmony_ci    DCHECK(!done());
901cb0ef41Sopenharmony_ci    uint8_t current_byte = *cursor_;
911cb0ef41Sopenharmony_ci    Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
921cb0ef41Sopenharmony_ci    DCHECK(!Bytecodes::IsPrefixScalingBytecode(current_bytecode));
931cb0ef41Sopenharmony_ci    return current_bytecode;
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci  int current_bytecode_size() const {
961cb0ef41Sopenharmony_ci    return prefix_size_ + current_bytecode_size_without_prefix();
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci  int current_bytecode_size_without_prefix() const {
991cb0ef41Sopenharmony_ci    return Bytecodes::Size(current_bytecode(), current_operand_scale());
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci  int current_offset() const {
1021cb0ef41Sopenharmony_ci    return static_cast<int>(cursor_ - start_ - prefix_size_);
1031cb0ef41Sopenharmony_ci  }
1041cb0ef41Sopenharmony_ci  int next_offset() const { return current_offset() + current_bytecode_size(); }
1051cb0ef41Sopenharmony_ci  OperandScale current_operand_scale() const { return operand_scale_; }
1061cb0ef41Sopenharmony_ci  Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  uint32_t GetFlagOperand(int operand_index) const;
1091cb0ef41Sopenharmony_ci  uint32_t GetUnsignedImmediateOperand(int operand_index) const;
1101cb0ef41Sopenharmony_ci  int32_t GetImmediateOperand(int operand_index) const;
1111cb0ef41Sopenharmony_ci  uint32_t GetIndexOperand(int operand_index) const;
1121cb0ef41Sopenharmony_ci  FeedbackSlot GetSlotOperand(int operand_index) const;
1131cb0ef41Sopenharmony_ci  Register GetReceiver() const;
1141cb0ef41Sopenharmony_ci  Register GetParameter(int parameter_index) const;
1151cb0ef41Sopenharmony_ci  uint32_t GetRegisterCountOperand(int operand_index) const;
1161cb0ef41Sopenharmony_ci  Register GetRegisterOperand(int operand_index) const;
1171cb0ef41Sopenharmony_ci  std::pair<Register, Register> GetRegisterPairOperand(int operand_index) const;
1181cb0ef41Sopenharmony_ci  RegisterList GetRegisterListOperand(int operand_index) const;
1191cb0ef41Sopenharmony_ci  int GetRegisterOperandRange(int operand_index) const;
1201cb0ef41Sopenharmony_ci  Runtime::FunctionId GetRuntimeIdOperand(int operand_index) const;
1211cb0ef41Sopenharmony_ci  Runtime::FunctionId GetIntrinsicIdOperand(int operand_index) const;
1221cb0ef41Sopenharmony_ci  uint32_t GetNativeContextIndexOperand(int operand_index) const;
1231cb0ef41Sopenharmony_ci  template <typename IsolateT>
1241cb0ef41Sopenharmony_ci  Handle<Object> GetConstantAtIndex(int offset, IsolateT* isolate) const;
1251cb0ef41Sopenharmony_ci  bool IsConstantAtIndexSmi(int offset) const;
1261cb0ef41Sopenharmony_ci  Smi GetConstantAtIndexAsSmi(int offset) const;
1271cb0ef41Sopenharmony_ci  template <typename IsolateT>
1281cb0ef41Sopenharmony_ci  Handle<Object> GetConstantForIndexOperand(int operand_index,
1291cb0ef41Sopenharmony_ci                                            IsolateT* isolate) const;
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  // Returns the relative offset of the branch target at the current bytecode.
1321cb0ef41Sopenharmony_ci  // It is an error to call this method if the bytecode is not for a jump or
1331cb0ef41Sopenharmony_ci  // conditional jump. Returns a negative offset for backward jumps.
1341cb0ef41Sopenharmony_ci  int GetRelativeJumpTargetOffset() const;
1351cb0ef41Sopenharmony_ci  // Returns the absolute offset of the branch target at the current bytecode.
1361cb0ef41Sopenharmony_ci  // It is an error to call this method if the bytecode is not for a jump or
1371cb0ef41Sopenharmony_ci  // conditional jump.
1381cb0ef41Sopenharmony_ci  int GetJumpTargetOffset() const;
1391cb0ef41Sopenharmony_ci  // Returns an iterator over the absolute offsets of the targets of the current
1401cb0ef41Sopenharmony_ci  // switch bytecode's jump table. It is an error to call this method if the
1411cb0ef41Sopenharmony_ci  // bytecode is not a switch.
1421cb0ef41Sopenharmony_ci  JumpTableTargetOffsets GetJumpTableTargetOffsets() const;
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci  // Returns the absolute offset of the bytecode at the given relative offset
1451cb0ef41Sopenharmony_ci  // from the current bytecode.
1461cb0ef41Sopenharmony_ci  int GetAbsoluteOffset(int relative_offset) const;
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  std::ostream& PrintTo(std::ostream& os) const;
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  static void UpdatePointersCallback(void* iterator) {
1511cb0ef41Sopenharmony_ci    reinterpret_cast<BytecodeArrayIterator*>(iterator)->UpdatePointers();
1521cb0ef41Sopenharmony_ci  }
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  void UpdatePointers();
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  inline bool done() const { return cursor_ >= end_; }
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci private:
1591cb0ef41Sopenharmony_ci  uint32_t GetUnsignedOperand(int operand_index,
1601cb0ef41Sopenharmony_ci                              OperandType operand_type) const;
1611cb0ef41Sopenharmony_ci  int32_t GetSignedOperand(int operand_index, OperandType operand_type) const;
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci  inline void UpdateOperandScale() {
1641cb0ef41Sopenharmony_ci    if (done()) return;
1651cb0ef41Sopenharmony_ci    uint8_t current_byte = *cursor_;
1661cb0ef41Sopenharmony_ci    Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
1671cb0ef41Sopenharmony_ci    if (Bytecodes::IsPrefixScalingBytecode(current_bytecode)) {
1681cb0ef41Sopenharmony_ci      operand_scale_ =
1691cb0ef41Sopenharmony_ci          Bytecodes::PrefixBytecodeToOperandScale(current_bytecode);
1701cb0ef41Sopenharmony_ci      ++cursor_;
1711cb0ef41Sopenharmony_ci      prefix_size_ = 1;
1721cb0ef41Sopenharmony_ci    } else {
1731cb0ef41Sopenharmony_ci      operand_scale_ = OperandScale::kSingle;
1741cb0ef41Sopenharmony_ci      prefix_size_ = 0;
1751cb0ef41Sopenharmony_ci    }
1761cb0ef41Sopenharmony_ci  }
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci  Handle<BytecodeArray> bytecode_array_;
1791cb0ef41Sopenharmony_ci  uint8_t* start_;
1801cb0ef41Sopenharmony_ci  uint8_t* end_;
1811cb0ef41Sopenharmony_ci  // The cursor always points to the active bytecode. If there's a prefix, the
1821cb0ef41Sopenharmony_ci  // prefix is at (cursor - 1).
1831cb0ef41Sopenharmony_ci  uint8_t* cursor_;
1841cb0ef41Sopenharmony_ci  OperandScale operand_scale_;
1851cb0ef41Sopenharmony_ci  int prefix_size_;
1861cb0ef41Sopenharmony_ci  LocalHeap* const local_heap_;
1871cb0ef41Sopenharmony_ci};
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci}  // namespace interpreter
1901cb0ef41Sopenharmony_ci}  // namespace internal
1911cb0ef41Sopenharmony_ci}  // namespace v8
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci#endif  // V8_INTERPRETER_BYTECODE_ARRAY_ITERATOR_H_
194