Clean up node iteration
authordanno <danno@chromium.org>
Tue, 2 Dec 2014 14:38:55 +0000 (06:38 -0800)
committerCommit bot <commit-bot@chromium.org>
Tue, 2 Dec 2014 14:38:58 +0000 (14:38 +0000)
- Create a first-class Edge type.
- Separate node and edge iterators
- Make iterators only responsible for iteration
- Make it possible to modify the use edge iterator while iterating.
- Add the ability to update inputs to Edges directly.

Review URL: https://codereview.chromium.org/765983002

Cr-Commit-Position: refs/heads/master@{#25616}

15 files changed:
src/compiler/change-lowering.cc
src/compiler/control-reducer.cc
src/compiler/generic-algorithm-inl.h
src/compiler/generic-algorithm.h
src/compiler/graph-visualizer.cc
src/compiler/instruction-selector.cc
src/compiler/js-inlining.cc
src/compiler/node-properties-inl.h
src/compiler/node-properties.h
src/compiler/node.h
src/compiler/scheduler.cc
src/compiler/simplified-lowering.cc
src/compiler/verifier.cc
test/cctest/compiler/test-control-reducer.cc
test/cctest/compiler/test-node.cc

index a4e081a..c5cdc27 100644 (file)
@@ -199,9 +199,9 @@ namespace {
 bool CanCover(Node* value, IrOpcode::Value opcode) {
   if (value->opcode() != opcode) return false;
   bool first = true;
-  for (auto i = value->uses().begin(); i != value->uses().end(); ++i) {
-    if (NodeProperties::IsEffectEdge(i.edge())) continue;
-    DCHECK(NodeProperties::IsValueEdge(i.edge()));
+  for (Edge const edge : value->use_edges()) {
+    if (NodeProperties::IsEffectEdge(edge)) continue;
+    DCHECK(NodeProperties::IsValueEdge(edge));
     if (!first) return false;
     first = false;
   }
@@ -236,11 +236,9 @@ Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) {
     Node* phi1 = d1.Phi(kMachFloat64, phi2, ChangeSmiToFloat64(object));
     Node* ephi1 = d1.EffectPhi(number, effect);
 
-    for (auto i = value->uses().begin(); i != value->uses().end();) {
-      if (NodeProperties::IsEffectEdge(i.edge())) {
-        i.UpdateToAndIncrement(ephi1);
-      } else {
-        ++i;
+    for (Edge edge : value->use_edges()) {
+      if (NodeProperties::IsEffectEdge(edge)) {
+        edge.UpdateTo(ephi1);
       }
     }
     return Replace(phi1);
index 5068385..236ce4b 100644 (file)
@@ -237,14 +237,13 @@ class ControlReducerImpl {
     // Remove dead->live edges.
     for (size_t j = 0; j < nodes.size(); j++) {
       Node* node = nodes[j];
-      for (UseIter i = node->uses().begin(); i != node->uses().end();) {
-        if (!marked.IsReachableFromEnd(*i)) {
-          TRACE(("DeadLink: #%d:%s(%d) -> #%d:%s\n", (*i)->id(),
-                 (*i)->op()->mnemonic(), i.index(), node->id(),
+      for (Edge edge : node->use_edges()) {
+        Node* use = edge.from();
+        if (!marked.IsReachableFromEnd(use)) {
+          TRACE(("DeadLink: #%d:%s(%d) -> #%d:%s\n", use->id(),
+                 use->op()->mnemonic(), edge.index(), node->id(),
                  node->op()->mnemonic()));
-          i.UpdateToAndIncrement(NULL);
-        } else {
-          ++i;
+          edge.UpdateTo(NULL);
         }
       }
     }
@@ -473,18 +472,16 @@ class ControlReducerImpl {
 
     // Replace IfTrue and IfFalse projections from this branch.
     Node* control = NodeProperties::GetControlInput(node);
-    for (UseIter i = node->uses().begin(); i != node->uses().end();) {
-      Node* to = *i;
-      if (to->opcode() == IrOpcode::kIfTrue) {
-        TRACE(("  IfTrue: #%d:%s\n", to->id(), to->op()->mnemonic()));
-        i.UpdateToAndIncrement(NULL);
-        ReplaceNode(to, (result == kTrue) ? control : dead());
-      } else if (to->opcode() == IrOpcode::kIfFalse) {
-        TRACE(("  IfFalse: #%d:%s\n", to->id(), to->op()->mnemonic()));
-        i.UpdateToAndIncrement(NULL);
-        ReplaceNode(to, (result == kTrue) ? dead() : control);
-      } else {
-        ++i;
+    for (Edge edge : node->use_edges()) {
+      Node* use = edge.from();
+      if (use->opcode() == IrOpcode::kIfTrue) {
+        TRACE(("  IfTrue: #%d:%s\n", use->id(), use->op()->mnemonic()));
+        edge.UpdateTo(NULL);
+        ReplaceNode(use, (result == kTrue) ? control : dead());
+      } else if (use->opcode() == IrOpcode::kIfFalse) {
+        TRACE(("  IfFalse: #%d:%s\n", use->id(), use->op()->mnemonic()));
+        edge.UpdateTo(NULL);
+        ReplaceNode(use, (result == kTrue) ? dead() : control);
       }
     }
     return control;
index 0229296..41280b2 100644 (file)
@@ -19,13 +19,13 @@ template <class N>
 class NodeInputIterationTraits {
  public:
   typedef N Node;
-  typedef typename N::Inputs::iterator Iterator;
+  typedef typename N::InputEdges::iterator Iterator;
 
-  static Iterator begin(Node* node) { return node->inputs().begin(); }
-  static Iterator end(Node* node) { return node->inputs().end(); }
+  static Iterator begin(Node* node) { return node->input_edges().begin(); }
+  static Iterator end(Node* node) { return node->input_edges().end(); }
   static int max_id(Graph* graph) { return graph->NodeCount(); }
-  static Node* to(Iterator iterator) { return *iterator; }
-  static Node* from(Iterator iterator) { return iterator.edge().from(); }
+  static Node* to(Iterator iterator) { return (*iterator).to(); }
+  static Node* from(Iterator iterator) { return (*iterator).from(); }
 };
 
 }  // namespace compiler
index a755d24..4b695c7 100644 (file)
@@ -70,13 +70,13 @@ class GenericGraphVisit {
           post_order_node = Traits::from(stack.top().first);
           visit = true;
         } else {
-          visitor->PreEdge(Traits::from(top.first), top.first.edge().index(),
+          visitor->PreEdge(Traits::from(top.first), (*top.first).index(),
                            Traits::to(top.first));
           current = Traits::to(top.first);
           if (!GetVisited(&visited, current->id())) break;
         }
         top = stack.top();
-        visitor->PostEdge(Traits::from(top.first), top.first.edge().index(),
+        visitor->PostEdge(Traits::from(top.first), (*top.first).index(),
                           Traits::to(top.first));
         ++stack.top().first;
       }
index c23672e..81ed99e 100644 (file)
@@ -228,7 +228,7 @@ class GraphVisualizer {
   void PrintNode(Node* node, bool gray);
 
  private:
-  void PrintEdge(Node::Edge edge);
+  void PrintEdge(Edge edge);
 
   AllNodes all_;
   std::ostream& os_;
@@ -285,26 +285,26 @@ void GraphVisualizer::PrintNode(Node* node, bool gray) {
   label << *node->op();
   os_ << "    label=\"{{#" << SafeId(node) << ":" << Escaped(label);
 
-  InputIter i = node->inputs().begin();
+  auto i = node->input_edges().begin();
   for (int j = node->op()->ValueInputCount(); j > 0; ++i, j--) {
-    os_ << "|<I" << i.index() << ">#" << SafeId(*i);
+    os_ << "|<I" << (*i).index() << ">#" << SafeId((*i).to());
   }
   for (int j = OperatorProperties::GetContextInputCount(node->op()); j > 0;
        ++i, j--) {
-    os_ << "|<I" << i.index() << ">X #" << SafeId(*i);
+    os_ << "|<I" << (*i).index() << ">X #" << SafeId((*i).to());
   }
   for (int j = OperatorProperties::GetFrameStateInputCount(node->op()); j > 0;
        ++i, j--) {
-    os_ << "|<I" << i.index() << ">F #" << SafeId(*i);
+    os_ << "|<I" << (*i).index() << ">F #" << SafeId((*i).to());
   }
   for (int j = node->op()->EffectInputCount(); j > 0; ++i, j--) {
-    os_ << "|<I" << i.index() << ">E #" << SafeId(*i);
+    os_ << "|<I" << (*i).index() << ">E #" << SafeId((*i).to());
   }
 
   if (OperatorProperties::IsBasicBlockBegin(node->op()) ||
       GetControlCluster(node) == NULL) {
     for (int j = node->op()->ControlInputCount(); j > 0; ++i, j--) {
-      os_ << "|<I" << i.index() << ">C #" << SafeId(*i);
+      os_ << "|<I" << (*i).index() << ">C #" << SafeId((*i).to());
     }
   }
   os_ << "}";
@@ -338,7 +338,7 @@ static bool IsLikelyBackEdge(Node* from, int index, Node* to) {
 }
 
 
-void GraphVisualizer::PrintEdge(Node::Edge edge) {
+void GraphVisualizer::PrintEdge(Edge edge) {
   Node* from = edge.from();
   int index = edge.index();
   Node* to = edge.to();
@@ -382,8 +382,8 @@ void GraphVisualizer::Print() {
 
   // With all the nodes written, add the edges.
   for (Node* const node : all_.live) {
-    for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
-      PrintEdge(i.edge());
+    for (Edge edge : node->use_edges()) {
+      PrintEdge(edge);
     }
   }
   os_ << "}\n";
@@ -531,7 +531,7 @@ void GraphC1Visualizer::PrintInputs(InputIter* i, int count,
 
 
 void GraphC1Visualizer::PrintInputs(Node* node) {
-  InputIter i = node->inputs().begin();
+  auto i = node->inputs().begin();
   PrintInputs(&i, node->op()->ValueInputCount(), " ");
   PrintInputs(&i, OperatorProperties::GetContextInputCount(node->op()),
               " Ctx:");
index 05ba19f..a91b7db 100644 (file)
@@ -47,9 +47,8 @@ void InstructionSelector::SelectInstructions() {
       if (phi->opcode() != IrOpcode::kPhi) continue;
 
       // Mark all inputs as used.
-      Node::Inputs inputs = phi->inputs();
-      for (InputIter k = inputs.begin(); k != inputs.end(); ++k) {
-        MarkAsUsed(*k);
+      for (Node* const k : phi->inputs()) {
+        MarkAsUsed(k);
       }
     }
   }
@@ -409,11 +408,10 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
   // arguments require an explicit push instruction before the call and do
   // not appear as arguments to the call. Everything else ends up
   // as an InstructionOperand argument to the call.
-  InputIter iter(call->inputs().begin());
+  auto iter(call->inputs().begin());
   int pushed_count = 0;
   for (size_t index = 0; index < input_count; ++iter, ++index) {
     DCHECK(iter != call->inputs().end());
-    DCHECK(index == static_cast<size_t>(iter.index()));
     DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState);
     if (index == 0) continue;  // The first argument (callee) is already done.
     InstructionOperand* op =
index ec6ab90..d143382 100644 (file)
@@ -126,19 +126,17 @@ void Inlinee::UnifyReturn(JSGraph* jsgraph) {
   NodeVector effects(jsgraph->zone());
   // Iterate over all control flow predecessors,
   // which must be return statements.
-  InputIter iter = final_merge->inputs().begin();
-  while (iter != final_merge->inputs().end()) {
-    Node* input = *iter;
+  for (Edge edge : final_merge->input_edges()) {
+    Node* input = edge.to();
     switch (input->opcode()) {
       case IrOpcode::kReturn:
         values.push_back(NodeProperties::GetValueInput(input, 0));
         effects.push_back(NodeProperties::GetEffectInput(input));
-        iter.UpdateToAndIncrement(NodeProperties::GetControlInput(input));
+        edge.UpdateTo(NodeProperties::GetControlInput(input));
         input->RemoveAllInputs();
         break;
       default:
         UNREACHABLE();
-        ++iter;
         break;
     }
   }
@@ -167,9 +165,8 @@ class CopyVisitor : public NullNodeVisitor {
 
   void Post(Node* original) {
     NodeVector inputs(temp_zone_);
-    for (InputIter it = original->inputs().begin();
-         it != original->inputs().end(); ++it) {
-      inputs.push_back(GetCopy(*it));
+    for (Node* const node : original->inputs()) {
+      inputs.push_back(GetCopy(node));
     }
 
     // Reuse the operator in the copy. This assumes that op lives in a zone
@@ -242,35 +239,33 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
   // context, effect, control.
   int inliner_inputs = call->op()->ValueInputCount();
   // Iterate over all uses of the start node.
-  UseIter iter = start_->uses().begin();
-  while (iter != start_->uses().end()) {
-    Node* use = *iter;
+  for (Edge edge : start_->use_edges()) {
+    Node* use = edge.from();
     switch (use->opcode()) {
       case IrOpcode::kParameter: {
         int index = 1 + OpParameter<int>(use->op());
         if (index < inliner_inputs && index < inlinee_context_index) {
           // There is an input from the call, and the index is a value
           // projection but not the context, so rewire the input.
-          NodeProperties::ReplaceWithValue(*iter, call->InputAt(index));
+          NodeProperties::ReplaceWithValue(use, call->InputAt(index));
         } else if (index == inlinee_context_index) {
           // This is the context projection, rewire it to the context from the
           // JSFunction object.
-          NodeProperties::ReplaceWithValue(*iter, context);
+          NodeProperties::ReplaceWithValue(use, context);
         } else if (index < inlinee_context_index) {
           // Call has fewer arguments than required, fill with undefined.
-          NodeProperties::ReplaceWithValue(*iter, jsgraph->UndefinedConstant());
+          NodeProperties::ReplaceWithValue(use, jsgraph->UndefinedConstant());
         } else {
           // We got too many arguments, discard for now.
           // TODO(sigurds): Fix to treat arguments array correctly.
         }
-        ++iter;
         break;
       }
       default:
-        if (NodeProperties::IsEffectEdge(iter.edge())) {
-          iter.UpdateToAndIncrement(context);
-        } else if (NodeProperties::IsControlEdge(iter.edge())) {
-          iter.UpdateToAndIncrement(control);
+        if (NodeProperties::IsEffectEdge(edge)) {
+          edge.UpdateTo(context);
+        } else if (NodeProperties::IsControlEdge(edge)) {
+          edge.UpdateTo(control);
         } else {
           UNREACHABLE();
         }
@@ -455,9 +450,8 @@ class JSCallRuntimeAccessor {
 
   NodeVector inputs(Zone* zone) const {
     NodeVector inputs(zone);
-    for (InputIter it = call_->inputs().begin(); it != call_->inputs().end();
-         ++it) {
-      inputs.push_back(*it);
+    for (Node* const node : call_->inputs()) {
+      inputs.push_back(node);
     }
     return inputs;
   }
index a0319e7..5fe0cb6 100644 (file)
@@ -101,7 +101,7 @@ inline int NodeProperties::GetFrameStateIndex(Node* node) {
 // -----------------------------------------------------------------------------
 // Edge kinds.
 
-inline bool NodeProperties::IsInputRange(Node::Edge edge, int first, int num) {
+inline bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
   // TODO(titzer): edge.index() is linear time;
   // edges maybe need to be marked as value/effect/control.
   if (num == 0) return false;
@@ -109,25 +109,25 @@ inline bool NodeProperties::IsInputRange(Node::Edge edge, int first, int num) {
   return first <= index && index < first + num;
 }
 
-inline bool NodeProperties::IsValueEdge(Node::Edge edge) {
+inline bool NodeProperties::IsValueEdge(Edge edge) {
   Node* node = edge.from();
   return IsInputRange(edge, FirstValueIndex(node),
                       node->op()->ValueInputCount());
 }
 
-inline bool NodeProperties::IsContextEdge(Node::Edge edge) {
+inline bool NodeProperties::IsContextEdge(Edge edge) {
   Node* node = edge.from();
   return IsInputRange(edge, FirstContextIndex(node),
                       OperatorProperties::GetContextInputCount(node->op()));
 }
 
-inline bool NodeProperties::IsEffectEdge(Node::Edge edge) {
+inline bool NodeProperties::IsEffectEdge(Edge edge) {
   Node* node = edge.from();
   return IsInputRange(edge, FirstEffectIndex(node),
                       node->op()->EffectInputCount());
 }
 
-inline bool NodeProperties::IsControlEdge(Node::Edge edge) {
+inline bool NodeProperties::IsControlEdge(Edge edge) {
   Node* node = edge.from();
   return IsInputRange(edge, FirstControlIndex(node),
                       node->op()->ControlInputCount());
@@ -176,13 +176,12 @@ inline void NodeProperties::ReplaceWithValue(Node* node, Node* value,
   }
 
   // Requires distinguishing between value and effect edges.
-  UseIter iter = node->uses().begin();
-  while (iter != node->uses().end()) {
-    if (NodeProperties::IsEffectEdge(iter.edge())) {
+  for (Edge edge : node->use_edges()) {
+    if (NodeProperties::IsEffectEdge(edge)) {
       DCHECK_NE(NULL, effect);
-      iter = iter.UpdateToAndIncrement(effect);
+      edge.UpdateTo(effect);
     } else {
-      iter = iter.UpdateToAndIncrement(value);
+      edge.UpdateTo(value);
     }
   }
 }
index 2c3468f..0f7a161 100644 (file)
@@ -25,10 +25,10 @@ class NodeProperties {
 
   static inline int GetFrameStateIndex(Node* node);
 
-  static inline bool IsValueEdge(Node::Edge edge);
-  static inline bool IsContextEdge(Node::Edge edge);
-  static inline bool IsEffectEdge(Node::Edge edge);
-  static inline bool IsControlEdge(Node::Edge edge);
+  static inline bool IsValueEdge(Edge edge);
+  static inline bool IsContextEdge(Edge edge);
+  static inline bool IsEffectEdge(Edge edge);
+  static inline bool IsControlEdge(Edge edge);
 
   static inline bool IsControl(Node* node);
 
@@ -56,7 +56,7 @@ class NodeProperties {
   static inline int PastEffectIndex(Node* node);
   static inline int PastControlIndex(Node* node);
 
-  static inline bool IsInputRange(Node::Edge edge, int first, int count);
+  static inline bool IsInputRange(Edge edge, int first, int count);
 };
 
 }  // namespace compiler
index a370496..6291ddf 100644 (file)
@@ -23,6 +23,7 @@ namespace v8 {
 namespace internal {
 namespace compiler {
 
+class Edge;
 class Graph;
 
 // Marks are used during traversal of the graph to distinguish states of nodes.
@@ -89,11 +90,25 @@ class Node FINAL {
 
   inline void TrimInputCount(int input_count);
 
+  class InputEdges {
+   public:
+    class iterator;
+    iterator begin() const;
+    iterator end() const;
+    bool empty() const;
+
+    explicit InputEdges(Node* node) : node_(node) {}
+
+   private:
+    Node* node_;
+  };
+
   class Inputs {
    public:
     class iterator;
-    iterator begin();
-    iterator end();
+    iterator begin() const;
+    iterator end() const;
+    bool empty() const;
 
     explicit Inputs(Node* node) : node_(node) {}
 
@@ -102,13 +117,27 @@ class Node FINAL {
   };
 
   Inputs inputs() { return Inputs(this); }
+  InputEdges input_edges() { return InputEdges(this); }
+
+  class UseEdges {
+   public:
+    class iterator;
+    iterator begin() const;
+    iterator end() const;
+    bool empty() const;
+
+    explicit UseEdges(Node* node) : node_(node) {}
+
+   private:
+    Node* node_;
+  };
 
   class Uses {
    public:
     class iterator;
-    iterator begin();
-    iterator end();
-    bool empty();
+    iterator begin() const;
+    iterator end() const;
+    bool empty() const;
 
     explicit Uses(Node* node) : node_(node) {}
 
@@ -117,8 +146,7 @@ class Node FINAL {
   };
 
   Uses uses() { return Uses(this); }
-
-  class Edge;
+  UseEdges use_edges() { return UseEdges(this); }
 
   bool OwnedBy(Node* owner) const;
 
@@ -127,6 +155,7 @@ class Node FINAL {
 
  protected:
   friend class Graph;
+  friend class Edge;
 
   class Use : public ZoneObject {
    public:
@@ -205,8 +234,8 @@ class Node FINAL {
 
 // 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 ndoe having the input.
-class Node::Edge {
+// the node having the input.
+class Edge {
  public:
   Node* from() const { return input_->use->from; }
   Node* to() const { return input_->to; }
@@ -216,9 +245,16 @@ class Node::Edge {
     return index;
   }
 
+  bool operator==(const Edge& other) { return input_ == other.input_; }
+  bool operator!=(const Edge& other) { return !(*this == other); }
+
+  void UpdateTo(Node* new_to) { input_->Update(new_to); }
+
  private:
   friend class Node::Uses::iterator;
   friend class Node::Inputs::iterator;
+  friend class Node::UseEdges::iterator;
+  friend class Node::InputEdges::iterator;
 
   explicit Edge(Node::Input* input) : input_(input) {}
 
@@ -226,43 +262,134 @@ class Node::Edge {
 };
 
 
-// A forward iterator to visit the nodes which are depended upon by a node
-// in the order of input.
+// A forward iterator to visit the edges for the input dependencies of a node..
+class Node::InputEdges::iterator {
+ public:
+  typedef std::forward_iterator_tag iterator_category;
+  typedef int difference_type;
+  typedef Edge value_type;
+  typedef Edge* pointer;
+  typedef Edge& reference;
+  iterator(const Node::InputEdges::iterator& other)  // NOLINT
+      : input_(other.input_) {}
+  iterator() : input_(NULL) {}
+
+  Edge operator*() const { return Edge(input_); }
+  bool operator==(const iterator& other) const { return Equals(other); }
+  bool operator!=(const iterator& other) const { return !Equals(other); }
+  iterator& operator++() {
+    DCHECK(input_ != NULL);
+    Edge edge(input_);
+    Node* from = edge.from();
+    SetInput(from, input_->use->input_index + 1);
+    return *this;
+  }
+  iterator operator++(int) {
+    iterator result(*this);
+    ++(*this);
+    return result;
+  }
+
+ private:
+  friend class Node;
+
+  explicit iterator(Node* from, int index = 0) : input_(NULL) {
+    SetInput(from, index);
+  }
+
+  bool Equals(const iterator& other) const { return other.input_ == input_; }
+  void SetInput(Node* from, int index) {
+    DCHECK(index >= 0 && index <= from->InputCount());
+    if (index < from->InputCount()) {
+      input_ = from->GetInputRecordPtr(index);
+    } else {
+      input_ = NULL;
+    }
+  }
+
+  Input* input_;
+};
+
+
+// A forward iterator to visit the inputs of a node.
 class Node::Inputs::iterator {
  public:
+  typedef std::forward_iterator_tag iterator_category;
+  typedef int difference_type;
+  typedef Node* value_type;
+  typedef Node** pointer;
+  typedef Node*& reference;
+
   iterator(const Node::Inputs::iterator& other)  // NOLINT
-      : node_(other.node_),
-        index_(other.index_) {}
+      : iter_(other.iter_) {}
 
-  Node* operator*() { return GetInput()->to; }
-  Node::Edge edge() { return Node::Edge(GetInput()); }
-  bool operator==(const iterator& other) const {
-    return other.index_ == index_ && other.node_ == node_;
-  }
-  bool operator!=(const iterator& other) const { return !(other == *this); }
+  Node* operator*() const { return (*iter_).to(); }
+  bool operator==(const iterator& other) const { return Equals(other); }
+  bool operator!=(const iterator& other) const { return !Equals(other); }
   iterator& operator++() {
-    DCHECK(node_ != NULL);
-    DCHECK(index_ < node_->input_count_);
-    ++index_;
+    ++iter_;
     return *this;
   }
-  iterator& UpdateToAndIncrement(Node* new_to) {
-    Node::Input* input = GetInput();
-    input->Update(new_to);
-    index_++;
+  iterator operator++(int) {
+    iterator result(*this);
+    ++(*this);
+    return result;
+  }
+
+
+ private:
+  friend class Node::Inputs;
+
+  explicit iterator(Node* node, int index) : iter_(node, index) {}
+
+  bool Equals(const iterator& other) const { return other.iter_ == iter_; }
+
+  Node::InputEdges::iterator iter_;
+};
+
+// A forward iterator to visit the uses edges of a node. The edges are returned
+// in
+// the order in which they were added as inputs.
+class Node::UseEdges::iterator {
+ public:
+  iterator(const Node::UseEdges::iterator& other)  // NOLINT
+      : current_(other.current_),
+        next_(other.next_) {}
+
+  Edge operator*() const { return Edge(CurrentInput()); }
+
+  bool operator==(const iterator& other) { return Equals(other); }
+  bool operator!=(const iterator& other) { return !Equals(other); }
+  iterator& operator++() {
+    DCHECK(current_ != NULL);
+    current_ = next_;
+    next_ = (current_ == NULL) ? NULL : current_->next;
     return *this;
   }
-  int index() { return index_; }
+  iterator operator++(int) {
+    iterator result(*this);
+    ++(*this);
+    return result;
+  }
 
  private:
-  friend class Node;
+  friend class Node::UseEdges;
+
+  iterator() : current_(NULL), next_(NULL) {}
+  explicit iterator(Node* node)
+      : current_(node->first_use_),
+        next_(current_ == NULL ? NULL : current_->next) {}
 
-  explicit iterator(Node* node, int index) : node_(node), index_(index) {}
+  bool Equals(const iterator& other) const {
+    return other.current_ == current_;
+  }
 
-  Input* GetInput() const { return node_->GetInputRecordPtr(index_); }
+  Input* CurrentInput() const {
+    return current_->from->GetInputRecordPtr(current_->input_index);
+  }
 
-  Node* node_;
-  int index_;
+  Node::Use* current_;
+  Node::Use* next_;
 };
 
 
@@ -271,42 +398,29 @@ class Node::Inputs::iterator {
 class Node::Uses::iterator {
  public:
   iterator(const Node::Uses::iterator& other)  // NOLINT
-      : current_(other.current_),
-        index_(other.index_) {}
+      : current_(other.current_) {}
 
   Node* operator*() { return current_->from; }
-  Node::Edge edge() { return Node::Edge(CurrentInput()); }
 
   bool operator==(const iterator& other) { return other.current_ == current_; }
   bool operator!=(const iterator& other) { return other.current_ != current_; }
   iterator& operator++() {
     DCHECK(current_ != NULL);
-    index_++;
-    current_ = current_->next;
-    return *this;
-  }
-  iterator& UpdateToAndIncrement(Node* new_to) {
-    DCHECK(current_ != NULL);
-    index_++;
-    Node::Input* input = CurrentInput();
     current_ = current_->next;
-    input->Update(new_to);
     return *this;
   }
-  int index() const { return index_; }
 
  private:
   friend class Node::Uses;
 
-  iterator() : current_(NULL), index_(0) {}
-  explicit iterator(Node* node) : current_(node->first_use_), index_(0) {}
+  iterator() : current_(NULL) {}
+  explicit iterator(Node* node) : current_(node->first_use_) {}
 
   Input* CurrentInput() const {
     return current_->from->GetInputRecordPtr(current_->input_index);
   }
 
   Node::Use* current_;
-  int index_;
 };
 
 
@@ -338,21 +452,42 @@ static inline const T& OpParameter(const Node* node) {
   return OpParameter<T>(node->op());
 }
 
-inline Node::Inputs::iterator Node::Inputs::begin() {
+inline Node::InputEdges::iterator Node::InputEdges::begin() const {
+  return Node::InputEdges::iterator(this->node_, 0);
+}
+
+inline Node::InputEdges::iterator Node::InputEdges::end() const {
+  return Node::InputEdges::iterator(this->node_, this->node_->InputCount());
+}
+
+inline Node::Inputs::iterator Node::Inputs::begin() const {
   return Node::Inputs::iterator(this->node_, 0);
 }
 
-inline Node::Inputs::iterator Node::Inputs::end() {
+inline Node::Inputs::iterator Node::Inputs::end() const {
   return Node::Inputs::iterator(this->node_, this->node_->InputCount());
 }
 
-inline Node::Uses::iterator Node::Uses::begin() {
+inline Node::UseEdges::iterator Node::UseEdges::begin() const {
+  return Node::UseEdges::iterator(this->node_);
+}
+
+inline Node::UseEdges::iterator Node::UseEdges::end() const {
+  return Node::UseEdges::iterator();
+}
+
+inline Node::Uses::iterator Node::Uses::begin() const {
   return Node::Uses::iterator(this->node_);
 }
 
-inline Node::Uses::iterator Node::Uses::end() { return Node::Uses::iterator(); }
+inline Node::Uses::iterator Node::Uses::end() const {
+  return Node::Uses::iterator();
+}
 
-inline bool Node::Uses::empty() { return begin() == end(); }
+inline bool Node::InputEdges::empty() const { return begin() == end(); }
+inline bool Node::Uses::empty() const { return begin() == end(); }
+inline bool Node::UseEdges::empty() const { return begin() == end(); }
+inline bool Node::Inputs::empty() const { return begin() == end(); }
 
 inline void Node::ReplaceUses(Node* replace_to) {
   for (Use* use = first_use_; use != NULL; use = use->next) {
@@ -388,9 +523,8 @@ inline void Node::ReplaceUsesIf(UnaryPredicate pred, Node* replace_to) {
 }
 
 inline void Node::RemoveAllInputs() {
-  for (Inputs::iterator iter(inputs().begin()); iter != inputs().end();
-       ++iter) {
-    iter.GetInput()->Update(NULL);
+  for (Edge edge : input_edges()) {
+    edge.UpdateTo(NULL);
   }
 }
 
index 051d015..5252d42 100644 (file)
@@ -147,8 +147,8 @@ void Scheduler::UpdatePlacement(Node* node, Placement placement) {
     // Reduce the use count of the node's inputs to potentially make them
     // schedulable. If all the uses of a node have been scheduled, then the node
     // itself can be scheduled.
-    for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) {
-      DecrementUnscheduledUseCount(*i, i.index(), i.edge().from());
+    for (Edge const edge : node->input_edges()) {
+      DecrementUnscheduledUseCount(edge.to(), edge.index(), edge.from());
     }
   }
   data->placement_ = placement;
@@ -455,9 +455,8 @@ class CFGBuilder : public ZoneObject {
     DCHECK(block != NULL);
     // For all of the merge's control inputs, add a goto at the end to the
     // merge's basic block.
-    for (InputIter j = merge->inputs().begin(); j != merge->inputs().end();
-         ++j) {
-      BasicBlock* predecessor_block = schedule_->block(*j);
+    for (Node* const j : merge->inputs()) {
+      BasicBlock* predecessor_block = schedule_->block(j);
       TraceConnect(merge, predecessor_block, block);
       schedule_->AddGoto(predecessor_block, block);
     }
@@ -1250,9 +1249,7 @@ class ScheduleLateNodeVisitor {
  private:
   void ProcessQueue(Node* root) {
     ZoneQueue<Node*>* queue = &(scheduler_->schedule_queue_);
-    for (InputIter i = root->inputs().begin(); i != root->inputs().end(); ++i) {
-      Node* node = *i;
-
+    for (Node* node : root->inputs()) {
       // Don't schedule coupled nodes on their own.
       if (scheduler_->GetPlacement(node) == Scheduler::kCoupled) {
         node = NodeProperties::GetControlInput(node);
@@ -1325,9 +1322,8 @@ class ScheduleLateNodeVisitor {
 
   BasicBlock* GetCommonDominatorOfUses(Node* node) {
     BasicBlock* block = NULL;
-    Node::Uses uses = node->uses();
-    for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) {
-      BasicBlock* use_block = GetBlockForUse(i.edge());
+    for (Edge edge : node->use_edges()) {
+      BasicBlock* use_block = GetBlockForUse(edge);
       block = block == NULL ? use_block : use_block == NULL
                                               ? block
                                               : scheduler_->GetCommonDominator(
@@ -1336,7 +1332,7 @@ class ScheduleLateNodeVisitor {
     return block;
   }
 
-  BasicBlock* GetBlockForUse(Node::Edge edge) {
+  BasicBlock* GetBlockForUse(Edge edge) {
     Node* use = edge.from();
     IrOpcode::Value opcode = use->opcode();
     if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) {
index df3c825..1fea3af 100644 (file)
@@ -237,19 +237,19 @@ class RepresentationSelector {
   // context, effect, and control inputs, assuming that value inputs should have
   // {kRepTagged} representation and can observe all output values {kTypeAny}.
   void VisitInputs(Node* node) {
-    InputIter i = node->inputs().begin();
+    auto i = node->input_edges().begin();
     for (int j = node->op()->ValueInputCount(); j > 0; ++i, j--) {
-      ProcessInput(node, i.index(), kMachAnyTagged);  // Value inputs
+      ProcessInput(node, (*i).index(), kMachAnyTagged);  // Value inputs
     }
     for (int j = OperatorProperties::GetContextInputCount(node->op()); j > 0;
          ++i, j--) {
-      ProcessInput(node, i.index(), kMachAnyTagged);  // Context inputs
+      ProcessInput(node, (*i).index(), kMachAnyTagged);  // Context inputs
     }
     for (int j = node->op()->EffectInputCount(); j > 0; ++i, j--) {
-      Enqueue(*i);  // Effect inputs: just visit
+      Enqueue((*i).to());  // Effect inputs: just visit
     }
     for (int j = node->op()->ControlInputCount(); j > 0; ++i, j--) {
-      Enqueue(*i);  // Control inputs: just visit
+      Enqueue((*i).to());  // Control inputs: just visit
     }
     SetOutput(node, kMachAnyTagged);
   }
@@ -379,21 +379,19 @@ class RepresentationSelector {
       }
 
       // Convert inputs to the output representation of this phi.
-      Node::Inputs inputs = node->inputs();
-      for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
-           ++iter, --values) {
+      for (Edge const edge : node->input_edges()) {
         // TODO(titzer): it'd be nice to have distinguished edge kinds here.
-        ProcessInput(node, iter.index(), values > 0 ? output_type : 0);
+        ProcessInput(node, edge.index(), values > 0 ? output_type : 0);
+        values--;
       }
     } else {
       // Propagate {use} of the phi to value inputs, and 0 to control.
-      Node::Inputs inputs = node->inputs();
       MachineType use_type =
           static_cast<MachineType>((use & kTypeMask) | output);
-      for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
-           ++iter, --values) {
+      for (Edge const edge : node->input_edges()) {
         // TODO(titzer): it'd be nice to have distinguished edge kinds here.
-        ProcessInput(node, iter.index(), values > 0 ? use_type : 0);
+        ProcessInput(node, edge.index(), values > 0 ? use_type : 0);
+        values--;
       }
     }
   }
index 44a4eea..6021dfc 100644 (file)
@@ -176,11 +176,11 @@ void Verifier::Visitor::Pre(Node* node) {
 
   // Verify all successors are projections if multiple value outputs exist.
   if (node->op()->ValueOutputCount() > 1) {
-    Node::Uses uses = node->uses();
-    for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
-      CHECK(!NodeProperties::IsValueEdge(it.edge()) ||
-            (*it)->opcode() == IrOpcode::kProjection ||
-            (*it)->opcode() == IrOpcode::kParameter);
+    for (Edge edge : node->use_edges()) {
+      Node* use = edge.from();
+      CHECK(!NodeProperties::IsValueEdge(edge) ||
+            use->opcode() == IrOpcode::kProjection ||
+            use->opcode() == IrOpcode::kParameter);
     }
   }
 
index d0103f5..03aa50b 100644 (file)
@@ -130,11 +130,8 @@ class ControlReducerTester : HandleAndZoneScope {
   }
 
   Node* SetSelfReferences(Node* node) {
-    Node::Inputs inputs = node->inputs();
-    for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
-         ++iter) {
-      Node* input = *iter;
-      if (input == self) node->ReplaceInput(iter.index(), node);
+    for (Edge edge : node->input_edges()) {
+      if (edge.to() == self) node->ReplaceInput(edge.index(), node);
     }
     return node;
   }
index 36a9b49..eafabd3 100644 (file)
@@ -92,10 +92,8 @@ TEST(NodeInputIteratorOne) {
 TEST(NodeUseIteratorEmpty) {
   GraphTester graph;
   Node* n1 = graph.NewNode(&dummy_operator);
-  Node::Uses::iterator i(n1->uses().begin());
   int use_count = 0;
-  for (; i != n1->uses().end(); ++i) {
-    Node::Edge edge(i.edge());
+  for (Edge const edge : n1->use_edges()) {
     USE(edge);
     use_count++;
   }
@@ -365,31 +363,31 @@ TEST(AppendInputsAndIterator) {
   Node* n1 = graph.NewNode(&dummy_operator, n0);
   Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
 
-  Node::Inputs inputs(n2->inputs());
-  Node::Inputs::iterator current = inputs.begin();
+  Node::InputEdges inputs(n2->input_edges());
+  Node::InputEdges::iterator current = inputs.begin();
   CHECK(current != inputs.end());
-  CHECK(*current == n0);
+  CHECK((*current).to() == n0);
   ++current;
   CHECK(current != inputs.end());
-  CHECK(*current == n1);
+  CHECK((*current).to() == n1);
   ++current;
   CHECK(current == inputs.end());
 
   Node* n3 = graph.NewNode(&dummy_operator);
   n2->AppendInput(graph.zone(), n3);
-  inputs = n2->inputs();
+  inputs = n2->input_edges();
   current = inputs.begin();
   CHECK(current != inputs.end());
-  CHECK(*current == n0);
-  CHECK_EQ(0, current.index());
+  CHECK((*current).to() == n0);
+  CHECK_EQ(0, (*current).index());
   ++current;
   CHECK(current != inputs.end());
-  CHECK(*current == n1);
-  CHECK_EQ(1, current.index());
+  CHECK((*current).to() == n1);
+  CHECK_EQ(1, (*current).index());
   ++current;
   CHECK(current != inputs.end());
-  CHECK(*current == n3);
-  CHECK_EQ(2, current.index());
+  CHECK((*current).to() == n3);
+  CHECK_EQ(2, (*current).index());
   ++current;
   CHECK(current == inputs.end());
 }