OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 <deque> | 5 #include <deque> |
6 #include <queue> | 6 #include <queue> |
7 | 7 |
8 #include "src/compiler/scheduler.h" | 8 #include "src/compiler/scheduler.h" |
9 | 9 |
10 #include "src/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 | 88 |
89 void BuildBlocks(Node* node) { | 89 void BuildBlocks(Node* node) { |
90 switch (node->opcode()) { | 90 switch (node->opcode()) { |
91 case IrOpcode::kLoop: | 91 case IrOpcode::kLoop: |
92 case IrOpcode::kMerge: | 92 case IrOpcode::kMerge: |
93 BuildBlockForNode(node); | 93 BuildBlockForNode(node); |
94 break; | 94 break; |
95 case IrOpcode::kBranch: | 95 case IrOpcode::kBranch: |
96 BuildBlocksForSuccessors(node, IrOpcode::kIfTrue, IrOpcode::kIfFalse); | 96 BuildBlocksForSuccessors(node, IrOpcode::kIfTrue, IrOpcode::kIfFalse); |
97 break; | 97 break; |
98 case IrOpcode::kCall: | |
99 if (OperatorProperties::CanLazilyDeoptimize(node->op())) { | |
100 BuildBlocksForSuccessors(node, IrOpcode::kContinuation, | |
101 IrOpcode::kLazyDeoptimization); | |
102 } | |
103 break; | |
104 default: | 98 default: |
105 break; | 99 break; |
106 } | 100 } |
107 } | 101 } |
108 | 102 |
109 void ConnectBlocks(Node* node) { | 103 void ConnectBlocks(Node* node) { |
110 switch (node->opcode()) { | 104 switch (node->opcode()) { |
111 case IrOpcode::kLoop: | 105 case IrOpcode::kLoop: |
112 case IrOpcode::kMerge: | 106 case IrOpcode::kMerge: |
113 ConnectMerge(node); | 107 ConnectMerge(node); |
114 break; | 108 break; |
115 case IrOpcode::kBranch: | 109 case IrOpcode::kBranch: |
116 scheduler_->schedule_root_nodes_.push_back(node); | 110 scheduler_->schedule_root_nodes_.push_back(node); |
117 ConnectBranch(node); | 111 ConnectBranch(node); |
118 break; | 112 break; |
119 case IrOpcode::kDeoptimize: | |
120 scheduler_->schedule_root_nodes_.push_back(node); | |
121 ConnectDeoptimize(node); | |
122 case IrOpcode::kCall: | |
123 if (OperatorProperties::CanLazilyDeoptimize(node->op())) { | |
124 scheduler_->schedule_root_nodes_.push_back(node); | |
125 ConnectCall(node); | |
126 } | |
127 break; | |
128 case IrOpcode::kReturn: | 113 case IrOpcode::kReturn: |
129 scheduler_->schedule_root_nodes_.push_back(node); | 114 scheduler_->schedule_root_nodes_.push_back(node); |
130 ConnectReturn(node); | 115 ConnectReturn(node); |
131 break; | 116 break; |
132 default: | 117 default: |
133 break; | 118 break; |
134 } | 119 } |
135 } | 120 } |
136 | 121 |
137 void BuildBlockForNode(Node* node) { | 122 void BuildBlockForNode(Node* node) { |
138 if (schedule_->block(node) == NULL) { | 123 if (schedule_->block(node) == NULL) { |
139 BasicBlock* block = schedule_->NewBasicBlock(); | 124 BasicBlock* block = schedule_->NewBasicBlock(); |
140 Trace("Create block B%d for #%d:%s\n", block->id(), node->id(), | 125 Trace("Create block B%d for #%d:%s\n", block->id(), node->id(), |
141 node->op()->mnemonic()); | 126 node->op()->mnemonic()); |
142 FixNode(block, node); | 127 FixNode(block, node); |
143 } | 128 } |
144 } | 129 } |
145 | 130 |
146 void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a, | 131 void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a, |
147 IrOpcode::Value b) { | 132 IrOpcode::Value b) { |
148 Node* successors[2]; | 133 Node* successors[2]; |
149 CollectSuccessorProjections(node, successors, a, b); | 134 CollectSuccessorProjections(node, successors, a, b); |
150 BuildBlockForNode(successors[0]); | 135 BuildBlockForNode(successors[0]); |
151 BuildBlockForNode(successors[1]); | 136 BuildBlockForNode(successors[1]); |
152 } | 137 } |
153 | 138 |
154 // Collect the branch-related projections from a node, such as IfTrue, | 139 // Collect the branch-related projections from a node, such as IfTrue, |
155 // IfFalse, Continuation, and LazyDeoptimization. | 140 // IfFalse. |
156 // TODO(titzer): consider moving this to node.h | 141 // TODO(titzer): consider moving this to node.h |
157 void CollectSuccessorProjections(Node* node, Node** buffer, | 142 void CollectSuccessorProjections(Node* node, Node** buffer, |
158 IrOpcode::Value true_opcode, | 143 IrOpcode::Value true_opcode, |
159 IrOpcode::Value false_opcode) { | 144 IrOpcode::Value false_opcode) { |
160 buffer[0] = NULL; | 145 buffer[0] = NULL; |
161 buffer[1] = NULL; | 146 buffer[1] = NULL; |
162 for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) { | 147 for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) { |
163 if ((*i)->opcode() == true_opcode) { | 148 if ((*i)->opcode() == true_opcode) { |
164 DCHECK_EQ(NULL, buffer[0]); | 149 DCHECK_EQ(NULL, buffer[0]); |
165 buffer[0] = *i; | 150 buffer[0] = *i; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 } | 184 } |
200 | 185 |
201 void ConnectMerge(Node* merge) { | 186 void ConnectMerge(Node* merge) { |
202 BasicBlock* block = schedule_->block(merge); | 187 BasicBlock* block = schedule_->block(merge); |
203 DCHECK(block != NULL); | 188 DCHECK(block != NULL); |
204 // For all of the merge's control inputs, add a goto at the end to the | 189 // For all of the merge's control inputs, add a goto at the end to the |
205 // merge's basic block. | 190 // merge's basic block. |
206 for (InputIter j = merge->inputs().begin(); j != merge->inputs().end(); | 191 for (InputIter j = merge->inputs().begin(); j != merge->inputs().end(); |
207 ++j) { | 192 ++j) { |
208 BasicBlock* predecessor_block = schedule_->block(*j); | 193 BasicBlock* predecessor_block = schedule_->block(*j); |
209 if ((*j)->opcode() != IrOpcode::kReturn && | 194 if ((*j)->opcode() != IrOpcode::kReturn) { |
210 (*j)->opcode() != IrOpcode::kDeoptimize) { | |
211 TraceConnect(merge, predecessor_block, block); | 195 TraceConnect(merge, predecessor_block, block); |
212 schedule_->AddGoto(predecessor_block, block); | 196 schedule_->AddGoto(predecessor_block, block); |
213 } | 197 } |
214 } | 198 } |
215 } | 199 } |
216 | 200 |
217 void ConnectDeoptimize(Node* deopt) { | |
218 Node* deopt_block_node = NodeProperties::GetControlInput(deopt); | |
219 BasicBlock* deopt_block = schedule_->block(deopt_block_node); | |
220 TraceConnect(deopt, deopt_block, NULL); | |
221 schedule_->AddDeoptimize(deopt_block, deopt); | |
222 } | |
223 | |
224 void ConnectReturn(Node* ret) { | 201 void ConnectReturn(Node* ret) { |
225 Node* return_block_node = NodeProperties::GetControlInput(ret); | 202 Node* return_block_node = NodeProperties::GetControlInput(ret); |
226 BasicBlock* return_block = schedule_->block(return_block_node); | 203 BasicBlock* return_block = schedule_->block(return_block_node); |
227 TraceConnect(ret, return_block, NULL); | 204 TraceConnect(ret, return_block, NULL); |
228 schedule_->AddReturn(return_block, ret); | 205 schedule_->AddReturn(return_block, ret); |
229 } | 206 } |
230 | 207 |
231 void ConnectCall(Node* call) { | |
232 Node* call_block_node = NodeProperties::GetControlInput(call); | |
233 BasicBlock* call_block = schedule_->block(call_block_node); | |
234 | |
235 BasicBlock* successor_blocks[2]; | |
236 CollectSuccessorBlocks(call, successor_blocks, IrOpcode::kContinuation, | |
237 IrOpcode::kLazyDeoptimization); | |
238 | |
239 TraceConnect(call, call_block, successor_blocks[0]); | |
240 TraceConnect(call, call_block, successor_blocks[1]); | |
241 | |
242 schedule_->AddCall(call_block, call, successor_blocks[0], | |
243 successor_blocks[1]); | |
244 } | |
245 | |
246 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { | 208 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { |
247 DCHECK_NE(NULL, block); | 209 DCHECK_NE(NULL, block); |
248 if (succ == NULL) { | 210 if (succ == NULL) { |
249 Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), | 211 Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), |
250 block->id()); | 212 block->id()); |
251 } else { | 213 } else { |
252 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), | 214 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), |
253 block->id(), succ->id()); | 215 block->id(), succ->id()); |
254 } | 216 } |
255 } | 217 } |
(...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 | 1110 |
1149 #if DEBUG | 1111 #if DEBUG |
1150 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); | 1112 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); |
1151 VerifySpecialRPO(num_loops, loops, final_order); | 1113 VerifySpecialRPO(num_loops, loops, final_order); |
1152 #endif | 1114 #endif |
1153 return final_order; | 1115 return final_order; |
1154 } | 1116 } |
1155 } | 1117 } |
1156 } | 1118 } |
1157 } // namespace v8::internal::compiler | 1119 } // namespace v8::internal::compiler |
OLD | NEW |