// Copyright 2013 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_COMPILER_NODE_H_
#define V8_COMPILER_NODE_H_

#include "src/common/globals.h"
#include "src/compiler/graph-zone-traits.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
#include "src/compiler/types.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {
namespace compiler {

// Forward declarations.
class Edge;
class Graph;


// Marks are used during traversal of the graph to distinguish states of nodes.
// Each node has a mark which is a monotonically increasing integer, and a
// {NodeMarker} has a range of values that indicate states of a node.
using Mark = uint32_t;

// NodeIds are identifying numbers for nodes that can be used to index auxiliary
// out-of-line data associated with each node.
using NodeId = uint32_t;

// A Node is the basic primitive of graphs. Nodes are chained together by
// input/use chains but by default otherwise contain only an identifying number
// which specific applications of graphs and nodes can use to index auxiliary
// out-of-line data, especially transient data.
//
// In addition Nodes only contain a mutable Operator that may change during
// compilation, e.g. during lowering passes. Other information that needs to be
// associated with Nodes during compilation must be stored out-of-line indexed
// by the Node's id.
class V8_EXPORT_PRIVATE Node final {
 public:
  static Node* New(Zone* zone, NodeId id, const Operator* op, int input_count,
                   Node* const* inputs, bool has_extensible_inputs);
  static Node* Clone(Zone* zone, NodeId id, const Node* node);

  inline bool IsDead() const;
  void Kill();

  const Operator* op() const { return op_; }

  IrOpcode::Value opcode() const {
    DCHECK_GE(IrOpcode::kLast, op_->opcode());
    return static_cast<IrOpcode::Value>(op_->opcode());
  }

  NodeId id() const { return IdField::decode(bit_field_); }

  int InputCount() const {
    return has_inline_inputs() ? InlineCountField::decode(bit_field_)
                               : outline_inputs()->count_;
  }

#ifdef DEBUG
  void Verify();
#else
  inline void Verify() {}
#endif

  Node* InputAt(int index) const {
    CHECK_LE(0, index);
    CHECK_LT(index, InputCount());
    return *GetInputPtrConst(index);
  }

  void ReplaceInput(int index, Node* new_to) {
    CHECK_LE(0, index);
    CHECK_LT(index, InputCount());
    ZoneNodePtr* input_ptr = GetInputPtr(index);
    Node* old_to = *input_ptr;
    if (old_to != new_to) {
      Use* use = GetUsePtr(index);
      if (old_to) old_to->RemoveUse(use);
      *input_ptr = new_to;
      if (new_to) new_to->AppendUse(use);
    }
  }

  void AppendInput(Zone* zone, Node* new_to);
  void InsertInput(Zone* zone, int index, Node* new_to);
  void InsertInputs(Zone* zone, int index, int count);
  // Returns the removed input.
  Node* RemoveInput(int index);
  void NullAllInputs();
  void TrimInputCount(int new_input_count);
  // Can trim, extend by appending new inputs, or do nothing.
  void EnsureInputCount(Zone* zone, int new_input_count);

  int UseCount() const;
  void ReplaceUses(Node* replace_to);

  class InputEdges;
  inline InputEdges input_edges();

  class Inputs;
  inline Inputs inputs() const;

  class UseEdges final {
   public:
    using value_type = Edge;

    class iterator;
    inline iterator begin() const;
    inline iterator end() const;

    bool empty() const;

    explicit UseEdges(Node* node) : node_(node) {}

   private:
    Node* node_;
  };

  UseEdges use_edges() { return UseEdges(this); }

  class V8_EXPORT_PRIVATE Uses final {
   public:
    using value_type = Node*;

    class const_iterator;
    inline const_iterator begin() const;
    inline const_iterator end() const;

    bool empty() const;

    explicit Uses(Node* node) : node_(node) {}

   private:
    Node* node_;
  };

  Uses uses() { return Uses(this); }

  // Returns true if {owner} is the only user of {this} node.
  bool OwnedBy(Node const* owner) const;

  // Returns true if {owner1} and {owner2} are the only users of {this} node.
  bool OwnedBy(Node const* owner1, Node const* owner2) const;

  void Print() const { Print(1); }
  void Print(int depth) const;
  void Print(std::ostream&, int depth = 1) const;

 private:
  template <typename NodePtrT>
  inline static Node* NewImpl(Zone* zone, NodeId id, const Operator* op,
                              int input_count, NodePtrT const* inputs,
                              bool has_extensible_inputs);

