From: danno Date: Tue, 2 Dec 2014 14:38:55 +0000 (-0800) Subject: Clean up node iteration X-Git-Tag: upstream/4.7.83~5424 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f6e5bc1642ed4580f71c221d5cf289a4d74ba324;p=platform%2Fupstream%2Fv8.git Clean up node iteration - 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} --- diff --git a/src/compiler/change-lowering.cc b/src/compiler/change-lowering.cc index a4e081a..c5cdc27 100644 --- a/src/compiler/change-lowering.cc +++ b/src/compiler/change-lowering.cc @@ -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); diff --git a/src/compiler/control-reducer.cc b/src/compiler/control-reducer.cc index 5068385..236ce4b 100644 --- a/src/compiler/control-reducer.cc +++ b/src/compiler/control-reducer.cc @@ -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; diff --git a/src/compiler/generic-algorithm-inl.h b/src/compiler/generic-algorithm-inl.h index 0229296..41280b2 100644 --- a/src/compiler/generic-algorithm-inl.h +++ b/src/compiler/generic-algorithm-inl.h @@ -19,13 +19,13 @@ template 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 diff --git a/src/compiler/generic-algorithm.h b/src/compiler/generic-algorithm.h index a755d24..4b695c7 100644 --- a/src/compiler/generic-algorithm.h +++ b/src/compiler/generic-algorithm.h @@ -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; } diff --git a/src/compiler/graph-visualizer.cc b/src/compiler/graph-visualizer.cc index c23672e..81ed99e 100644 --- a/src/compiler/graph-visualizer.cc +++ b/src/compiler/graph-visualizer.cc @@ -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_ << "|#" << SafeId(*i); + os_ << "|#" << SafeId((*i).to()); } for (int j = OperatorProperties::GetContextInputCount(node->op()); j > 0; ++i, j--) { - os_ << "|X #" << SafeId(*i); + os_ << "|X #" << SafeId((*i).to()); } for (int j = OperatorProperties::GetFrameStateInputCount(node->op()); j > 0; ++i, j--) { - os_ << "|F #" << SafeId(*i); + os_ << "|F #" << SafeId((*i).to()); } for (int j = node->op()->EffectInputCount(); j > 0; ++i, j--) { - os_ << "|E #" << SafeId(*i); + os_ << "|E #" << SafeId((*i).to()); } if (OperatorProperties::IsBasicBlockBegin(node->op()) || GetControlCluster(node) == NULL) { for (int j = node->op()->ControlInputCount(); j > 0; ++i, j--) { - os_ << "|C #" << SafeId(*i); + os_ << "|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:"); diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index 05ba19f..a91b7db 100644 --- a/src/compiler/instruction-selector.cc +++ b/src/compiler/instruction-selector.cc @@ -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(iter.index())); DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); if (index == 0) continue; // The first argument (callee) is already done. InstructionOperand* op = diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc index ec6ab90..d143382 100644 --- a/src/compiler/js-inlining.cc +++ b/src/compiler/js-inlining.cc @@ -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(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; } diff --git a/src/compiler/node-properties-inl.h b/src/compiler/node-properties-inl.h index a0319e7..5fe0cb6 100644 --- a/src/compiler/node-properties-inl.h +++ b/src/compiler/node-properties-inl.h @@ -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); } } } diff --git a/src/compiler/node-properties.h b/src/compiler/node-properties.h index 2c3468f..0f7a161 100644 --- a/src/compiler/node-properties.h +++ b/src/compiler/node-properties.h @@ -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 diff --git a/src/compiler/node.h b/src/compiler/node.h index a370496..6291ddf 100644 --- a/src/compiler/node.h +++ b/src/compiler/node.h @@ -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(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); } } diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc index 051d015..5252d42 100644 --- a/src/compiler/scheduler.cc +++ b/src/compiler/scheduler.cc @@ -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* 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) { diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index df3c825..1fea3af 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -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((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--; } } } diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index 44a4eea..6021dfc 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -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); } } diff --git a/test/cctest/compiler/test-control-reducer.cc b/test/cctest/compiler/test-control-reducer.cc index d0103f5..03aa50b 100644 --- a/test/cctest/compiler/test-control-reducer.cc +++ b/test/cctest/compiler/test-control-reducer.cc @@ -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; } diff --git a/test/cctest/compiler/test-node.cc b/test/cctest/compiler/test-node.cc index 36a9b49..eafabd3 100644 --- a/test/cctest/compiler/test-node.cc +++ b/test/cctest/compiler/test-node.cc @@ -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()); }