// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_INTERPRETER_BYTECODE_ARRAY_ITERATOR_H_
#define V8_INTERPRETER_BYTECODE_ARRAY_ITERATOR_H_

#include <memory>

#include "include/v8-callbacks.h"
#include "src/common/globals.h"
#include "src/handles/handles.h"
#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/bytecodes.h"
#include "src/objects/objects.h"
#include "src/objects/smi.h"
#include "src/runtime/runtime.h"

namespace v8 {
namespace internal {

class BytecodeArray;

namespace interpreter {

class BytecodeArrayIterator;

struct V8_EXPORT_PRIVATE JumpTableTargetOffset {
  int case_value;
  int target_offset;
};

class V8_EXPORT_PRIVATE JumpTableTargetOffsets final {
 public:
  // Minimal iterator implementation for use in ranged-for.
  class V8_EXPORT_PRIVATE iterator final {
   public:
    iterator(int case_value, int table_offset, int table_end,
             const BytecodeArrayIterator* iterator);

    JumpTableTargetOffset operator*();
    iterator& operator++();
    bool operator!=(const iterator& other);

   private:
    void UpdateAndAdvanceToValid();

    const BytecodeArrayIterator* iterator_;
    Tagged<Smi> current_;
    int index_;
    int table_offset_;
    int table_end_;
  };

  JumpTableTargetOffsets(const BytecodeArrayIterator* iterator, int table_start,
                         int table_size, int case_value_base);

  iterator begin() const;
  iterator end() const;

  int size() const;

 private:
  const BytecodeArrayIterator* iterator_;
  int table_start_;
  int table_size_;
  int case_value_base_;
};

class V8_EXPORT_PRIVATE BytecodeArrayIterator {
 public:
  explicit BytecodeArrayIterator(Handle<BytecodeArray> bytecode_array,
                                 int initial_offset = 0);
  BytecodeArrayIterator(Handle<BytecodeArray> bytecode_array,
                        int initial_offset, DisallowGarbageCollection& no_gc);
  ~BytecodeArrayIterator();

  BytecodeArrayIterator(const BytecodeArrayIterator&) = delete;
  BytecodeArrayIterator& operator=(const BytecodeArrayIterator&) = delete;

  inline void Advance() {
    cursor_ += current_bytecode_size_without_prefix();
    UpdateOperandScale();
  }
  void SetOffset(int offset);
  void Reset() { SetOffset(0); }

  // Whether the given offset is reachable in this bytecode array.
  static bool IsValidOffset(Handle<BytecodeArray> bytecode_array, int offset);

  void ApplyDebugBreak();

  inline Bytecode current_bytecode() const {
    DCHECK(!done());
    uint8_t current_byte = *cursor_;
    Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
    DCHECK(!Bytecodes::IsPrefixScalingBytecode(current_bytecode));
    return current_bytecode;
  }
  int current_bytecode_size() const {
    return prefix_size_ + current_bytecode_size_without_prefix();
  }
  int current_bytecode_size_without_prefix() const {
    return Bytecodes::Size(current_bytecode(), current_operand_scale());
  }
  int current_offset() const {
    return static_cast<int>(cursor_ - start_ - prefix_size_);
  }
  uint8_t* current_address() const { return cursor_ - prefix_size_; }
  int next_offset() const { return current_offset() + current_bytecode_size(); }
  Bytecode next_bytecode() const {
    uint8_t* next_cursor = cursor_ + current_bytecode_size_without_prefix();
    if (next_cursor == end_) return Bytecode::kIllegal;
    Bytecode next_bytecode = Bytecodes::FromByte(*next_cursor);
    if (Bytecodes::IsPrefixScalingBytecode(next_bytecode)) {
      next_bytecode = Bytecodes::FromByte(*(next_cursor + 1));
    }
    return next_bytecode;
  }
  OperandScale current_operand_scale() const { return operand_scale_; }
  Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }

