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 |