  struct Use;
  using ZoneUsePtr = GraphZoneTraits::Ptr<Use>;

  // Out of line storage for inputs when the number of inputs overflowed the
  // capacity of the inline-allocated space.
  struct OutOfLineInputs {
    ZoneNodePtr node_;
    int count_;
    int capacity_;

    // Inputs are allocated right behind the OutOfLineInputs instance.
    inline ZoneNodePtr* inputs();

    static OutOfLineInputs* New(Zone* zone, int capacity);
    void ExtractFrom(Use* use_ptr, ZoneNodePtr* input_ptr, int count);
  };
  using ZoneOutOfLineInputsPtr = GraphZoneTraits::Ptr<OutOfLineInputs>;

  // A link in the use chain for a node. Every input {i} to a node {n} has an
  // associated {Use} which is linked into the use chain of the {i} node.
  struct Use {
    ZoneUsePtr next;
    ZoneUsePtr prev;
    uint32_t bit_field_;

    int input_index() const { return InputIndexField::decode(bit_field_); }
    bool is_inline_use() const { return InlineField::decode(bit_field_); }
    ZoneNodePtr* input_ptr() {
      int index = input_index();
      Use* start = this + 1 + index;
      ZoneNodePtr* inputs =
          is_inline_use() ? reinterpret_cast<Node*>(start)->inline_inputs()
                          : reinterpret_cast<OutOfLineInputs*>(start)->inputs();
      return &inputs[index];
    }

    Node* from() {
      Use* start = this + 1 + input_index();
      return is_inline_use() ? reinterpret_cast<Node*>(start)
                             : reinterpret_cast<OutOfLineInputs*>(start)->node_;
    }

    using InlineField = base::BitField<bool, 0, 1>;
    using InputIndexField = base::BitField<unsigned, 1, 31>;
  };

  //============================================================================
  //== Memory layout ===========================================================
  //============================================================================
  // Saving space for big graphs is important. We use a memory layout trick to
  // be able to map {Node} objects to {Use} objects and vice-versa in a
  // space-efficient manner.
  //
  // {Use} links are laid out in memory directly before a {Node}, followed by
  // direct pointers to input {Nodes}.
  //
  // inline case:
  // |Use #N  |Use #N-1|...|Use #1  |Use #0  |Node xxxx |I#0|I#1|...|I#N-1|I#N|
  //          ^                              ^                  ^
  //          + Use                          + Node             + Input
  //
  // Since every {Use} instance records its {input_index}, pointer arithmetic
  // can compute the {Node}.
  //
  // out-of-line case:
  //     |Node xxxx |
  //     ^       + outline ------------------+
  //     +----------------------------------------+
  //                                         |    |
  //                                         v    | node
  // |Use #N  |Use #N-1|...|Use #1  |Use #0  |OOL xxxxx |I#0|I#1|...|I#N-1|I#N|
  //          ^                                                 ^
  //          + Use                                             + Input
  //
  // Out-of-line storage of input lists is needed if appending an input to
  // a node exceeds the maximum inline capacity.

  Node(NodeId id, const Operator* op, int inline_count, int inline_capacity);
  Node(const Node&) = delete;
  Node& operator=(const Node&) = delete;

  inline Address inputs_location() const;

  ZoneNodePtr* inline_inputs() const {
    return reinterpret_cast<ZoneNodePtr*>(inputs_location());
  }
  OutOfLineInputs* outline_inputs() const {
    return *reinterpret_cast<ZoneOutOfLineInputsPtr*>(inputs_location());
  }
  void set_outline_inputs(OutOfLineInputs* outline) {
    *reinterpret_cast<ZoneOutOfLineInputsPtr*>(inputs_location()) = outline;
  }

  ZoneNodePtr const* GetInputPtrConst(int input_index) const {
    return has_inline_inputs() ? &(inline_inputs()[input_index])
                               : &(outline_inputs()->inputs()[input_index]);
  }
  ZoneNodePtr* GetInputPtr(int input_index) {
    return has_inline_inputs() ? &(inline_inputs()[input_index])
                               : &(outline_inputs()->inputs()[input_index]);
  }
  Use* GetUsePtr(int input_index) {
    Use* ptr = has_inline_inputs() ? reinterpret_cast<Use*>(this)
                                   : reinterpret_cast<Use*>(outline_inputs());
    return &ptr[-1 - input_index];
  }

  void AppendUse(Use* use);
  void RemoveUse(Use* use);

