| 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/graph-reducer.h" | 8 #include "src/compiler/graph-reducer.h" |
| 9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
| 10 #include "src/compiler/node-marker.h" | 10 #include "src/compiler/node-marker.h" |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 } | 143 } |
| 144 | 144 |
| 145 return done; | 145 return done; |
| 146 } | 146 } |
| 147 | 147 |
| 148 // Connect {loop}, the header of a non-terminating loop, to the end node. | 148 // Connect {loop}, the header of a non-terminating loop, to the end node. |
| 149 Node* ConnectNTL(Node* loop) { | 149 Node* ConnectNTL(Node* loop) { |
| 150 TRACE("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic()); | 150 TRACE("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic()); |
| 151 DCHECK_EQ(IrOpcode::kLoop, loop->opcode()); | 151 DCHECK_EQ(IrOpcode::kLoop, loop->opcode()); |
| 152 | 152 |
| 153 Node* always = graph()->NewNode(common()->Always()); | 153 // Collect all loop effects. |
| 154 Node* branch = graph()->NewNode(common()->Branch(), always, loop); | |
| 155 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 156 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 157 | |
| 158 // Insert the branch into the loop and collect all loop effects. | |
| 159 NodeVector effects(zone_); | 154 NodeVector effects(zone_); |
| 160 for (auto edge : loop->use_edges()) { | 155 for (auto edge : loop->use_edges()) { |
| 161 DCHECK_EQ(loop, edge.to()); | 156 DCHECK_EQ(loop, edge.to()); |
| 162 DCHECK(NodeProperties::IsControlEdge(edge)); | 157 DCHECK(NodeProperties::IsControlEdge(edge)); |
| 163 if (edge.from() == branch) continue; | |
| 164 switch (edge.from()->opcode()) { | 158 switch (edge.from()->opcode()) { |
| 165 case IrOpcode::kPhi: | 159 case IrOpcode::kPhi: |
| 166 break; | 160 break; |
| 167 case IrOpcode::kEffectPhi: | 161 case IrOpcode::kEffectPhi: |
| 168 effects.push_back(edge.from()); | 162 effects.push_back(edge.from()); |
| 169 break; | 163 break; |
| 170 default: | 164 default: |
| 171 // Update all control edges (except {branch}) pointing to the {loop}. | |
| 172 edge.UpdateTo(if_true); | |
| 173 break; | 165 break; |
| 174 } | 166 } |
| 175 } | 167 } |
| 176 | 168 |
| 177 // Compute effects for the Return. | 169 // Compute effects for the Return. |
| 178 Node* effect = graph()->start(); | 170 Node* effect = graph()->start(); |
| 179 int const effects_count = static_cast<int>(effects.size()); | 171 int const effects_count = static_cast<int>(effects.size()); |
| 180 if (effects_count == 1) { | 172 if (effects_count == 1) { |
| 181 effect = effects[0]; | 173 effect = effects[0]; |
| 182 } else if (effects_count > 1) { | 174 } else if (effects_count > 1) { |
| 183 effect = graph()->NewNode(common()->EffectSet(effects_count), | 175 effect = graph()->NewNode(common()->EffectSet(effects_count), |
| 184 effects_count, &effects.front()); | 176 effects_count, &effects.front()); |
| 185 } | 177 } |
| 186 | 178 |
| 187 // Add a return to connect the NTL to the end. | 179 // Add a terminate to connect the NTL to the end. |
| 188 Node* ret = graph()->NewNode( | 180 Node* terminate = graph()->NewNode(common()->Terminate(), effect, loop); |
| 189 common()->Return(), jsgraph_->UndefinedConstant(), effect, if_false); | |
| 190 | 181 |
| 191 Node* end = graph()->end(); | 182 Node* end = graph()->end(); |
| 192 if (end->opcode() == IrOpcode::kDead) { | 183 if (end->opcode() == IrOpcode::kDead) { |
| 193 // End is actually the dead node. Make a new end. | 184 // End is actually the dead node. Make a new end. |
| 194 end = graph()->NewNode(common()->End(), ret); | 185 end = graph()->NewNode(common()->End(), terminate); |
| 195 graph()->SetEnd(end); | 186 graph()->SetEnd(end); |
| 196 return end; | 187 return end; |
| 197 } | 188 } |
| 198 // End is not dead. | 189 // End is not dead. |
| 199 Node* merge = end->InputAt(0); | 190 Node* merge = end->InputAt(0); |
| 200 if (merge == NULL || merge->opcode() == IrOpcode::kDead) { | 191 if (merge == NULL || merge->opcode() == IrOpcode::kDead) { |
| 201 // The end node died; just connect end to {ret}. | 192 // The end node died; just connect end to {terminate}. |
| 202 end->ReplaceInput(0, ret); | 193 end->ReplaceInput(0, terminate); |
| 203 } else if (merge->opcode() != IrOpcode::kMerge) { | 194 } else if (merge->opcode() != IrOpcode::kMerge) { |
| 204 // Introduce a final merge node for {end->InputAt(0)} and {ret}. | 195 // Introduce a final merge node for {end->InputAt(0)} and {terminate}. |
| 205 merge = graph()->NewNode(common()->Merge(2), merge, ret); | 196 merge = graph()->NewNode(common()->Merge(2), merge, terminate); |
| 206 end->ReplaceInput(0, merge); | 197 end->ReplaceInput(0, merge); |
| 207 ret = merge; | 198 terminate = merge; |
| 208 } else { | 199 } else { |
| 209 // Append a new input to the final merge at the end. | 200 // Append a new input to the final merge at the end. |
| 210 merge->AppendInput(graph()->zone(), ret); | 201 merge->AppendInput(graph()->zone(), terminate); |
| 211 merge->set_op(common()->Merge(merge->InputCount())); | 202 merge->set_op(common()->Merge(merge->InputCount())); |
| 212 } | 203 } |
| 213 return ret; | 204 return terminate; |
| 214 } | 205 } |
| 215 | 206 |
| 216 void AddNodesReachableFromRoots(ReachabilityMarker& marked, | 207 void AddNodesReachableFromRoots(ReachabilityMarker& marked, |
| 217 NodeVector& nodes) { | 208 NodeVector& nodes) { |
| 218 jsgraph_->GetCachedNodes(&nodes); // Consider cached nodes roots. | 209 jsgraph_->GetCachedNodes(&nodes); // Consider cached nodes roots. |
| 219 Node* end = graph()->end(); | 210 Node* end = graph()->end(); |
| 220 marked.SetReachableFromEnd(end); | 211 marked.SetReachableFromEnd(end); |
| 221 if (!end->IsDead()) nodes.push_back(end); // Consider end to be a root. | 212 if (!end->IsDead()) nodes.push_back(end); // Consider end to be a root. |
| 222 for (Node* node : nodes) marked.SetReachableFromEnd(node); | 213 for (Node* node : nodes) marked.SetReachableFromEnd(node); |
| 223 AddBackwardsReachableNodes(marked, nodes, 0); | 214 AddBackwardsReachableNodes(marked, nodes, 0); |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 case IrOpcode::kIfFalse: | 592 case IrOpcode::kIfFalse: |
| 602 return impl.ReduceIfProjection(node, kFalse); | 593 return impl.ReduceIfProjection(node, kFalse); |
| 603 default: | 594 default: |
| 604 return node; | 595 return node; |
| 605 } | 596 } |
| 606 } | 597 } |
| 607 | 598 |
| 608 } // namespace compiler | 599 } // namespace compiler |
| 609 } // namespace internal | 600 } // namespace internal |
| 610 } // namespace v8 | 601 } // namespace v8 |
| OLD | NEW |