| 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 |