11cb0ef41Sopenharmony_ci// Copyright 2013 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_COMPILER_NODE_H_
61cb0ef41Sopenharmony_ci#define V8_COMPILER_NODE_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/common/globals.h"
91cb0ef41Sopenharmony_ci#include "src/compiler/graph-zone-traits.h"
101cb0ef41Sopenharmony_ci#include "src/compiler/opcodes.h"
111cb0ef41Sopenharmony_ci#include "src/compiler/operator.h"
121cb0ef41Sopenharmony_ci#include "src/compiler/types.h"
131cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h"
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cinamespace v8 {
161cb0ef41Sopenharmony_cinamespace internal {
171cb0ef41Sopenharmony_cinamespace compiler {
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci// Forward declarations.
201cb0ef41Sopenharmony_ciclass Edge;
211cb0ef41Sopenharmony_ciclass Graph;
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// Marks are used during traversal of the graph to distinguish states of nodes.
251cb0ef41Sopenharmony_ci// Each node has a mark which is a monotonically increasing integer, and a
261cb0ef41Sopenharmony_ci// {NodeMarker} has a range of values that indicate states of a node.
271cb0ef41Sopenharmony_ciusing Mark = uint32_t;
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci// NodeIds are identifying numbers for nodes that can be used to index auxiliary
301cb0ef41Sopenharmony_ci// out-of-line data associated with each node.
311cb0ef41Sopenharmony_ciusing NodeId = uint32_t;
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci// A Node is the basic primitive of graphs. Nodes are chained together by
341cb0ef41Sopenharmony_ci// input/use chains but by default otherwise contain only an identifying number
351cb0ef41Sopenharmony_ci// which specific applications of graphs and nodes can use to index auxiliary
361cb0ef41Sopenharmony_ci// out-of-line data, especially transient data.
371cb0ef41Sopenharmony_ci//
381cb0ef41Sopenharmony_ci// In addition Nodes only contain a mutable Operator that may change during
391cb0ef41Sopenharmony_ci// compilation, e.g. during lowering passes. Other information that needs to be
401cb0ef41Sopenharmony_ci// associated with Nodes during compilation must be stored out-of-line indexed
411cb0ef41Sopenharmony_ci// by the Node's id.
421cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE Node final {
431cb0ef41Sopenharmony_ci public:
441cb0ef41Sopenharmony_ci  static Node* New(Zone* zone, NodeId id, const Operator* op, int input_count,
451cb0ef41Sopenharmony_ci                   Node* const* inputs, bool has_extensible_inputs);
461cb0ef41Sopenharmony_ci  static Node* Clone(Zone* zone, NodeId id, const Node* node);
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  inline bool IsDead() const;
491cb0ef41Sopenharmony_ci  void Kill();
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  const Operator* op() const { return op_; }
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  constexpr IrOpcode::Value opcode() const {
541cb0ef41Sopenharmony_ci    DCHECK_GE(IrOpcode::kLast, op_->opcode());
551cb0ef41Sopenharmony_ci    return static_cast<IrOpcode::Value>(op_->opcode());
561cb0ef41Sopenharmony_ci  }
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  NodeId id() const { return IdField::decode(bit_field_); }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  int InputCount() const {
611cb0ef41Sopenharmony_ci    return has_inline_inputs() ? InlineCountField::decode(bit_field_)
621cb0ef41Sopenharmony_ci                               : outline_inputs()->count_;
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci#ifdef DEBUG
661cb0ef41Sopenharmony_ci  void Verify();
671cb0ef41Sopenharmony_ci#else
681cb0ef41Sopenharmony_ci  inline void Verify() {}
691cb0ef41Sopenharmony_ci#endif
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  Node* InputAt(int index) const {
721cb0ef41Sopenharmony_ci    DCHECK_LE(0, index);
731cb0ef41Sopenharmony_ci    DCHECK_LT(index, InputCount());
741cb0ef41Sopenharmony_ci    return *GetInputPtrConst(index);
751cb0ef41Sopenharmony_ci  }
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  void ReplaceInput(int index, Node* new_to) {
781cb0ef41Sopenharmony_ci    DCHECK_LE(0, index);
791cb0ef41Sopenharmony_ci    DCHECK_LT(index, InputCount());
801cb0ef41Sopenharmony_ci    ZoneNodePtr* input_ptr = GetInputPtr(index);
811cb0ef41Sopenharmony_ci    Node* old_to = *input_ptr;
821cb0ef41Sopenharmony_ci    if (old_to != new_to) {
831cb0ef41Sopenharmony_ci      Use* use = GetUsePtr(index);
841cb0ef41Sopenharmony_ci      if (old_to) old_to->RemoveUse(use);
851cb0ef41Sopenharmony_ci      *input_ptr = new_to;
861cb0ef41Sopenharmony_ci      if (new_to) new_to->AppendUse(use);
871cb0ef41Sopenharmony_ci    }
881cb0ef41Sopenharmony_ci  }
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  void AppendInput(Zone* zone, Node* new_to);
911cb0ef41Sopenharmony_ci  void InsertInput(Zone* zone, int index, Node* new_to);
921cb0ef41Sopenharmony_ci  void InsertInputs(Zone* zone, int index, int count);
931cb0ef41Sopenharmony_ci  // Returns the removed input.
941cb0ef41Sopenharmony_ci  Node* RemoveInput(int index);
951cb0ef41Sopenharmony_ci  void NullAllInputs();
961cb0ef41Sopenharmony_ci  void TrimInputCount(int new_input_count);
971cb0ef41Sopenharmony_ci  // Can trim, extend by appending new inputs, or do nothing.
981cb0ef41Sopenharmony_ci  void EnsureInputCount(Zone* zone, int new_input_count);
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  int UseCount() const;
1011cb0ef41Sopenharmony_ci  void ReplaceUses(Node* replace_to);
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  class InputEdges;
1041cb0ef41Sopenharmony_ci  inline InputEdges input_edges();
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  class Inputs;
1071cb0ef41Sopenharmony_ci  inline Inputs inputs() const;
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  class UseEdges final {
1101cb0ef41Sopenharmony_ci   public:
1111cb0ef41Sopenharmony_ci    using value_type = Edge;
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci    class iterator;
1141cb0ef41Sopenharmony_ci    inline iterator begin() const;
1151cb0ef41Sopenharmony_ci    inline iterator end() const;
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci    bool empty() const;
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci    explicit UseEdges(Node* node) : node_(node) {}
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci   private:
1221cb0ef41Sopenharmony_ci    Node* node_;
1231cb0ef41Sopenharmony_ci  };
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  UseEdges use_edges() { return UseEdges(this); }
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  class V8_EXPORT_PRIVATE Uses final {
1281cb0ef41Sopenharmony_ci   public:
1291cb0ef41Sopenharmony_ci    using value_type = Node*;
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci    class const_iterator;
1321cb0ef41Sopenharmony_ci    inline const_iterator begin() const;
1331cb0ef41Sopenharmony_ci    inline const_iterator end() const;
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci    bool empty() const;
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci    explicit Uses(Node* node) : node_(node) {}
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci   private:
1401cb0ef41Sopenharmony_ci    Node* node_;
1411cb0ef41Sopenharmony_ci  };
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  Uses uses() { return Uses(this); }
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  // Returns true if {owner} is the only user of {this} node.
1461cb0ef41Sopenharmony_ci  bool OwnedBy(Node const* owner) const;
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  // Returns true if {owner1} and {owner2} are the only users of {this} node.
1491cb0ef41Sopenharmony_ci  bool OwnedBy(Node const* owner1, Node const* owner2) const;
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  void Print() const { Print(1); }
1521cb0ef41Sopenharmony_ci  void Print(int depth) const;
1531cb0ef41Sopenharmony_ci  void Print(std::ostream&, int depth = 1) const;
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci private:
1561cb0ef41Sopenharmony_ci  template <typename NodePtrT>
1571cb0ef41Sopenharmony_ci  inline static Node* NewImpl(Zone* zone, NodeId id, const Operator* op,
1581cb0ef41Sopenharmony_ci                              int input_count, NodePtrT const* inputs,
1591cb0ef41Sopenharmony_ci                              bool has_extensible_inputs);
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  struct Use;
1621cb0ef41Sopenharmony_ci  using ZoneUsePtr = GraphZoneTraits::Ptr<Use>;
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  // Out of line storage for inputs when the number of inputs overflowed the
1651cb0ef41Sopenharmony_ci  // capacity of the inline-allocated space.
1661cb0ef41Sopenharmony_ci  struct OutOfLineInputs {
1671cb0ef41Sopenharmony_ci    ZoneNodePtr node_;
1681cb0ef41Sopenharmony_ci    int count_;
1691cb0ef41Sopenharmony_ci    int capacity_;
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci    // Inputs are allocated right behind the OutOfLineInputs instance.
1721cb0ef41Sopenharmony_ci    inline ZoneNodePtr* inputs();
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci    static OutOfLineInputs* New(Zone* zone, int capacity);
1751cb0ef41Sopenharmony_ci    void ExtractFrom(Use* use_ptr, ZoneNodePtr* input_ptr, int count);
1761cb0ef41Sopenharmony_ci  };
1771cb0ef41Sopenharmony_ci  using ZoneOutOfLineInputsPtr = GraphZoneTraits::Ptr<OutOfLineInputs>;
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  // A link in the use chain for a node. Every input {i} to a node {n} has an
1801cb0ef41Sopenharmony_ci  // associated {Use} which is linked into the use chain of the {i} node.
1811cb0ef41Sopenharmony_ci  struct Use {
1821cb0ef41Sopenharmony_ci    ZoneUsePtr next;
1831cb0ef41Sopenharmony_ci    ZoneUsePtr prev;
1841cb0ef41Sopenharmony_ci    uint32_t bit_field_;
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci    int input_index() const { return InputIndexField::decode(bit_field_); }
1871cb0ef41Sopenharmony_ci    bool is_inline_use() const { return InlineField::decode(bit_field_); }
1881cb0ef41Sopenharmony_ci    ZoneNodePtr* input_ptr() {
1891cb0ef41Sopenharmony_ci      int index = input_index();
1901cb0ef41Sopenharmony_ci      Use* start = this + 1 + index;
1911cb0ef41Sopenharmony_ci      ZoneNodePtr* inputs =
1921cb0ef41Sopenharmony_ci          is_inline_use() ? reinterpret_cast<Node*>(start)->inline_inputs()
1931cb0ef41Sopenharmony_ci                          : reinterpret_cast<OutOfLineInputs*>(start)->inputs();
1941cb0ef41Sopenharmony_ci      return &inputs[index];
1951cb0ef41Sopenharmony_ci    }
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci    Node* from() {
1981cb0ef41Sopenharmony_ci      Use* start = this + 1 + input_index();
1991cb0ef41Sopenharmony_ci      return is_inline_use() ? reinterpret_cast<Node*>(start)
2001cb0ef41Sopenharmony_ci                             : reinterpret_cast<OutOfLineInputs*>(start)->node_;
2011cb0ef41Sopenharmony_ci    }
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci    using InlineField = base::BitField<bool, 0, 1>;
2041cb0ef41Sopenharmony_ci    using InputIndexField = base::BitField<unsigned, 1, 31>;
2051cb0ef41Sopenharmony_ci  };
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci  //============================================================================
2081cb0ef41Sopenharmony_ci  //== Memory layout ===========================================================
2091cb0ef41Sopenharmony_ci  //============================================================================
2101cb0ef41Sopenharmony_ci  // Saving space for big graphs is important. We use a memory layout trick to
2111cb0ef41Sopenharmony_ci  // be able to map {Node} objects to {Use} objects and vice-versa in a
2121cb0ef41Sopenharmony_ci  // space-efficient manner.
2131cb0ef41Sopenharmony_ci  //
2141cb0ef41Sopenharmony_ci  // {Use} links are laid out in memory directly before a {Node}, followed by
2151cb0ef41Sopenharmony_ci  // direct pointers to input {Nodes}.
2161cb0ef41Sopenharmony_ci  //
2171cb0ef41Sopenharmony_ci  // inline case:
2181cb0ef41Sopenharmony_ci  // |Use #N  |Use #N-1|...|Use #1  |Use #0  |Node xxxx |I#0|I#1|...|I#N-1|I#N|
2191cb0ef41Sopenharmony_ci  //          ^                              ^                  ^
2201cb0ef41Sopenharmony_ci  //          + Use                          + Node             + Input
2211cb0ef41Sopenharmony_ci  //
2221cb0ef41Sopenharmony_ci  // Since every {Use} instance records its {input_index}, pointer arithmetic
2231cb0ef41Sopenharmony_ci  // can compute the {Node}.
2241cb0ef41Sopenharmony_ci  //
2251cb0ef41Sopenharmony_ci  // out-of-line case:
2261cb0ef41Sopenharmony_ci  //     |Node xxxx |
2271cb0ef41Sopenharmony_ci  //     ^       + outline ------------------+
2281cb0ef41Sopenharmony_ci  //     +----------------------------------------+
2291cb0ef41Sopenharmony_ci  //                                         |    |
2301cb0ef41Sopenharmony_ci  //                                         v    | node
2311cb0ef41Sopenharmony_ci  // |Use #N  |Use #N-1|...|Use #1  |Use #0  |OOL xxxxx |I#0|I#1|...|I#N-1|I#N|
2321cb0ef41Sopenharmony_ci  //          ^                                                 ^
2331cb0ef41Sopenharmony_ci  //          + Use                                             + Input
2341cb0ef41Sopenharmony_ci  //
2351cb0ef41Sopenharmony_ci  // Out-of-line storage of input lists is needed if appending an input to
2361cb0ef41Sopenharmony_ci  // a node exceeds the maximum inline capacity.
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci  Node(NodeId id, const Operator* op, int inline_count, int inline_capacity);
2391cb0ef41Sopenharmony_ci  Node(const Node&) = delete;
2401cb0ef41Sopenharmony_ci  Node& operator=(const Node&) = delete;
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci  inline Address inputs_location() const;
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci  ZoneNodePtr* inline_inputs() const {
2451cb0ef41Sopenharmony_ci    return reinterpret_cast<ZoneNodePtr*>(inputs_location());
2461cb0ef41Sopenharmony_ci  }
2471cb0ef41Sopenharmony_ci  OutOfLineInputs* outline_inputs() const {
2481cb0ef41Sopenharmony_ci    return *reinterpret_cast<ZoneOutOfLineInputsPtr*>(inputs_location());
2491cb0ef41Sopenharmony_ci  }
2501cb0ef41Sopenharmony_ci  void set_outline_inputs(OutOfLineInputs* outline) {
2511cb0ef41Sopenharmony_ci    *reinterpret_cast<ZoneOutOfLineInputsPtr*>(inputs_location()) = outline;
2521cb0ef41Sopenharmony_ci  }
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  ZoneNodePtr const* GetInputPtrConst(int input_index) const {
2551cb0ef41Sopenharmony_ci    return has_inline_inputs() ? &(inline_inputs()[input_index])
2561cb0ef41Sopenharmony_ci                               : &(outline_inputs()->inputs()[input_index]);
2571cb0ef41Sopenharmony_ci  }
2581cb0ef41Sopenharmony_ci  ZoneNodePtr* GetInputPtr(int input_index) {
2591cb0ef41Sopenharmony_ci    return has_inline_inputs() ? &(inline_inputs()[input_index])
2601cb0ef41Sopenharmony_ci                               : &(outline_inputs()->inputs()[input_index]);
2611cb0ef41Sopenharmony_ci  }
2621cb0ef41Sopenharmony_ci  Use* GetUsePtr(int input_index) {
2631cb0ef41Sopenharmony_ci    Use* ptr = has_inline_inputs() ? reinterpret_cast<Use*>(this)
2641cb0ef41Sopenharmony_ci                                   : reinterpret_cast<Use*>(outline_inputs());
2651cb0ef41Sopenharmony_ci    return &ptr[-1 - input_index];
2661cb0ef41Sopenharmony_ci  }
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci  void AppendUse(Use* use);
2691cb0ef41Sopenharmony_ci  void RemoveUse(Use* use);
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci  void* operator new(size_t, void* location) { return location; }
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci  // Only NodeProperties should manipulate the op.
2741cb0ef41Sopenharmony_ci  void set_op(const Operator* op) { op_ = op; }
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  // Only NodeProperties should manipulate the type.
2771cb0ef41Sopenharmony_ci  Type type() const { return type_; }
2781cb0ef41Sopenharmony_ci  void set_type(Type type) { type_ = type; }
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci  // Only NodeMarkers should manipulate the marks on nodes.
2811cb0ef41Sopenharmony_ci  Mark mark() const { return mark_; }
2821cb0ef41Sopenharmony_ci  void set_mark(Mark mark) { mark_ = mark; }
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci  inline bool has_inline_inputs() const {
2851cb0ef41Sopenharmony_ci    return InlineCountField::decode(bit_field_) != kOutlineMarker;
2861cb0ef41Sopenharmony_ci  }
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci  void ClearInputs(int start, int count);
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  using IdField = base::BitField<NodeId, 0, 24>;
2911cb0ef41Sopenharmony_ci  using InlineCountField = base::BitField<unsigned, 24, 4>;
2921cb0ef41Sopenharmony_ci  using InlineCapacityField = base::BitField<unsigned, 28, 4>;
2931cb0ef41Sopenharmony_ci  static const int kOutlineMarker = InlineCountField::kMax;
2941cb0ef41Sopenharmony_ci  static const int kMaxInlineCapacity = InlineCapacityField::kMax - 1;
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci  const Operator* op_;
2971cb0ef41Sopenharmony_ci  Type type_;
2981cb0ef41Sopenharmony_ci  Mark mark_;
2991cb0ef41Sopenharmony_ci  uint32_t bit_field_;
3001cb0ef41Sopenharmony_ci  ZoneUsePtr first_use_;
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci  friend class Edge;
3031cb0ef41Sopenharmony_ci  friend class NodeMarkerBase;
3041cb0ef41Sopenharmony_ci  friend class NodeProperties;
3051cb0ef41Sopenharmony_ci};
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ciAddress Node::inputs_location() const {
3081cb0ef41Sopenharmony_ci  return reinterpret_cast<Address>(this) + sizeof(Node);
3091cb0ef41Sopenharmony_ci}
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ciZoneNodePtr* Node::OutOfLineInputs::inputs() {
3121cb0ef41Sopenharmony_ci  return reinterpret_cast<ZoneNodePtr*>(reinterpret_cast<Address>(this) +
3131cb0ef41Sopenharmony_ci                                        sizeof(Node::OutOfLineInputs));
3141cb0ef41Sopenharmony_ci}
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const Node& n);
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci// Base class for node wrappers.
3191cb0ef41Sopenharmony_ciclass NodeWrapper {
3201cb0ef41Sopenharmony_ci public:
3211cb0ef41Sopenharmony_ci  explicit constexpr NodeWrapper(Node* node) : node_(node) {}
3221cb0ef41Sopenharmony_ci  operator Node*() const { return node_; }
3231cb0ef41Sopenharmony_ci  Node* operator->() const { return node_; }
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci protected:
3261cb0ef41Sopenharmony_ci  Node* node() const { return node_; }
3271cb0ef41Sopenharmony_ci  void set_node(Node* node) {
3281cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(node);
3291cb0ef41Sopenharmony_ci    node_ = node;
3301cb0ef41Sopenharmony_ci  }
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_ci private:
3331cb0ef41Sopenharmony_ci  Node* node_;
3341cb0ef41Sopenharmony_ci};
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ci// Wrapper classes for special node/edge types (effect, control, frame states).
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ciclass Effect : public NodeWrapper {
3391cb0ef41Sopenharmony_ci public:
3401cb0ef41Sopenharmony_ci  explicit constexpr Effect(Node* node) : NodeWrapper(node) {
3411cb0ef41Sopenharmony_ci    // TODO(jgruber): Remove the End special case.
3421cb0ef41Sopenharmony_ci    SLOW_DCHECK(node == nullptr || node->op()->opcode() == IrOpcode::kEnd ||
3431cb0ef41Sopenharmony_ci                node->op()->EffectOutputCount() > 0);
3441cb0ef41Sopenharmony_ci  }
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci  // Support the common `Node* x = effect = ...` pattern.
3471cb0ef41Sopenharmony_ci  Node* operator=(Node* value) {
3481cb0ef41Sopenharmony_ci    DCHECK_GT(value->op()->EffectOutputCount(), 0);
3491cb0ef41Sopenharmony_ci    set_node(value);
3501cb0ef41Sopenharmony_ci    return value;
3511cb0ef41Sopenharmony_ci  }
3521cb0ef41Sopenharmony_ci};
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ciclass Control : public NodeWrapper {
3551cb0ef41Sopenharmony_ci public:
3561cb0ef41Sopenharmony_ci  explicit constexpr Control(Node* node) : NodeWrapper(node) {
3571cb0ef41Sopenharmony_ci    // TODO(jgruber): Remove the End special case.
3581cb0ef41Sopenharmony_ci    SLOW_DCHECK(node == nullptr || node->opcode() == IrOpcode::kEnd ||
3591cb0ef41Sopenharmony_ci                node->op()->ControlOutputCount() > 0);
3601cb0ef41Sopenharmony_ci  }
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci  // Support the common `Node* x = control = ...` pattern.
3631cb0ef41Sopenharmony_ci  Node* operator=(Node* value) {
3641cb0ef41Sopenharmony_ci    DCHECK_GT(value->op()->ControlOutputCount(), 0);
3651cb0ef41Sopenharmony_ci    set_node(value);
3661cb0ef41Sopenharmony_ci    return value;
3671cb0ef41Sopenharmony_ci  }
3681cb0ef41Sopenharmony_ci};
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci// Typedefs to shorten commonly used Node containers.
3711cb0ef41Sopenharmony_ciusing NodeDeque = ZoneDeque<Node*>;
3721cb0ef41Sopenharmony_ciusing NodeSet = ZoneSet<Node*>;
3731cb0ef41Sopenharmony_ciusing NodeVector = ZoneVector<Node*>;
3741cb0ef41Sopenharmony_ciusing NodeVectorVector = ZoneVector<NodeVector>;
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ciclass Node::InputEdges final {
3771cb0ef41Sopenharmony_ci public:
3781cb0ef41Sopenharmony_ci  using value_type = Edge;
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci  class iterator;
3811cb0ef41Sopenharmony_ci  inline iterator begin() const;
3821cb0ef41Sopenharmony_ci  inline iterator end() const;
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  bool empty() const { return count_ == 0; }
3851cb0ef41Sopenharmony_ci  int count() const { return count_; }
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci  inline value_type operator[](int index) const;
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci  InputEdges(ZoneNodePtr* input_root, Use* use_root, int count)
3901cb0ef41Sopenharmony_ci      : input_root_(input_root), use_root_(use_root), count_(count) {}
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci private:
3931cb0ef41Sopenharmony_ci  ZoneNodePtr* input_root_;
3941cb0ef41Sopenharmony_ci  Use* use_root_;
3951cb0ef41Sopenharmony_ci  int count_;
3961cb0ef41Sopenharmony_ci};
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE Node::Inputs final {
3991cb0ef41Sopenharmony_ci public:
4001cb0ef41Sopenharmony_ci  using value_type = Node*;
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  class const_iterator;
4031cb0ef41Sopenharmony_ci  inline const_iterator begin() const;
4041cb0ef41Sopenharmony_ci  inline const_iterator end() const;
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  bool empty() const { return count_ == 0; }
4071cb0ef41Sopenharmony_ci  int count() const { return count_; }
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  inline value_type operator[](int index) const;
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci  explicit Inputs(ZoneNodePtr const* input_root, int count)
4121cb0ef41Sopenharmony_ci      : input_root_(input_root), count_(count) {}
4131cb0ef41Sopenharmony_ci
4141cb0ef41Sopenharmony_ci private:
4151cb0ef41Sopenharmony_ci  ZoneNodePtr const* input_root_;
4161cb0ef41Sopenharmony_ci  int count_;
4171cb0ef41Sopenharmony_ci};
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci// An encapsulation for information associated with a single use of node as a
4201cb0ef41Sopenharmony_ci// input from another node, allowing access to both the defining node and
4211cb0ef41Sopenharmony_ci// the node having the input.
4221cb0ef41Sopenharmony_ciclass Edge final {
4231cb0ef41Sopenharmony_ci public:
4241cb0ef41Sopenharmony_ci  Node* from() const { return use_->from(); }
4251cb0ef41Sopenharmony_ci  Node* to() const { return *input_ptr_; }
4261cb0ef41Sopenharmony_ci  int index() const {
4271cb0ef41Sopenharmony_ci    int const index = use_->input_index();
4281cb0ef41Sopenharmony_ci    DCHECK_LT(index, use_->from()->InputCount());
4291cb0ef41Sopenharmony_ci    return index;
4301cb0ef41Sopenharmony_ci  }
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci  bool operator==(const Edge& other) { return input_ptr_ == other.input_ptr_; }
4331cb0ef41Sopenharmony_ci  bool operator!=(const Edge& other) { return !(*this == other); }
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_ci  void UpdateTo(Node* new_to) {
4361cb0ef41Sopenharmony_ci    Node* old_to = *input_ptr_;
4371cb0ef41Sopenharmony_ci    if (old_to != new_to) {
4381cb0ef41Sopenharmony_ci      if (old_to) old_to->RemoveUse(use_);
4391cb0ef41Sopenharmony_ci      *input_ptr_ = new_to;
4401cb0ef41Sopenharmony_ci      if (new_to) new_to->AppendUse(use_);
4411cb0ef41Sopenharmony_ci    }
4421cb0ef41Sopenharmony_ci  }
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ci private:
4451cb0ef41Sopenharmony_ci  friend class Node::UseEdges::iterator;
4461cb0ef41Sopenharmony_ci  friend class Node::InputEdges;
4471cb0ef41Sopenharmony_ci  friend class Node::InputEdges::iterator;
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ci  Edge(Node::Use* use, ZoneNodePtr* input_ptr)
4501cb0ef41Sopenharmony_ci      : use_(use), input_ptr_(input_ptr) {
4511cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(use);
4521cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(input_ptr);
4531cb0ef41Sopenharmony_ci    DCHECK_EQ(input_ptr, use->input_ptr());
4541cb0ef41Sopenharmony_ci  }
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  Node::Use* use_;
4571cb0ef41Sopenharmony_ci  ZoneNodePtr* input_ptr_;
4581cb0ef41Sopenharmony_ci};
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_cibool Node::IsDead() const {
4611cb0ef41Sopenharmony_ci  Node::Inputs inputs = this->inputs();
4621cb0ef41Sopenharmony_ci  return inputs.count() > 0 && inputs[0] == nullptr;
4631cb0ef41Sopenharmony_ci}
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ciNode::InputEdges Node::input_edges() {
4661cb0ef41Sopenharmony_ci  int inline_count = InlineCountField::decode(bit_field_);
4671cb0ef41Sopenharmony_ci  if (inline_count != kOutlineMarker) {
4681cb0ef41Sopenharmony_ci    return InputEdges(inline_inputs(), reinterpret_cast<Use*>(this) - 1,
4691cb0ef41Sopenharmony_ci                      inline_count);
4701cb0ef41Sopenharmony_ci  } else {
4711cb0ef41Sopenharmony_ci    return InputEdges(outline_inputs()->inputs(),
4721cb0ef41Sopenharmony_ci                      reinterpret_cast<Use*>(outline_inputs()) - 1,
4731cb0ef41Sopenharmony_ci                      outline_inputs()->count_);
4741cb0ef41Sopenharmony_ci  }
4751cb0ef41Sopenharmony_ci}
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ciNode::Inputs Node::inputs() const {
4781cb0ef41Sopenharmony_ci  int inline_count = InlineCountField::decode(bit_field_);
4791cb0ef41Sopenharmony_ci  if (inline_count != kOutlineMarker) {
4801cb0ef41Sopenharmony_ci    return Inputs(inline_inputs(), inline_count);
4811cb0ef41Sopenharmony_ci  } else {
4821cb0ef41Sopenharmony_ci    return Inputs(outline_inputs()->inputs(), outline_inputs()->count_);
4831cb0ef41Sopenharmony_ci  }
4841cb0ef41Sopenharmony_ci}
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_ci// A forward iterator to visit the edges for the input dependencies of a node.
4871cb0ef41Sopenharmony_ciclass Node::InputEdges::iterator final {
4881cb0ef41Sopenharmony_ci public:
4891cb0ef41Sopenharmony_ci  using iterator_category = std::forward_iterator_tag;
4901cb0ef41Sopenharmony_ci  using difference_type = std::ptrdiff_t;
4911cb0ef41Sopenharmony_ci  using value_type = Edge;
4921cb0ef41Sopenharmony_ci  using pointer = Edge*;
4931cb0ef41Sopenharmony_ci  using reference = Edge&;
4941cb0ef41Sopenharmony_ci
4951cb0ef41Sopenharmony_ci  iterator() : use_(nullptr), input_ptr_(nullptr) {}
4961cb0ef41Sopenharmony_ci  iterator(const iterator& other) = default;
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_ci  Edge operator*() const { return Edge(use_, input_ptr_); }
4991cb0ef41Sopenharmony_ci  bool operator==(const iterator& other) const {
5001cb0ef41Sopenharmony_ci    return input_ptr_ == other.input_ptr_;
5011cb0ef41Sopenharmony_ci  }
5021cb0ef41Sopenharmony_ci  bool operator!=(const iterator& other) const { return !(*this == other); }
5031cb0ef41Sopenharmony_ci  iterator& operator++() {
5041cb0ef41Sopenharmony_ci    input_ptr_++;
5051cb0ef41Sopenharmony_ci    use_--;
5061cb0ef41Sopenharmony_ci    return *this;
5071cb0ef41Sopenharmony_ci  }
5081cb0ef41Sopenharmony_ci  iterator operator++(int);
5091cb0ef41Sopenharmony_ci  iterator& operator+=(difference_type offset) {
5101cb0ef41Sopenharmony_ci    input_ptr_ += offset;
5111cb0ef41Sopenharmony_ci    use_ -= offset;
5121cb0ef41Sopenharmony_ci    return *this;
5131cb0ef41Sopenharmony_ci  }
5141cb0ef41Sopenharmony_ci  iterator operator+(difference_type offset) const {
5151cb0ef41Sopenharmony_ci    return iterator(use_ - offset, input_ptr_ + offset);
5161cb0ef41Sopenharmony_ci  }
5171cb0ef41Sopenharmony_ci  difference_type operator-(const iterator& other) const {
5181cb0ef41Sopenharmony_ci    return input_ptr_ - other.input_ptr_;
5191cb0ef41Sopenharmony_ci  }
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ci private:
5221cb0ef41Sopenharmony_ci  friend class Node;
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci  explicit iterator(Use* use, ZoneNodePtr* input_ptr)
5251cb0ef41Sopenharmony_ci      : use_(use), input_ptr_(input_ptr) {}
5261cb0ef41Sopenharmony_ci
5271cb0ef41Sopenharmony_ci  Use* use_;
5281cb0ef41Sopenharmony_ci  ZoneNodePtr* input_ptr_;
5291cb0ef41Sopenharmony_ci};
5301cb0ef41Sopenharmony_ci
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_ciNode::InputEdges::iterator Node::InputEdges::begin() const {
5331cb0ef41Sopenharmony_ci  return Node::InputEdges::iterator(use_root_, input_root_);
5341cb0ef41Sopenharmony_ci}
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_ciNode::InputEdges::iterator Node::InputEdges::end() const {
5381cb0ef41Sopenharmony_ci  return Node::InputEdges::iterator(use_root_ - count_, input_root_ + count_);
5391cb0ef41Sopenharmony_ci}
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ciEdge Node::InputEdges::operator[](int index) const {
5421cb0ef41Sopenharmony_ci  return Edge(use_root_ + index, input_root_ + index);
5431cb0ef41Sopenharmony_ci}
5441cb0ef41Sopenharmony_ci
5451cb0ef41Sopenharmony_ci// A forward iterator to visit the inputs of a node.
5461cb0ef41Sopenharmony_ciclass Node::Inputs::const_iterator final {
5471cb0ef41Sopenharmony_ci public:
5481cb0ef41Sopenharmony_ci  using iterator_category = std::forward_iterator_tag;
5491cb0ef41Sopenharmony_ci  using difference_type = std::ptrdiff_t;
5501cb0ef41Sopenharmony_ci  using value_type = Node*;
5511cb0ef41Sopenharmony_ci  using pointer = const value_type*;
5521cb0ef41Sopenharmony_ci  using reference = value_type&;
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  const_iterator(const const_iterator& other) = default;
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_ci  Node* operator*() const { return *input_ptr_; }
5571cb0ef41Sopenharmony_ci  bool operator==(const const_iterator& other) const {
5581cb0ef41Sopenharmony_ci    return input_ptr_ == other.input_ptr_;
5591cb0ef41Sopenharmony_ci  }
5601cb0ef41Sopenharmony_ci  bool operator!=(const const_iterator& other) const {
5611cb0ef41Sopenharmony_ci    return !(*this == other);
5621cb0ef41Sopenharmony_ci  }
5631cb0ef41Sopenharmony_ci  const_iterator& operator++() {
5641cb0ef41Sopenharmony_ci    ++input_ptr_;
5651cb0ef41Sopenharmony_ci    return *this;
5661cb0ef41Sopenharmony_ci  }
5671cb0ef41Sopenharmony_ci  const_iterator operator++(int);
5681cb0ef41Sopenharmony_ci  const_iterator& operator+=(difference_type offset) {
5691cb0ef41Sopenharmony_ci    input_ptr_ += offset;
5701cb0ef41Sopenharmony_ci    return *this;
5711cb0ef41Sopenharmony_ci  }
5721cb0ef41Sopenharmony_ci  const_iterator operator+(difference_type offset) const {
5731cb0ef41Sopenharmony_ci    return const_iterator(input_ptr_ + offset);
5741cb0ef41Sopenharmony_ci  }
5751cb0ef41Sopenharmony_ci  difference_type operator-(const const_iterator& other) const {
5761cb0ef41Sopenharmony_ci    return input_ptr_ - other.input_ptr_;
5771cb0ef41Sopenharmony_ci  }
5781cb0ef41Sopenharmony_ci
5791cb0ef41Sopenharmony_ci private:
5801cb0ef41Sopenharmony_ci  friend class Node::Inputs;
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci  explicit const_iterator(ZoneNodePtr const* input_ptr)
5831cb0ef41Sopenharmony_ci      : input_ptr_(input_ptr) {}
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ci  ZoneNodePtr const* input_ptr_;
5861cb0ef41Sopenharmony_ci};
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_ciNode::Inputs::const_iterator Node::Inputs::begin() const {
5901cb0ef41Sopenharmony_ci  return const_iterator(input_root_);
5911cb0ef41Sopenharmony_ci}
5921cb0ef41Sopenharmony_ci
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ciNode::Inputs::const_iterator Node::Inputs::end() const {
5951cb0ef41Sopenharmony_ci  return const_iterator(input_root_ + count_);
5961cb0ef41Sopenharmony_ci}
5971cb0ef41Sopenharmony_ci
5981cb0ef41Sopenharmony_ciNode* Node::Inputs::operator[](int index) const { return input_root_[index]; }
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ci// A forward iterator to visit the uses edges of a node.
6011cb0ef41Sopenharmony_ciclass Node::UseEdges::iterator final {
6021cb0ef41Sopenharmony_ci public:
6031cb0ef41Sopenharmony_ci  iterator(const iterator& other) = default;
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci  Edge operator*() const { return Edge(current_, current_->input_ptr()); }
6061cb0ef41Sopenharmony_ci  bool operator==(const iterator& other) const {
6071cb0ef41Sopenharmony_ci    return current_ == other.current_;
6081cb0ef41Sopenharmony_ci  }
6091cb0ef41Sopenharmony_ci  bool operator!=(const iterator& other) const { return !(*this == other); }
6101cb0ef41Sopenharmony_ci  iterator& operator++() {
6111cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(current_);
6121cb0ef41Sopenharmony_ci    current_ = next_;
6131cb0ef41Sopenharmony_ci    next_ = current_ ? static_cast<Node::Use*>(current_->next) : nullptr;
6141cb0ef41Sopenharmony_ci    return *this;
6151cb0ef41Sopenharmony_ci  }
6161cb0ef41Sopenharmony_ci  iterator operator++(int);
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ci private:
6191cb0ef41Sopenharmony_ci  friend class Node::UseEdges;
6201cb0ef41Sopenharmony_ci
6211cb0ef41Sopenharmony_ci  iterator() : current_(nullptr), next_(nullptr) {}
6221cb0ef41Sopenharmony_ci  explicit iterator(Node* node)
6231cb0ef41Sopenharmony_ci      : current_(node->first_use_),
6241cb0ef41Sopenharmony_ci        next_(current_ ? static_cast<Node::Use*>(current_->next) : nullptr) {}
6251cb0ef41Sopenharmony_ci
6261cb0ef41Sopenharmony_ci  Node::Use* current_;
6271cb0ef41Sopenharmony_ci  Node::Use* next_;
6281cb0ef41Sopenharmony_ci};
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci
6311cb0ef41Sopenharmony_ciNode::UseEdges::iterator Node::UseEdges::begin() const {
6321cb0ef41Sopenharmony_ci  return Node::UseEdges::iterator(this->node_);
6331cb0ef41Sopenharmony_ci}
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci
6361cb0ef41Sopenharmony_ciNode::UseEdges::iterator Node::UseEdges::end() const {
6371cb0ef41Sopenharmony_ci  return Node::UseEdges::iterator();
6381cb0ef41Sopenharmony_ci}
6391cb0ef41Sopenharmony_ci
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci// A forward iterator to visit the uses of a node.
6421cb0ef41Sopenharmony_ciclass Node::Uses::const_iterator final {
6431cb0ef41Sopenharmony_ci public:
6441cb0ef41Sopenharmony_ci  using iterator_category = std::forward_iterator_tag;
6451cb0ef41Sopenharmony_ci  using difference_type = int;
6461cb0ef41Sopenharmony_ci  using value_type = Node*;
6471cb0ef41Sopenharmony_ci  using pointer = Node**;
6481cb0ef41Sopenharmony_ci  using reference = Node*&;
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_ci  Node* operator*() const { return current_->from(); }
6511cb0ef41Sopenharmony_ci  bool operator==(const const_iterator& other) const {
6521cb0ef41Sopenharmony_ci    return other.current_ == current_;
6531cb0ef41Sopenharmony_ci  }
6541cb0ef41Sopenharmony_ci  bool operator!=(const const_iterator& other) const {
6551cb0ef41Sopenharmony_ci    return other.current_ != current_;
6561cb0ef41Sopenharmony_ci  }
6571cb0ef41Sopenharmony_ci  const_iterator& operator++() {
6581cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(current_);
6591cb0ef41Sopenharmony_ci    // Checking no use gets mutated while iterating through them, a potential
6601cb0ef41Sopenharmony_ci    // very tricky cause of bug.
6611cb0ef41Sopenharmony_ci    current_ = current_->next;
6621cb0ef41Sopenharmony_ci#ifdef DEBUG
6631cb0ef41Sopenharmony_ci    DCHECK_EQ(current_, next_);
6641cb0ef41Sopenharmony_ci    next_ = current_ ? current_->next : nullptr;
6651cb0ef41Sopenharmony_ci#endif
6661cb0ef41Sopenharmony_ci    return *this;
6671cb0ef41Sopenharmony_ci  }
6681cb0ef41Sopenharmony_ci  const_iterator operator++(int);
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci private:
6711cb0ef41Sopenharmony_ci  friend class Node::Uses;
6721cb0ef41Sopenharmony_ci
6731cb0ef41Sopenharmony_ci  const_iterator() : current_(nullptr) {}
6741cb0ef41Sopenharmony_ci  explicit const_iterator(Node* node)
6751cb0ef41Sopenharmony_ci      : current_(node->first_use_)
6761cb0ef41Sopenharmony_ci#ifdef DEBUG
6771cb0ef41Sopenharmony_ci        ,
6781cb0ef41Sopenharmony_ci        next_(current_ ? current_->next : nullptr)
6791cb0ef41Sopenharmony_ci#endif
6801cb0ef41Sopenharmony_ci  {
6811cb0ef41Sopenharmony_ci  }
6821cb0ef41Sopenharmony_ci
6831cb0ef41Sopenharmony_ci  Node::Use* current_;
6841cb0ef41Sopenharmony_ci#ifdef DEBUG
6851cb0ef41Sopenharmony_ci  Node::Use* next_;
6861cb0ef41Sopenharmony_ci#endif
6871cb0ef41Sopenharmony_ci};
6881cb0ef41Sopenharmony_ci
6891cb0ef41Sopenharmony_ci
6901cb0ef41Sopenharmony_ciNode::Uses::const_iterator Node::Uses::begin() const {
6911cb0ef41Sopenharmony_ci  return const_iterator(this->node_);
6921cb0ef41Sopenharmony_ci}
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ciNode::Uses::const_iterator Node::Uses::end() const { return const_iterator(); }
6961cb0ef41Sopenharmony_ci
6971cb0ef41Sopenharmony_ci}  // namespace compiler
6981cb0ef41Sopenharmony_ci}  // namespace internal
6991cb0ef41Sopenharmony_ci}  // namespace v8
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_ci#endif  // V8_COMPILER_NODE_H_
702