OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/effect-control-linearizer.h" | 5 #include "src/compiler/effect-control-linearizer.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
11 #include "src/compiler/node-matchers.h" | |
11 #include "src/compiler/node-properties.h" | 12 #include "src/compiler/node-properties.h" |
12 #include "src/compiler/node.h" | 13 #include "src/compiler/node.h" |
13 #include "src/compiler/schedule.h" | 14 #include "src/compiler/schedule.h" |
14 | 15 |
15 namespace v8 { | 16 namespace v8 { |
16 namespace internal { | 17 namespace internal { |
17 namespace compiler { | 18 namespace compiler { |
18 | 19 |
19 EffectControlLinearizer::EffectControlLinearizer(JSGraph* js_graph, | 20 EffectControlLinearizer::EffectControlLinearizer(JSGraph* js_graph, |
20 Schedule* schedule, | 21 Schedule* schedule, |
21 Zone* temp_zone) | 22 Zone* temp_zone) |
22 : js_graph_(js_graph), schedule_(schedule), temp_zone_(temp_zone) {} | 23 : js_graph_(js_graph), schedule_(schedule), temp_zone_(temp_zone) {} |
23 | 24 |
24 Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); } | 25 Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); } |
25 CommonOperatorBuilder* EffectControlLinearizer::common() const { | 26 CommonOperatorBuilder* EffectControlLinearizer::common() const { |
26 return js_graph_->common(); | 27 return js_graph_->common(); |
27 } | 28 } |
28 SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const { | 29 SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const { |
29 return js_graph_->simplified(); | 30 return js_graph_->simplified(); |
30 } | 31 } |
31 MachineOperatorBuilder* EffectControlLinearizer::machine() const { | 32 MachineOperatorBuilder* EffectControlLinearizer::machine() const { |
32 return js_graph_->machine(); | 33 return js_graph_->machine(); |
33 } | 34 } |
34 | 35 |
35 namespace { | 36 namespace { |
36 | 37 |
37 struct BlockEffectControlData { | 38 struct BlockEffectControlData { |
38 Node* current_effect = nullptr; // New effect. | 39 Node* current_effect = nullptr; // New effect. |
39 Node* current_control = nullptr; // New control. | 40 Node* current_control = nullptr; // New control. |
40 Node* current_frame_state = nullptr; // New frame state. | 41 Node* current_frame_state = nullptr; // New frame state. |
41 }; | 42 }; |
42 | 43 |
44 struct BlockDataKey { | |
45 int32_t from; | |
46 int32_t to; | |
47 | |
48 BlockDataKey(int32_t from, int32_t to) : from(from), to(to) {} | |
49 BlockDataKey(BasicBlock* from, BasicBlock* to) | |
50 : from(from->rpo_number()), to(to->rpo_number()) {} | |
51 }; | |
52 | |
53 struct BlockDataKeyComparator { | |
54 bool operator()(const BlockDataKey& lhs, const BlockDataKey& rhs) const { | |
55 return std::make_pair(lhs.from, lhs.to) < std::make_pair(rhs.from, rhs.to); | |
56 } | |
57 }; | |
58 | |
59 using BlockEffectControlMap = | |
60 ZoneMap<BlockDataKey, BlockEffectControlData, BlockDataKeyComparator>; | |
61 | |
43 // Effect phis that need to be updated after the first pass. | 62 // Effect phis that need to be updated after the first pass. |
44 struct PendingEffectPhi { | 63 struct PendingEffectPhi { |
45 Node* effect_phi; | 64 Node* effect_phi; |
46 BasicBlock* block; | 65 BasicBlock* block; |
47 | 66 |
48 PendingEffectPhi(Node* effect_phi, BasicBlock* block) | 67 PendingEffectPhi(Node* effect_phi, BasicBlock* block) |
49 : effect_phi(effect_phi), block(block) {} | 68 : effect_phi(effect_phi), block(block) {} |
50 }; | 69 }; |
51 | 70 |
52 void UpdateEffectPhi(Node* node, BasicBlock* block, | 71 void UpdateEffectPhi(Node* node, BasicBlock* block, |
53 ZoneVector<BlockEffectControlData>* block_effects) { | 72 BlockEffectControlMap* block_effects) { |
54 // Update all inputs to an effect phi with the effects from the given | 73 // Update all inputs to an effect phi with the effects from the given |
55 // block->effect map. | 74 // block->effect map. |
56 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); | 75 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); |
57 DCHECK_EQ(node->op()->EffectInputCount(), block->PredecessorCount()); | 76 DCHECK_EQ(node->op()->EffectInputCount(), block->PredecessorCount()); |
58 for (int i = 0; i < node->op()->EffectInputCount(); i++) { | 77 for (int i = 0; i < node->op()->EffectInputCount(); i++) { |
59 Node* input = node->InputAt(i); | 78 Node* input = node->InputAt(i); |
60 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); | 79 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); |
61 Node* input_effect = | 80 BlockEffectControlMap::iterator it = |
62 (*block_effects)[predecessor->rpo_number()].current_effect; | 81 block_effects->find(BlockDataKey(predecessor, block)); |
82 Node* input_effect = it->second.current_effect; | |
63 if (input != input_effect) { | 83 if (input != input_effect) { |
64 node->ReplaceInput(i, input_effect); | 84 node->ReplaceInput(i, input_effect); |
65 } | 85 } |
66 } | 86 } |
67 } | 87 } |
68 | 88 |
69 void UpdateBlockControl(BasicBlock* block, | 89 void UpdateBlockControl(BasicBlock* block, |
70 ZoneVector<BlockEffectControlData>* block_effects) { | 90 BlockEffectControlMap* block_effects) { |
71 Node* control = block->NodeAt(0); | 91 Node* control = block->NodeAt(0); |
72 DCHECK(NodeProperties::IsControl(control)); | 92 DCHECK(NodeProperties::IsControl(control)); |
73 | 93 |
74 // Do not rewire the end node. | 94 // Do not rewire the end node. |
75 if (control->opcode() == IrOpcode::kEnd) return; | 95 if (control->opcode() == IrOpcode::kEnd) return; |
76 | 96 |
77 // Update all inputs to the given control node with the correct control. | 97 // Update all inputs to the given control node with the correct control. |
78 DCHECK_EQ(control->op()->ControlInputCount(), block->PredecessorCount()); | 98 DCHECK(control->opcode() == IrOpcode::kMerge || |
99 control->op()->ControlInputCount() == block->PredecessorCount()); | |
100 if (control->op()->ControlInputCount() != block->PredecessorCount()) { | |
101 return; // We already re-wired the control inputs of this node. | |
102 } | |
79 for (int i = 0; i < control->op()->ControlInputCount(); i++) { | 103 for (int i = 0; i < control->op()->ControlInputCount(); i++) { |
80 Node* input = NodeProperties::GetControlInput(control, i); | 104 Node* input = NodeProperties::GetControlInput(control, i); |
81 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); | 105 BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); |
82 Node* input_control = | 106 BlockEffectControlMap::iterator it = |
83 (*block_effects)[predecessor->rpo_number()].current_control; | 107 block_effects->find(BlockDataKey(predecessor, block)); |
108 Node* input_control = it->second.current_control; | |
84 if (input != input_control) { | 109 if (input != input_control) { |
85 NodeProperties::ReplaceControlInput(control, input_control, i); | 110 NodeProperties::ReplaceControlInput(control, input_control, i); |
86 } | 111 } |
87 } | 112 } |
88 } | 113 } |
89 | 114 |
90 bool HasIncomingBackEdges(BasicBlock* block) { | 115 bool HasIncomingBackEdges(BasicBlock* block) { |
91 for (BasicBlock* pred : block->predecessors()) { | 116 for (BasicBlock* pred : block->predecessors()) { |
92 if (pred->rpo_number() >= block->rpo_number()) { | 117 if (pred->rpo_number() >= block->rpo_number()) { |
93 return true; | 118 return true; |
(...skipping 13 matching lines...) Expand all Loading... | |
107 edge.UpdateTo(NodeProperties::GetEffectInput(node)); | 132 edge.UpdateTo(NodeProperties::GetEffectInput(node)); |
108 } else { | 133 } else { |
109 DCHECK(!NodeProperties::IsControlEdge(edge)); | 134 DCHECK(!NodeProperties::IsControlEdge(edge)); |
110 DCHECK(!NodeProperties::IsFrameStateEdge(edge)); | 135 DCHECK(!NodeProperties::IsFrameStateEdge(edge)); |
111 edge.UpdateTo(node->InputAt(0)); | 136 edge.UpdateTo(node->InputAt(0)); |
112 } | 137 } |
113 } | 138 } |
114 node->Kill(); | 139 node->Kill(); |
115 } | 140 } |
116 | 141 |
142 void TryCloneBranch(Node* node, BasicBlock* block, Graph* graph, | |
143 CommonOperatorBuilder* common, | |
144 BlockEffectControlMap* block_effects) { | |
145 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); | |
146 | |
147 // This optimization is a special case of (super)block cloning. It takes an | |
148 // input graph as shown below and clones the Branch node for every predecessor | |
149 // to the Merge, essentially removing the Merge completely. This avoids | |
150 // materializing the bit for the Phi and may offer potential for further | |
151 // branch folding optimizations (i.e. because one or more inputs to the Phi is | |
152 // a constant). Note that there may be more Phi nodes hanging off the Merge, | |
153 // but we can only a certain subset of them currently (actually only Phi and | |
154 // EffectPhi nodes whose uses have either the IfTrue or IfFalse as control | |
155 // input). | |
156 | |
157 // Control1 ... ControlN | |
158 // ^ ^ | |
159 // | | Cond1 ... CondN | |
160 // +----+ +----+ ^ ^ | |
161 // | | | | | |
162 // | | +----+ | | |
163 // Merge<--+ | +------------+ | |
164 // ^ \|/ | |
165 // | Phi | |
166 // | | | |
167 // Branch----+ | |
168 // ^ | |
169 // | | |
170 // +-----+-----+ | |
171 // | | | |
172 // IfTrue IfFalse | |
173 // ^ ^ | |
174 // | | | |
175 | |
176 // The resulting graph (modulo the Phi and EffectPhi nodes) looks like this: | |
177 | |
178 // Control1 Cond1 ... ControlN CondN | |
179 // ^ ^ ^ ^ | |
180 // \ / \ / | |
181 // Branch ... Branch | |
182 // ^ ^ | |
183 // | | | |
184 // +---+---+ +---+----+ | |
185 // | | | | | |
186 // IfTrue IfFalse ... IfTrue IfFalse | |
187 // ^ ^ ^ ^ | |
188 // | | | | | |
189 // +--+ +-------------+ | | |
190 // | | +--------------+ +--+ | |
191 // | | | | | |
192 // Merge Merge | |
193 // ^ ^ | |
194 // | | | |
195 | |
196 Node* branch = node; | |
197 Node* cond = NodeProperties::GetValueInput(branch, 0); | |
198 if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return; | |
199 Node* merge = NodeProperties::GetControlInput(branch); | |
200 if (merge->opcode() != IrOpcode::kMerge || | |
201 NodeProperties::GetControlInput(cond) != merge) { | |
202 return; | |
203 } | |
204 // Grab the IfTrue/IfFalse projections of the Branch. | |
205 BranchMatcher matcher(branch); | |
206 // Check/collect other Phi/EffectPhi nodes hanging off the Merge. | |
207 NodeVector phis(graph->zone()); | |
208 for (Node* const use : merge->uses()) { | |
209 if (use == branch || use == cond) continue; | |
210 // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the | |
211 // Merge. Ideally, we would just clone the nodes (and everything that | |
212 // depends on it to some distant join point), but that requires knowledge | |
213 // about dominance/post-dominance. | |
214 if (!NodeProperties::IsPhi(use)) return; | |
215 for (Edge edge : use->use_edges()) { | |
216 // Right now we can only handle Phi/EffectPhi nodes whose uses are | |
217 // directly control-dependend on either the IfTrue or the IfFalse | |
218 // successor, because we know exactly how to update those uses. | |
219 if (edge.from()->op()->ControlInputCount() != 1) return; | |
220 Node* control = NodeProperties::GetControlInput(edge.from()); | |
221 if (NodeProperties::IsPhi(edge.from())) { | |
222 control = NodeProperties::GetControlInput(control, edge.index()); | |
223 } | |
224 if (control != matcher.IfTrue() && control != matcher.IfFalse()) return; | |
225 } | |
226 phis.push_back(use); | |
227 } | |
228 BranchHint const hint = BranchHintOf(branch->op()); | |
229 int const input_count = merge->op()->ControlInputCount(); | |
230 DCHECK_LE(1, input_count); | |
231 Node** const inputs = graph->zone()->NewArray<Node*>(2 * input_count); | |
232 Node** const merge_true_inputs = &inputs[0]; | |
233 Node** const merge_false_inputs = &inputs[input_count]; | |
234 for (int index = 0; index < input_count; ++index) { | |
235 Node* cond1 = NodeProperties::GetValueInput(cond, index); | |
236 Node* control1 = NodeProperties::GetControlInput(merge, index); | |
237 Node* branch1 = graph->NewNode(common->Branch(hint), cond1, control1); | |
238 merge_true_inputs[index] = graph->NewNode(common->IfTrue(), branch1); | |
239 merge_false_inputs[index] = graph->NewNode(common->IfFalse(), branch1); | |
240 } | |
241 Node* const merge_true = matcher.IfTrue(); | |
242 Node* const merge_false = matcher.IfFalse(); | |
243 merge_true->TrimInputCount(0); | |
244 merge_false->TrimInputCount(0); | |
245 for (int i = 0; i < input_count; ++i) { | |
246 merge_true->AppendInput(graph->zone(), merge_true_inputs[i]); | |
247 merge_false->AppendInput(graph->zone(), merge_false_inputs[i]); | |
248 } | |
249 DCHECK_EQ(2, block->SuccessorCount()); | |
250 NodeProperties::ChangeOp(matcher.IfTrue(), common->Merge(input_count)); | |
251 NodeProperties::ChangeOp(matcher.IfFalse(), common->Merge(input_count)); | |
252 int const true_index = | |
253 block->SuccessorAt(0)->NodeAt(0) == matcher.IfTrue() ? 0 : 1; | |
254 BlockEffectControlData* true_block_data = | |
255 &(*block_effects)[{block, block->SuccessorAt(true_index)}]; | |
256 BlockEffectControlData* false_block_data = | |
257 &(*block_effects)[{block, block->SuccessorAt(true_index ^ 1)}]; | |
258 for (Node* const phi : phis) { | |
259 for (int index = 0; index < input_count; ++index) { | |
260 inputs[index] = phi->InputAt(index); | |
261 } | |
262 inputs[input_count] = merge_true; | |
263 Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs); | |
264 inputs[input_count] = merge_false; | |
265 Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs); | |
266 if (phi->UseCount() == 0) { | |
267 DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi); | |
268 DCHECK_EQ(input_count, block->SuccessorCount()); | |
269 } else { | |
270 for (Edge edge : phi->use_edges()) { | |
271 Node* control = NodeProperties::GetControlInput(edge.from()); | |
272 if (NodeProperties::IsPhi(edge.from())) { | |
273 control = NodeProperties::GetControlInput(control, edge.index()); | |
274 } | |
275 DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse()); | |
276 edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false); | |
277 } | |
278 } | |
279 true_block_data->current_effect = phi_true; | |
280 false_block_data->current_effect = phi_false; | |
281 phi->Kill(); | |
282 } | |
283 // Fix up IfTrue and IfFalse and kill all dead nodes. | |
284 if (branch == block->control_input()) { | |
285 true_block_data->current_control = merge_true; | |
286 false_block_data->current_control = merge_false; | |
287 } | |
288 branch->Kill(); | |
289 cond->Kill(); | |
290 merge->Kill(); | |
291 } | |
117 } // namespace | 292 } // namespace |
118 | 293 |
119 void EffectControlLinearizer::Run() { | 294 void EffectControlLinearizer::Run() { |
120 ZoneVector<BlockEffectControlData> block_effects(temp_zone()); | 295 BlockEffectControlMap block_effects(temp_zone()); |
121 ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone()); | 296 ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone()); |
122 ZoneVector<BasicBlock*> pending_block_controls(temp_zone()); | 297 ZoneVector<BasicBlock*> pending_block_controls(temp_zone()); |
123 block_effects.resize(schedule()->RpoBlockCount()); | |
124 NodeVector inputs_buffer(temp_zone()); | 298 NodeVector inputs_buffer(temp_zone()); |
125 | 299 |
126 for (BasicBlock* block : *(schedule()->rpo_order())) { | 300 for (BasicBlock* block : *(schedule()->rpo_order())) { |
301 for (BasicBlock* successor : block->successors()) { | |
302 block_effects[BlockDataKey(block, successor)] = BlockEffectControlData(); | |
303 } | |
127 size_t instr = 0; | 304 size_t instr = 0; |
128 | 305 |
129 // The control node should be the first. | 306 // The control node should be the first. |
130 Node* control = block->NodeAt(instr); | 307 Node* control = block->NodeAt(instr); |
131 DCHECK(NodeProperties::IsControl(control)); | 308 DCHECK(NodeProperties::IsControl(control)); |
132 // Update the control inputs. | 309 // Update the control inputs. |
133 if (HasIncomingBackEdges(block)) { | 310 if (HasIncomingBackEdges(block)) { |
134 // If there are back edges, we need to update later because we have not | 311 // If there are back edges, we need to update later because we have not |
135 // computed the control yet. This should only happen for loops. | 312 // computed the control yet. This should only happen for loops. |
136 DCHECK_EQ(IrOpcode::kLoop, control->opcode()); | 313 DCHECK_EQ(IrOpcode::kLoop, control->opcode()); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 if (block == schedule()->start()) { | 356 if (block == schedule()->start()) { |
180 // Start block => effect is start. | 357 // Start block => effect is start. |
181 DCHECK_EQ(graph()->start(), control); | 358 DCHECK_EQ(graph()->start(), control); |
182 effect = graph()->start(); | 359 effect = graph()->start(); |
183 } else if (control->opcode() == IrOpcode::kEnd) { | 360 } else if (control->opcode() == IrOpcode::kEnd) { |
184 // End block is just a dummy, no effect needed. | 361 // End block is just a dummy, no effect needed. |
185 DCHECK_EQ(BasicBlock::kNone, block->control()); | 362 DCHECK_EQ(BasicBlock::kNone, block->control()); |
186 DCHECK_EQ(1u, block->size()); | 363 DCHECK_EQ(1u, block->size()); |
187 effect = nullptr; | 364 effect = nullptr; |
188 } else { | 365 } else { |
189 // If all the predecessors have the same effect, we can use it | 366 // If all the predecessors have the same effect, we can use it as our |
190 // as our current effect. | 367 // current effect. |
191 int rpo_number = block->PredecessorAt(0)->rpo_number(); | 368 effect = block_effects[BlockDataKey(block->PredecessorAt(0), block)] |
192 effect = block_effects[rpo_number].current_effect; | 369 .current_effect; |
193 for (size_t i = 1; i < block->PredecessorCount(); i++) { | 370 for (size_t i = 1; i < block->PredecessorCount(); ++i) { |
194 int rpo_number = block->PredecessorAt(i)->rpo_number(); | 371 if (block_effects[BlockDataKey(block->PredecessorAt(i), block)] |
195 if (block_effects[rpo_number].current_effect != effect) { | 372 .current_effect != effect) { |
196 effect = nullptr; | 373 effect = nullptr; |
197 break; | 374 break; |
198 } | 375 } |
199 } | 376 } |
200 if (effect == nullptr) { | 377 if (effect == nullptr) { |
201 DCHECK_NE(IrOpcode::kIfException, control->opcode()); | 378 DCHECK_NE(IrOpcode::kIfException, control->opcode()); |
202 // The input blocks do not have the same effect. We have | 379 // The input blocks do not have the same effect. We have |
203 // to create an effect phi node. | 380 // to create an effect phi node. |
204 inputs_buffer.clear(); | 381 inputs_buffer.clear(); |
205 inputs_buffer.resize(block->PredecessorCount(), graph()->start()); | 382 inputs_buffer.resize(block->PredecessorCount(), graph()->start()); |
(...skipping 19 matching lines...) Expand all Loading... | |
225 | 402 |
226 // The frame state at block entry is determined by the frame states leaving | 403 // The frame state at block entry is determined by the frame states leaving |
227 // all predecessors. In case there is no frame state dominating this block, | 404 // all predecessors. In case there is no frame state dominating this block, |
228 // we can rely on a checkpoint being present before the next deoptimization. | 405 // we can rely on a checkpoint being present before the next deoptimization. |
229 // TODO(mstarzinger): Eventually we will need to go hunt for a frame state | 406 // TODO(mstarzinger): Eventually we will need to go hunt for a frame state |
230 // once deoptimizing nodes roam freely through the schedule. | 407 // once deoptimizing nodes roam freely through the schedule. |
231 Node* frame_state = nullptr; | 408 Node* frame_state = nullptr; |
232 if (block != schedule()->start()) { | 409 if (block != schedule()->start()) { |
233 // If all the predecessors have the same effect, we can use it | 410 // If all the predecessors have the same effect, we can use it |
234 // as our current effect. | 411 // as our current effect. |
235 int rpo_number = block->PredecessorAt(0)->rpo_number(); | 412 frame_state = block_effects[BlockDataKey(block->PredecessorAt(0), block)] |
236 frame_state = block_effects[rpo_number].current_frame_state; | 413 .current_frame_state; |
237 for (size_t i = 1; i < block->PredecessorCount(); i++) { | 414 for (size_t i = 1; i < block->PredecessorCount(); i++) { |
238 int rpo_number = block->PredecessorAt(i)->rpo_number(); | 415 if (block_effects[BlockDataKey(block->PredecessorAt(i), block)] |
239 if (block_effects[rpo_number].current_frame_state != frame_state) { | 416 .current_frame_state != frame_state) { |
240 frame_state = nullptr; | 417 frame_state = nullptr; |
241 break; | 418 break; |
242 } | 419 } |
243 } | 420 } |
244 } | 421 } |
245 | 422 |
246 // Process the ordinary instructions. | 423 // Process the ordinary instructions. |
247 for (; instr < block->NodeCount(); instr++) { | 424 for (; instr < block->NodeCount(); instr++) { |
248 Node* node = block->NodeAt(instr); | 425 Node* node = block->NodeAt(instr); |
249 ProcessNode(node, &frame_state, &effect, &control); | 426 ProcessNode(node, &frame_state, &effect, &control); |
250 } | 427 } |
251 | 428 |
252 switch (block->control()) { | 429 switch (block->control()) { |
253 case BasicBlock::kGoto: | 430 case BasicBlock::kGoto: |
254 case BasicBlock::kNone: | 431 case BasicBlock::kNone: |
255 break; | 432 break; |
256 | 433 |
257 case BasicBlock::kCall: | 434 case BasicBlock::kCall: |
258 case BasicBlock::kTailCall: | 435 case BasicBlock::kTailCall: |
259 case BasicBlock::kBranch: | 436 case BasicBlock::kBranch: |
260 case BasicBlock::kSwitch: | 437 case BasicBlock::kSwitch: |
261 case BasicBlock::kReturn: | 438 case BasicBlock::kReturn: |
262 case BasicBlock::kDeoptimize: | 439 case BasicBlock::kDeoptimize: |
263 case BasicBlock::kThrow: | 440 case BasicBlock::kThrow: { |
264 ProcessNode(block->control_input(), &frame_state, &effect, &control); | 441 ProcessNode(block->control_input(), &frame_state, &effect, &control); |
265 break; | 442 if (block->control() == BasicBlock::kBranch) { |
443 TryCloneBranch(block->control_input(), block, graph(), common(), | |
444 &block_effects); | |
445 } | |
446 } break; | |
Jarin
2016/07/12 12:58:53
The break should go into the braces.
In fact, co
epertoso
2016/07/12 14:59:01
Done.
| |
266 } | 447 } |
267 | 448 |
268 // Store the effect for later use. | 449 // Store the effect, control and frame state for later use. |
269 block_effects[block->rpo_number()].current_effect = effect; | 450 for (BasicBlock* successor : block->successors()) { |
270 block_effects[block->rpo_number()].current_control = control; | 451 BlockEffectControlData& data = |
271 block_effects[block->rpo_number()].current_frame_state = frame_state; | 452 block_effects[BlockDataKey(block, successor)]; |
453 if (data.current_effect == nullptr) { | |
454 data.current_effect = effect; | |
455 } | |
456 if (data.current_control == nullptr) { | |
457 data.current_control = control; | |
458 } | |
459 data.current_frame_state = frame_state; | |
460 } | |
272 } | 461 } |
273 | 462 |
274 // Update the incoming edges of the effect phis that could not be processed | 463 // Update the incoming edges of the effect phis that could not be processed |
275 // during the first pass (because they could have incoming back edges). | 464 // during the first pass (because they could have incoming back edges). |
276 for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) { | 465 for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) { |
277 UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block, | 466 UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block, |
278 &block_effects); | 467 &block_effects); |
279 } | 468 } |
280 for (BasicBlock* pending_block_control : pending_block_controls) { | 469 for (BasicBlock* pending_block_control : pending_block_controls) { |
281 UpdateBlockControl(pending_block_control, &block_effects); | 470 UpdateBlockControl(pending_block_control, &block_effects); |
(...skipping 1586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1868 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 2057 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
1869 Operator::kNoThrow); | 2058 Operator::kNoThrow); |
1870 to_number_operator_.set(common()->Call(desc)); | 2059 to_number_operator_.set(common()->Call(desc)); |
1871 } | 2060 } |
1872 return to_number_operator_.get(); | 2061 return to_number_operator_.get(); |
1873 } | 2062 } |
1874 | 2063 |
1875 } // namespace compiler | 2064 } // namespace compiler |
1876 } // namespace internal | 2065 } // namespace internal |
1877 } // namespace v8 | 2066 } // namespace v8 |
OLD | NEW |