  void* operator new(size_t, void* location) { return location; }

  // Only NodeProperties should manipulate the op.
  void set_op(const Operator* op) { op_ = op; }

  // Only NodeProperties should manipulate the type.
  Type type() const { return type_; }
  void set_type(Type type) { type_ = type; }

  // Only NodeMarkers should manipulate the marks on nodes.
  Mark mark() const { return mark_; }
  void set_mark(Mark mark) { mark_ = mark; }

  inline bool has_inline_inputs() const {
    return InlineCountField::decode(bit_field_) != kOutlineMarker;
  }

  void ClearInputs(int start, int count);

  using IdField = base::BitField<NodeId, 0, 24>;
  using InlineCountField = base::BitField<unsigned, 24, 4>;
  using InlineCapacityField = base::BitField<unsigned, 28, 4>;
  static const int kOutlineMarker = InlineCountField::kMax;
  static const int kMaxInlineCapacity = InlineCapacityField::kMax - 1;

  const Operator* op_;
  Type type_;
  Mark mark_;
  uint32_t bit_field_;
  ZoneUsePtr first_use_;

  friend class Edge;
  friend class NodeMarkerBase;
  friend class NodeProperties;
};

Address Node::inputs_location() const {
  return reinterpret_cast<Address>(this) + sizeof(Node);
}

ZoneNodePtr* Node::OutOfLineInputs::inputs() {
  return reinterpret_cast<ZoneNodePtr*>(reinterpret_cast<Address>(this) +
                                        sizeof(Node::OutOfLineInputs));
}

std::ostream& operator<<(std::ostream& os, const Node& n);

// Base class for node wrappers.
class NodeWrapper {
 public:
  explicit constexpr NodeWrapper(Node* node) : node_(node) {}
  operator Node*() const { return node_; }
  Node* operator->() const { return node_; }

 protected:
  Node* node() const { return node_; }
  void set_node(Node* node) {
    DCHECK_NOT_NULL(node);
    node_ = node;
  }

 private:
  Node* node_;
};

// Wrapper classes for special node/edge types (effect, control, frame states).

class Effect : public NodeWrapper {
 public:
  explicit constexpr Effect(Node* node) : NodeWrapper(node) {
    // TODO(jgruber): Remove the End special case.
    SLOW_DCHECK(node == nullptr || node->op()->opcode() == IrOpcode::kEnd ||
                node->op()->EffectOutputCount() > 0);
  }

  // Support the common `Node* x = effect = ...` pattern.
  Node* operator=(Node* value) {
    DCHECK_GT(value->op()->EffectOutputCount(), 0);
    set_node(value);
    return value;
  }
};

class Control : public NodeWrapper {
 public:
  explicit constexpr Control(Node* node) : NodeWrapper(node) {
    // TODO(jgruber): Remove the End special case.
    SLOW_DCHECK(node == nullptr || node->opcode() == IrOpcode::kEnd ||
                node->op()->ControlOutputCount() > 0);
  }

  // Support the common `Node* x = control = ...` pattern.
  Node* operator=(Node* value) {
    DCHECK_GT(value->op()->ControlOutputCount(), 0);
    set_node(value);
    return value;
  }
};

class FrameState : public NodeWrapper {
 public:
  explicit constexpr FrameState(Node* node) : NodeWrapper(node) {
    // TODO(jgruber): Disallow kStart (needed for PromiseConstructorBasic unit
    // test, among others).
    SLOW_DCHECK(node->opcode() == IrOpcode::kFrameState ||
                node->opcode() == IrOpcode::kStart);
  }

  // Duplicating here from frame-states.h for ease of access and to keep
  // header include-balls small. Equality of the two constants is
  // static-asserted elsewhere.
  static constexpr int kFrameStateOuterStateInput = 5;

  FrameState outer_frame_state() const {
    return FrameState{node()->InputAt(kFrameStateOuterStateInput)};
  }
};

// Typedefs to shorten commonly used Node containers.
using NodeDeque = ZoneDeque<Node*>;
using NodeSet = ZoneSet<Node*>;
using NodeVector = ZoneVector<Node*>;
using NodeVectorVector = ZoneVector<NodeVector>;

class Node::InputEdges final {
 public:
  using value_type = Edge;

  class iterator;
  inline iterator begin() const;
  inline iterator end() const;

  bool empty() const { return count_ == 0; }
  int count() const { return count_; }

  inline value_type operator[](int index) const;