  uint32_t GetFlag8Operand(int operand_index) const;
  uint32_t GetFlag16Operand(int operand_index) const;
  uint32_t GetUnsignedImmediateOperand(int operand_index) const;
  int32_t GetImmediateOperand(int operand_index) const;
  uint32_t GetIndexOperand(int operand_index) const;
  FeedbackSlot GetSlotOperand(int operand_index) const;
  Register GetReceiver() const;
  Register GetParameter(int parameter_index) const;
  uint32_t GetRegisterCountOperand(int operand_index) const;
  Register GetRegisterOperand(int operand_index) const;
  Register GetStarTargetRegister() const;
  std::pair<Register, Register> GetRegisterPairOperand(int operand_index) const;
  RegisterList GetRegisterListOperand(int operand_index) const;
  int GetRegisterOperandRange(int operand_index) const;
  Runtime::FunctionId GetRuntimeIdOperand(int operand_index) const;
  Runtime::FunctionId GetIntrinsicIdOperand(int operand_index) const;
  uint32_t GetNativeContextIndexOperand(int operand_index) const;
  template <typename IsolateT>
  Handle<Object> GetConstantAtIndex(int offset, IsolateT* isolate) const;
  bool IsConstantAtIndexSmi(int offset) const;
  Tagged<Smi> GetConstantAtIndexAsSmi(int offset) const;
  template <typename IsolateT>
  Handle<Object> GetConstantForIndexOperand(int operand_index,
                                            IsolateT* isolate) const;

  // Returns the relative offset of the branch target at the current bytecode.
  // It is an error to call this method if the bytecode is not for a jump or
  // conditional jump. Returns a negative offset for backward jumps.
  int GetRelativeJumpTargetOffset() const;
  // Returns the absolute offset of the branch target at the current bytecode.
  // It is an error to call this method if the bytecode is not for a jump or
  // conditional jump.
  int GetJumpTargetOffset() const;
  // Returns an iterator over the absolute offsets of the targets of the current
  // switch bytecode's jump table. It is an error to call this method if the
  // bytecode is not a switch.
  JumpTableTargetOffsets GetJumpTableTargetOffsets() const;

  // Returns the absolute offset of the bytecode at the given relative offset
  // from the current bytecode.
  int GetAbsoluteOffset(int relative_offset) const;

  std::ostream& PrintTo(std::ostream& os) const;

  static void UpdatePointersCallback(void* iterator) {
    reinterpret_cast<BytecodeArrayIterator*>(iterator)->UpdatePointers();
  }

  void UpdatePointers();

  inline bool done() const { return cursor_ >= end_; }

  bool operator==(const BytecodeArrayIterator& other) const {
    return cursor_ == other.cursor_;
  }
  bool operator!=(const BytecodeArrayIterator& other) const {
    return cursor_ != other.cursor_;
  }

 private:
  uint32_t GetUnsignedOperand(int operand_index,
                              OperandType operand_type) const;
  int32_t GetSignedOperand(int operand_index, OperandType operand_type) const;

  inline void UpdateOperandScale() {
    if (done()) return;
    uint8_t current_byte = *cursor_;
    Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
    if (Bytecodes::IsPrefixScalingBytecode(current_bytecode)) {
      operand_scale_ =
          Bytecodes::PrefixBytecodeToOperandScale(current_bytecode);
      ++cursor_;
      prefix_size_ = 1;
    } else {
      operand_scale_ = OperandScale::kSingle;
      prefix_size_ = 0;
    }
  }

  Handle<BytecodeArray> bytecode_array_;
  uint8_t* start_;
  uint8_t* end_;
  // The cursor always points to the active bytecode. If there's a prefix, the
  // prefix is at (cursor - 1).
  uint8_t* cursor_;
  OperandScale operand_scale_;
  int prefix_size_;
  LocalHeap* const local_heap_;
};

}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_BYTECODE_ARRAY_ITERATOR_H_
