OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/common-operator.h" | 5 #include "src/compiler/common-operator.h" |
6 #include "src/compiler/control-reducer.h" | 6 #include "src/compiler/control-reducer.h" |
7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 // Gather all nodes backwards-reachable from end (through inputs). | 73 // Gather all nodes backwards-reachable from end (through inputs). |
74 state_.assign(graph()->NodeCount(), kUnvisited); | 74 state_.assign(graph()->NodeCount(), kUnvisited); |
75 NodeVector nodes(zone_); | 75 NodeVector nodes(zone_); |
76 AddNodesReachableFromEnd(nodes); | 76 AddNodesReachableFromEnd(nodes); |
77 | 77 |
78 // Walk forward through control nodes, looking for back edges to nodes | 78 // Walk forward through control nodes, looking for back edges to nodes |
79 // that are not connected to end. Those are non-terminating loops (NTLs). | 79 // that are not connected to end. Those are non-terminating loops (NTLs). |
80 Node* start = graph()->start(); | 80 Node* start = graph()->start(); |
81 ZoneVector<byte> fw_reachability(graph()->NodeCount(), 0, zone_); | 81 ZoneVector<byte> fw_reachability(graph()->NodeCount(), 0, zone_); |
82 fw_reachability[start->id()] = kFromStart | kOnStack; | 82 fw_reachability[start->id()] = kFromStart | kOnStack; |
83 stack_.push_back(start); | |
84 | 83 |
85 while (!stack_.empty()) { | 84 // We use a stack of (Node, UseIter) pairs to avoid O(n^2) traversal. |
86 Node* node = stack_.back(); | 85 typedef std::pair<Node*, UseIter> FwIter; |
| 86 ZoneDeque<FwIter> fw_stack(zone_); |
| 87 fw_stack.push_back(FwIter(start, start->uses().begin())); |
| 88 |
| 89 while (!fw_stack.empty()) { |
| 90 Node* node = fw_stack.back().first; |
87 TRACE(("ControlFw: #%d:%s\n", node->id(), node->op()->mnemonic())); | 91 TRACE(("ControlFw: #%d:%s\n", node->id(), node->op()->mnemonic())); |
88 bool pop = true; | 92 bool pop = true; |
89 for (Node* const succ : node->uses()) { | 93 while (fw_stack.back().second != node->uses().end()) { |
| 94 Node* succ = *(fw_stack.back().second); |
90 byte reach = fw_reachability[succ->id()]; | 95 byte reach = fw_reachability[succ->id()]; |
91 if ((reach & kOnStack) != 0 && state_[succ->id()] != kVisited) { | 96 if ((reach & kOnStack) != 0 && state_[succ->id()] != kVisited) { |
92 // {succ} is on stack and not reachable from end. | 97 // {succ} is on stack and not reachable from end. |
93 ConnectNTL(nodes, succ); | 98 ConnectNTL(nodes, succ); |
94 fw_reachability.resize(graph()->NodeCount(), 0); | 99 fw_reachability.resize(graph()->NodeCount(), 0); |
95 pop = false; // continue traversing inputs to this node. | 100 // The use list of {succ} might have changed. |
| 101 fw_stack[fw_stack.size() - 1] = FwIter(succ, succ->uses().begin()); |
| 102 pop = false; // restart traversing successors of this node. |
96 break; | 103 break; |
97 } | 104 } |
98 if ((reach & kFromStart) == 0 && | 105 if ((reach & kFromStart) == 0 && |
99 IrOpcode::IsControlOpcode(succ->opcode())) { | 106 IrOpcode::IsControlOpcode(succ->opcode())) { |
100 // {succ} is a control node and not yet reached from start. | 107 // {succ} is a control node and not yet reached from start. |
101 fw_reachability[succ->id()] |= kFromStart | kOnStack; | 108 fw_reachability[succ->id()] |= kFromStart | kOnStack; |
102 stack_.push_back(succ); | 109 fw_stack.push_back(FwIter(succ, succ->uses().begin())); |
103 pop = false; // "recurse" into successor control node. | 110 pop = false; // "recurse" into successor control node. |
104 break; | 111 break; |
105 } | 112 } |
| 113 ++fw_stack.back().second; |
106 } | 114 } |
107 if (pop) { | 115 if (pop) { |
108 fw_reachability[node->id()] &= ~kOnStack; | 116 fw_reachability[node->id()] &= ~kOnStack; |
109 stack_.pop_back(); | 117 fw_stack.pop_back(); |
110 } | 118 } |
111 } | 119 } |
112 | 120 |
113 // Trim references from dead nodes to live nodes first. | 121 // Trim references from dead nodes to live nodes first. |
114 jsgraph_->GetCachedNodes(&nodes); | 122 jsgraph_->GetCachedNodes(&nodes); |
115 TrimNodes(nodes); | 123 TrimNodes(nodes); |
116 | 124 |
117 // Any control nodes not reachable from start are dead, even loops. | 125 // Any control nodes not reachable from start are dead, even loops. |
118 for (size_t i = 0; i < nodes.size(); i++) { | 126 for (size_t i = 0; i < nodes.size(); i++) { |
119 Node* node = nodes[i]; | 127 Node* node = nodes[i]; |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 Node* ControlReducer::ReduceBranchForTesting(JSGraph* jsgraph, | 565 Node* ControlReducer::ReduceBranchForTesting(JSGraph* jsgraph, |
558 CommonOperatorBuilder* common, | 566 CommonOperatorBuilder* common, |
559 Node* node) { | 567 Node* node) { |
560 Zone zone(jsgraph->graph()->zone()->isolate()); | 568 Zone zone(jsgraph->graph()->zone()->isolate()); |
561 ControlReducerImpl impl(&zone, jsgraph, common); | 569 ControlReducerImpl impl(&zone, jsgraph, common); |
562 return impl.ReduceBranch(node); | 570 return impl.ReduceBranch(node); |
563 } | 571 } |
564 } | 572 } |
565 } | 573 } |
566 } // namespace v8::internal::compiler | 574 } // namespace v8::internal::compiler |
OLD | NEW |