  InputEdges(ZoneNodePtr* input_root, Use* use_root, int count)
      : input_root_(input_root), use_root_(use_root), count_(count) {}

 private:
  ZoneNodePtr* input_root_;
  Use* use_root_;
  int count_;
};

class V8_EXPORT_PRIVATE Node::Inputs final {
 public:
  using value_type = Node*;

  class const_iterator;
  inline const_iterator begin() const;
  inline const_iterator end() const;

  bool empty() const { return count_ == 0; }
  int count() const { return count_; }

  inline value_type operator[](int index) const;

  explicit Inputs(ZoneNodePtr const* input_root, int count)
      : input_root_(input_root), count_(count) {}

 private:
  ZoneNodePtr const* input_root_;
  int count_;
};

// An encapsulation for information associated with a single use of node as a
// input from another node, allowing access to both the defining node and
// the node having the input.
class Edge final {
 public:
  Node* from() const { return use_->from(); }
  Node* to() const { return *input_ptr_; }
  int index() const {
    int const index = use_->input_index();
    DCHECK_LT(index, use_->from()->InputCount());
    return index;
  }

  bool operator==(const Edge& other) { return input_ptr_ == other.input_ptr_; }
  bool operator!=(const Edge& other) { return !(*this == other); }

  void UpdateTo(Node* new_to) {
    Node* old_to = *input_ptr_;
    if (old_to != new_to) {
      if (old_to) old_to->RemoveUse(use_);
      *input_ptr_ = new_to;
      if (new_to) new_to->AppendUse(use_);
    }
  }

 private:
  friend class Node::UseEdges::iterator;
  friend class Node::InputEdges;
  friend class Node::InputEdges::iterator;

  Edge(Node::Use* use, ZoneNodePtr* input_ptr)
      : use_(use), input_ptr_(input_ptr) {
    DCHECK_NOT_NULL(use);
    DCHECK_NOT_NULL(input_ptr);
    DCHECK_EQ(input_ptr, use->input_ptr());
  }

  Node::Use* use_;
  ZoneNodePtr* input_ptr_;
};

bool Node::IsDead() const {
  Node::Inputs inputs = this->inputs();
  return inputs.count() > 0 && inputs[0] == nullptr;
}

Node::InputEdges Node::input_edges() {
  int inline_count = InlineCountField::decode(bit_field_);
  if (inline_count != kOutlineMarker) {
    return InputEdges(inline_inputs(), reinterpret_cast<Use*>(this) - 1,
                      inline_count);
  } else {
    return InputEdges(outline_inputs()->inputs(),
                      reinterpret_cast<Use*>(outline_inputs()) - 1,
                      outline_inputs()->count_);
  }
}

Node::Inputs Node::inputs() const {
  int inline_count = InlineCountField::decode(bit_field_);
  if (inline_count != kOutlineMarker) {
    return Inputs(inline_inputs(), inline_count);
  } else {
    return Inputs(outline_inputs()->inputs(), outline_inputs()->count_);
  }
}

// A forward iterator to visit the edges for the input dependencies of a node.
class Node::InputEdges::iterator final {
 public:
  using iterator_category = std::forward_iterator_tag;
  using difference_type = std::ptrdiff_t;
  using value_type = Edge;
  using pointer = Edge*;
  using reference = Edge&;

  iterator() : use_(nullptr), input_ptr_(nullptr) {}
  iterator(const iterator& other) = default;

  Edge operator*() const { return Edge(use_, input_ptr_); }
  bool operator==(const iterator& other) const {
    return input_ptr_ == other.input_ptr_;
  }
  bool operator!=(const iterator& other) const { return !(*this == other); }
  iterator& operator++() {
    input_ptr_++;
    use_--;
    return *this;
  }
  iterator operator++(int);
  iterator& operator+=(difference_type offset) {
    input_ptr_ += offset;
    use_ -= offset;
    return *this;
  }
  iterator operator+(difference_type offset) const {
    return iterator(use_ - offset, input_ptr_ + offset);
  }
  difference_type operator-(const iterator& other) const {
    return input_ptr_ - other.input_ptr_;
  }

 private:
  friend class Node;

  explicit iterator(Use* use, ZoneNodePtr* input_ptr)
      : use_(use), input_ptr_(input_ptr) {}

