| 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-marker.h" | 9 #include "src/compiler/node-marker.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| 11 #include "src/compiler/node-properties-inl.h" | 11 #include "src/compiler/node-properties.h" |
| 12 #include "src/zone-containers.h" | 12 #include "src/zone-containers.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 namespace compiler { | 16 namespace compiler { |
| 17 | 17 |
| 18 enum VisitState { kUnvisited = 0, kOnStack = 1, kRevisit = 2, kVisited = 3 }; | 18 enum VisitState { kUnvisited = 0, kOnStack = 1, kRevisit = 2, kVisited = 3 }; |
| 19 enum Decision { kFalse, kUnknown, kTrue }; | 19 enum Decision { kFalse, kUnknown, kTrue }; |
| 20 | 20 |
| 21 class ReachabilityMarker : public NodeMarker<uint8_t> { | 21 class ReachabilityMarker : public NodeMarker<uint8_t> { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); | 126 AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); |
| 127 | 127 |
| 128 // Reset the use iterators for the entire stack. | 128 // Reset the use iterators for the entire stack. |
| 129 for (size_t i = 0; i < fw_stack.size(); i++) { | 129 for (size_t i = 0; i < fw_stack.size(); i++) { |
| 130 FwIter& iter = fw_stack[i]; | 130 FwIter& iter = fw_stack[i]; |
| 131 fw_stack[i] = FwIter(iter.first, iter.first->uses().begin()); | 131 fw_stack[i] = FwIter(iter.first, iter.first->uses().begin()); |
| 132 } | 132 } |
| 133 pop = false; // restart traversing successors of this node. | 133 pop = false; // restart traversing successors of this node. |
| 134 break; | 134 break; |
| 135 } | 135 } |
| 136 if (IrOpcode::IsControlOpcode(succ->opcode()) && | 136 if (NodeProperties::IsControl(succ) && |
| 137 !marked.IsReachableFromStart(succ)) { | 137 !marked.IsReachableFromStart(succ)) { |
| 138 // {succ} is a control node and not yet reached from start. | 138 // {succ} is a control node and not yet reached from start. |
| 139 marked.Push(succ); | 139 marked.Push(succ); |
| 140 marked.SetReachableFromStart(succ); | 140 marked.SetReachableFromStart(succ); |
| 141 fw_stack.push_back(FwIter(succ, succ->uses().begin())); | 141 fw_stack.push_back(FwIter(succ, succ->uses().begin())); |
| 142 pop = false; // "recurse" into successor control node. | 142 pop = false; // "recurse" into successor control node. |
| 143 break; | 143 break; |
| 144 } | 144 } |
| 145 ++fw_stack.back().second; | 145 ++fw_stack.back().second; |
| 146 } | 146 } |
| 147 if (pop) { | 147 if (pop) { |
| 148 marked.Pop(node); | 148 marked.Pop(node); |
| 149 fw_stack.pop_back(); | 149 fw_stack.pop_back(); |
| 150 } | 150 } |
| 151 } | 151 } |
| 152 | 152 |
| 153 // Trim references from dead nodes to live nodes first. | 153 // Trim references from dead nodes to live nodes first. |
| 154 jsgraph_->GetCachedNodes(&nodes); | 154 jsgraph_->GetCachedNodes(&nodes); |
| 155 TrimNodes(marked, nodes); | 155 TrimNodes(marked, nodes); |
| 156 | 156 |
| 157 // Any control nodes not reachable from start are dead, even loops. | 157 // Any control nodes not reachable from start are dead, even loops. |
| 158 for (size_t i = 0; i < nodes.size(); i++) { | 158 for (size_t i = 0; i < nodes.size(); i++) { |
| 159 Node* node = nodes[i]; | 159 Node* node = nodes[i]; |
| 160 if (IrOpcode::IsControlOpcode(node->opcode()) && | 160 if (NodeProperties::IsControl(node) && |
| 161 !marked.IsReachableFromStart(node)) { | 161 !marked.IsReachableFromStart(node)) { |
| 162 ReplaceNode(node, dead()); // uses will be added to revisit queue. | 162 ReplaceNode(node, dead()); // uses will be added to revisit queue. |
| 163 } | 163 } |
| 164 } | 164 } |
| 165 return TryRevisit(); // try to push a node onto the stack. | 165 return TryRevisit(); // try to push a node onto the stack. |
| 166 } | 166 } |
| 167 | 167 |
| 168 // Connect {loop}, the header of a non-terminating loop, to the end node. | 168 // Connect {loop}, the header of a non-terminating loop, to the end node. |
| 169 Node* ConnectNTL(Node* loop) { | 169 Node* ConnectNTL(Node* loop) { |
| 170 TRACE(("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic())); | 170 TRACE(("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic())); |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 if (live > 1 && live == node->InputCount()) return node; // nothing to do. | 495 if (live > 1 && live == node->InputCount()) return node; // nothing to do. |
| 496 | 496 |
| 497 TRACE(("ReduceMerge: #%d:%s (%d live)\n", node->id(), | 497 TRACE(("ReduceMerge: #%d:%s (%d live)\n", node->id(), |
| 498 node->op()->mnemonic(), live)); | 498 node->op()->mnemonic(), live)); |
| 499 | 499 |
| 500 if (live == 0) return dead(); // no remaining inputs. | 500 if (live == 0) return dead(); // no remaining inputs. |
| 501 | 501 |
| 502 // Gather phis and effect phis to be edited. | 502 // Gather phis and effect phis to be edited. |
| 503 ZoneVector<Node*> phis(zone_); | 503 ZoneVector<Node*> phis(zone_); |
| 504 for (Node* const use : node->uses()) { | 504 for (Node* const use : node->uses()) { |
| 505 if (IrOpcode::IsPhiOpcode(use->opcode())) phis.push_back(use); | 505 if (NodeProperties::IsPhi(use)) phis.push_back(use); |
| 506 } | 506 } |
| 507 | 507 |
| 508 if (live == 1) { | 508 if (live == 1) { |
| 509 // All phis are redundant. Replace them with their live input. | 509 // All phis are redundant. Replace them with their live input. |
| 510 for (Node* const phi : phis) ReplaceNode(phi, phi->InputAt(live_index)); | 510 for (Node* const phi : phis) ReplaceNode(phi, phi->InputAt(live_index)); |
| 511 // The merge itself is redundant. | 511 // The merge itself is redundant. |
| 512 return node->InputAt(live_index); | 512 return node->InputAt(live_index); |
| 513 } | 513 } |
| 514 | 514 |
| 515 // Edit phis in place, removing dead inputs and revisiting them. | 515 // Edit phis in place, removing dead inputs and revisiting them. |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 return impl.ReduceIfTrue(node); | 634 return impl.ReduceIfTrue(node); |
| 635 case IrOpcode::kIfFalse: | 635 case IrOpcode::kIfFalse: |
| 636 return impl.ReduceIfFalse(node); | 636 return impl.ReduceIfFalse(node); |
| 637 default: | 637 default: |
| 638 return node; | 638 return node; |
| 639 } | 639 } |
| 640 } | 640 } |
| 641 } | 641 } |
| 642 } | 642 } |
| 643 } // namespace v8::internal::compiler | 643 } // namespace v8::internal::compiler |
| OLD | NEW |