  Use* use_;
  ZoneNodePtr* input_ptr_;
};


Node::InputEdges::iterator Node::InputEdges::begin() const {
  return Node::InputEdges::iterator(use_root_, input_root_);
}


Node::InputEdges::iterator Node::InputEdges::end() const {
  return Node::InputEdges::iterator(use_root_ - count_, input_root_ + count_);
}

Edge Node::InputEdges::operator[](int index) const {
  return Edge(use_root_ + index, input_root_ + index);
}

// A forward iterator to visit the inputs of a node.
class Node::Inputs::const_iterator final {
 public:
  using iterator_category = std::forward_iterator_tag;
  using difference_type = std::ptrdiff_t;
  using value_type = Node*;
  using pointer = const value_type*;
  using reference = value_type&;

  const_iterator(const const_iterator& other) = default;

  Node* operator*() const { return *input_ptr_; }
  bool operator==(const const_iterator& other) const {
    return input_ptr_ == other.input_ptr_;
  }
  bool operator!=(const const_iterator& other) const {
    return !(*this == other);
  }
  const_iterator& operator++() {
    ++input_ptr_;
    return *this;
  }
  const_iterator operator++(int);
  const_iterator& operator+=(difference_type offset) {
    input_ptr_ += offset;
    return *this;
  }
  const_iterator operator+(difference_type offset) const {
    return const_iterator(input_ptr_ + offset);
  }
  difference_type operator-(const const_iterator& other) const {
    return input_ptr_ - other.input_ptr_;
  }

 private:
  friend class Node::Inputs;

  explicit const_iterator(ZoneNodePtr const* input_ptr)
      : input_ptr_(input_ptr) {}

  ZoneNodePtr const* input_ptr_;
};


Node::Inputs::const_iterator Node::Inputs::begin() const {
  return const_iterator(input_root_);
}


Node::Inputs::const_iterator Node::Inputs::end() const {
  return const_iterator(input_root_ + count_);
}

Node* Node::Inputs::operator[](int index) const { return input_root_[index]; }

// A forward iterator to visit the uses edges of a node.
class Node::UseEdges::iterator final {
 public:
  iterator(const iterator& other) = default;

  Edge operator*() const { return Edge(current_, current_->input_ptr()); }
  bool operator==(const iterator& other) const {
    return current_ == other.current_;
  }
  bool operator!=(const iterator& other) const { return !(*this == other); }
  iterator& operator++() {
    DCHECK_NOT_NULL(current_);
    current_ = next_;
    next_ = current_ ? static_cast<Node::Use*>(current_->next) : nullptr;
    return *this;
  }
  iterator operator++(int);

 private:
  friend class Node::UseEdges;

  iterator() : current_(nullptr), next_(nullptr) {}
  explicit iterator(Node* node)
      : current_(node->first_use_),
        next_(current_ ? static_cast<Node::Use*>(current_->next) : nullptr) {}

  Node::Use* current_;
  Node::Use* next_;
};


Node::UseEdges::iterator Node::UseEdges::begin() const {
  return Node::UseEdges::iterator(this->node_);
}


Node::UseEdges::iterator Node::UseEdges::end() const {
  return Node::UseEdges::iterator();
}


// A forward iterator to visit the uses of a node.
class Node::Uses::const_iterator final {
 public:
  using iterator_category = std::forward_iterator_tag;
  using difference_type = int;
  using value_type = Node*;
  using pointer = Node**;
  using reference = Node*&;

  Node* operator*() const { return current_->from(); }
  bool operator==(const const_iterator& other) const {
    return other.current_ == current_;
  }
  bool operator!=(const const_iterator& other) const {
    return other.current_ != current_;
  }
  const_iterator& operator++() {
    DCHECK_NOT_NULL(current_);
    // Checking no use gets mutated while iterating through them, a potential
    // very tricky cause of bug.
    current_ = current_->next;
#ifdef DEBUG
    DCHECK_EQ(current_, next_);
    next_ = current_ ? current_->next : nullptr;
#endif
    return *this;
  }
  const_iterator operator++(int);

 private:
  friend class Node::Uses;

  const_iterator() : current_(nullptr) {}
  explicit const_iterator(Node* node)
      : current_(node->first_use_)
#ifdef DEBUG
        ,
        next_(current_ ? current_->next : nullptr)
#endif
  {
  }

  Node::Use* current_;
#ifdef DEBUG
  Node::Use* next_;
#endif
};


Node::Uses::const_iterator Node::Uses::begin() const {
  return const_iterator(this->node_);
}


Node::Uses::const_iterator Node::Uses::end() const { return const_iterator(); }

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_NODE_H_
