| 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 #ifndef V8_COMPILER_SCHEDULE_H_ | 5 #ifndef V8_COMPILER_SCHEDULE_H_ |
| 6 #define V8_COMPILER_SCHEDULE_H_ | 6 #define V8_COMPILER_SCHEDULE_H_ |
| 7 | 7 |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "src/v8.h" | 10 #include "src/v8.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 kNone, // Control not initialized yet. | 33 kNone, // Control not initialized yet. |
| 34 kGoto, // Goto a single successor block. | 34 kGoto, // Goto a single successor block. |
| 35 kBranch, // Branch if true to first successor, otherwise second. | 35 kBranch, // Branch if true to first successor, otherwise second. |
| 36 kReturn, // Return a value from this method. | 36 kReturn, // Return a value from this method. |
| 37 kThrow, // Throw an exception. | 37 kThrow, // Throw an exception. |
| 38 kCall, // Call to a possibly deoptimizing or throwing function. | 38 kCall, // Call to a possibly deoptimizing or throwing function. |
| 39 kDeoptimize // Deoptimize. | 39 kDeoptimize // Deoptimize. |
| 40 }; | 40 }; |
| 41 | 41 |
| 42 int32_t rpo_number_; // special RPO number of the block. | 42 int32_t rpo_number_; // special RPO number of the block. |
| 43 BasicBlock* dominator_; // Immediate dominator of the block. |
| 43 BasicBlock* loop_header_; // Pointer to dominating loop header basic block, | 44 BasicBlock* loop_header_; // Pointer to dominating loop header basic block, |
| 44 // NULL if none. For loop headers, this points to | 45 // NULL if none. For loop headers, this points to |
| 45 // enclosing loop header. | 46 // enclosing loop header. |
| 46 int32_t loop_depth_; // loop nesting, 0 is top-level | 47 int32_t loop_depth_; // loop nesting, 0 is top-level |
| 47 int32_t loop_end_; // end of the loop, if this block is a loop header. | 48 int32_t loop_end_; // end of the loop, if this block is a loop header. |
| 48 int32_t code_start_; // start index of arch-specific code. | 49 int32_t code_start_; // start index of arch-specific code. |
| 49 int32_t code_end_; // end index of arch-specific code. | 50 int32_t code_end_; // end index of arch-specific code. |
| 50 bool deferred_; // {true} if this block is considered the slow | 51 bool deferred_; // {true} if this block is considered the slow |
| 51 // path. | 52 // path. |
| 52 Control control_; // Control at the end of the block. | 53 Control control_; // Control at the end of the block. |
| 53 Node* control_input_; // Input value for control. | 54 Node* control_input_; // Input value for control. |
| 54 NodeVector nodes_; // nodes of this block in forward order. | 55 NodeVector nodes_; // nodes of this block in forward order. |
| 55 | 56 |
| 56 explicit BasicBlockData(Zone* zone) | 57 explicit BasicBlockData(Zone* zone) |
| 57 : rpo_number_(-1), | 58 : rpo_number_(-1), |
| 59 dominator_(NULL), |
| 58 loop_header_(NULL), | 60 loop_header_(NULL), |
| 59 loop_depth_(0), | 61 loop_depth_(0), |
| 60 loop_end_(-1), | 62 loop_end_(-1), |
| 61 code_start_(-1), | 63 code_start_(-1), |
| 62 code_end_(-1), | 64 code_end_(-1), |
| 63 deferred_(false), | 65 deferred_(false), |
| 64 control_(kNone), | 66 control_(kNone), |
| 65 control_input_(NULL), | 67 control_input_(NULL), |
| 66 nodes_(NodeVector::allocator_type(zone)) {} | 68 nodes_(NodeVector::allocator_type(zone)) {} |
| 67 | 69 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 // and ordering them within basic blocks. Prior to computing a schedule, | 156 // and ordering them within basic blocks. Prior to computing a schedule, |
| 155 // a graph has no notion of control flow ordering other than that induced | 157 // a graph has no notion of control flow ordering other than that induced |
| 156 // by the graph's dependencies. A schedule is required to generate code. | 158 // by the graph's dependencies. A schedule is required to generate code. |
| 157 class Schedule : public GenericGraph<BasicBlock> { | 159 class Schedule : public GenericGraph<BasicBlock> { |
| 158 public: | 160 public: |
| 159 explicit Schedule(Zone* zone) | 161 explicit Schedule(Zone* zone) |
| 160 : GenericGraph<BasicBlock>(zone), | 162 : GenericGraph<BasicBlock>(zone), |
| 161 zone_(zone), | 163 zone_(zone), |
| 162 all_blocks_(BasicBlockVector::allocator_type(zone)), | 164 all_blocks_(BasicBlockVector::allocator_type(zone)), |
| 163 nodeid_to_block_(BasicBlockVector::allocator_type(zone)), | 165 nodeid_to_block_(BasicBlockVector::allocator_type(zone)), |
| 164 rpo_order_(BasicBlockVector::allocator_type(zone)), | 166 rpo_order_(BasicBlockVector::allocator_type(zone)) { |
| 165 immediate_dominator_(BasicBlockVector::allocator_type(zone)) { | |
| 166 SetStart(NewBasicBlock()); // entry. | 167 SetStart(NewBasicBlock()); // entry. |
| 167 SetEnd(NewBasicBlock()); // exit. | 168 SetEnd(NewBasicBlock()); // exit. |
| 168 } | 169 } |
| 169 | 170 |
| 170 // Return the block which contains {node}, if any. | 171 // Return the block which contains {node}, if any. |
| 171 BasicBlock* block(Node* node) const { | 172 BasicBlock* block(Node* node) const { |
| 172 if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) { | 173 if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) { |
| 173 return nodeid_to_block_[node->id()]; | 174 return nodeid_to_block_[node->id()]; |
| 174 } | 175 } |
| 175 return NULL; | 176 return NULL; |
| 176 } | 177 } |
| 177 | 178 |
| 178 BasicBlock* dominator(BasicBlock* block) { | |
| 179 return immediate_dominator_[block->id()]; | |
| 180 } | |
| 181 | |
| 182 bool IsScheduled(Node* node) { | 179 bool IsScheduled(Node* node) { |
| 183 int length = static_cast<int>(nodeid_to_block_.size()); | 180 int length = static_cast<int>(nodeid_to_block_.size()); |
| 184 if (node->id() >= length) return false; | 181 if (node->id() >= length) return false; |
| 185 return nodeid_to_block_[node->id()] != NULL; | 182 return nodeid_to_block_[node->id()] != NULL; |
| 186 } | 183 } |
| 187 | 184 |
| 188 BasicBlock* GetBlockById(int block_id) { return all_blocks_[block_id]; } | 185 BasicBlock* GetBlockById(int block_id) { return all_blocks_[block_id]; } |
| 189 | 186 |
| 190 int BasicBlockCount() const { return NodeCount(); } | 187 int BasicBlockCount() const { return NodeCount(); } |
| 191 int RpoBlockCount() const { return static_cast<int>(rpo_order_.size()); } | 188 int RpoBlockCount() const { return static_cast<int>(rpo_order_.size()); } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 206 BasicBlock* block = | 203 BasicBlock* block = |
| 207 BasicBlock::New(this, 0, static_cast<BasicBlock**>(NULL)); | 204 BasicBlock::New(this, 0, static_cast<BasicBlock**>(NULL)); |
| 208 all_blocks_.push_back(block); | 205 all_blocks_.push_back(block); |
| 209 return block; | 206 return block; |
| 210 } | 207 } |
| 211 | 208 |
| 212 // BasicBlock building: records that a node will later be added to a block but | 209 // BasicBlock building: records that a node will later be added to a block but |
| 213 // doesn't actually add the node to the block. | 210 // doesn't actually add the node to the block. |
| 214 inline void PlanNode(BasicBlock* block, Node* node) { | 211 inline void PlanNode(BasicBlock* block, Node* node) { |
| 215 if (FLAG_trace_turbo_scheduler) { | 212 if (FLAG_trace_turbo_scheduler) { |
| 216 PrintF("Planning node %d for future add to block %d\n", node->id(), | 213 PrintF("Planning #%d:%s for future add to B%d\n", node->id(), |
| 217 block->id()); | 214 node->op()->mnemonic(), block->id()); |
| 218 } | 215 } |
| 219 DCHECK(this->block(node) == NULL); | 216 DCHECK(this->block(node) == NULL); |
| 220 SetBlockForNode(block, node); | 217 SetBlockForNode(block, node); |
| 221 } | 218 } |
| 222 | 219 |
| 223 // BasicBlock building: add a node to the end of the block. | 220 // BasicBlock building: add a node to the end of the block. |
| 224 inline void AddNode(BasicBlock* block, Node* node) { | 221 inline void AddNode(BasicBlock* block, Node* node) { |
| 225 if (FLAG_trace_turbo_scheduler) { | 222 if (FLAG_trace_turbo_scheduler) { |
| 226 PrintF("Adding node %d to block %d\n", node->id(), block->id()); | 223 PrintF("Adding #%d:%s to B%d\n", node->id(), node->op()->mnemonic(), |
| 224 block->id()); |
| 227 } | 225 } |
| 228 DCHECK(this->block(node) == NULL || this->block(node) == block); | 226 DCHECK(this->block(node) == NULL || this->block(node) == block); |
| 229 block->nodes_.push_back(node); | 227 block->nodes_.push_back(node); |
| 230 SetBlockForNode(block, node); | 228 SetBlockForNode(block, node); |
| 231 } | 229 } |
| 232 | 230 |
| 233 // BasicBlock building: add a goto to the end of {block}. | 231 // BasicBlock building: add a goto to the end of {block}. |
| 234 void AddGoto(BasicBlock* block, BasicBlock* succ) { | 232 void AddGoto(BasicBlock* block, BasicBlock* succ) { |
| 235 DCHECK(block->control_ == BasicBlock::kNone); | 233 DCHECK(block->control_ == BasicBlock::kNone); |
| 236 block->control_ = BasicBlock::kGoto; | 234 block->control_ = BasicBlock::kGoto; |
| 237 AddSuccessor(block, succ); | 235 AddSuccessor(block, succ); |
| 238 } | 236 } |
| 239 | 237 |
| 240 // BasicBlock building: add a (branching) call at the end of {block}. | 238 // BasicBlock building: add a (branching) call at the end of {block}. |
| 241 void AddCall(BasicBlock* block, Node* call, BasicBlock* cont_block, | 239 void AddCall(BasicBlock* block, Node* call, BasicBlock* cont_block, |
| 242 BasicBlock* deopt_block) { | 240 BasicBlock* deopt_block) { |
| 243 DCHECK(block->control_ == BasicBlock::kNone); | 241 DCHECK(block->control_ == BasicBlock::kNone); |
| 244 DCHECK(call->opcode() == IrOpcode::kCall); | 242 DCHECK(call->opcode() == IrOpcode::kCall); |
| 245 block->control_ = BasicBlock::kCall; | 243 block->control_ = BasicBlock::kCall; |
| 246 // Insert the deopt block first so that the RPO order builder picks | 244 // Insert the deopt block first so that the RPO order builder picks |
| 247 // it first (and thus it ends up late in the RPO order). | 245 // it first (and thus it ends up late in the RPO order). |
| 248 AddSuccessor(block, deopt_block); | 246 AddSuccessor(block, deopt_block); |
| 249 AddSuccessor(block, cont_block); | 247 AddSuccessor(block, cont_block); |
| 250 SetControlInput(block, call); | 248 SetControlInput(block, call); |
| 249 SetBlockForNode(block, call); |
| 251 } | 250 } |
| 252 | 251 |
| 253 // BasicBlock building: add a branch at the end of {block}. | 252 // BasicBlock building: add a branch at the end of {block}. |
| 254 void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock, | 253 void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock, |
| 255 BasicBlock* fblock) { | 254 BasicBlock* fblock) { |
| 256 DCHECK(block->control_ == BasicBlock::kNone); | 255 DCHECK(block->control_ == BasicBlock::kNone); |
| 257 DCHECK(branch->opcode() == IrOpcode::kBranch); | 256 DCHECK(branch->opcode() == IrOpcode::kBranch); |
| 258 block->control_ = BasicBlock::kBranch; | 257 block->control_ = BasicBlock::kBranch; |
| 259 AddSuccessor(block, tblock); | 258 AddSuccessor(block, tblock); |
| 260 AddSuccessor(block, fblock); | 259 AddSuccessor(block, fblock); |
| 261 SetControlInput(block, branch); | 260 SetControlInput(block, branch); |
| 261 if (branch->opcode() == IrOpcode::kBranch) { |
| 262 // TODO(titzer): require a Branch node here. (sloppy tests). |
| 263 SetBlockForNode(block, branch); |
| 264 } |
| 262 } | 265 } |
| 263 | 266 |
| 264 // BasicBlock building: add a return at the end of {block}. | 267 // BasicBlock building: add a return at the end of {block}. |
| 265 void AddReturn(BasicBlock* block, Node* input) { | 268 void AddReturn(BasicBlock* block, Node* input) { |
| 266 // TODO(titzer): require a Return node here. | |
| 267 DCHECK(block->control_ == BasicBlock::kNone); | 269 DCHECK(block->control_ == BasicBlock::kNone); |
| 268 block->control_ = BasicBlock::kReturn; | 270 block->control_ = BasicBlock::kReturn; |
| 269 SetControlInput(block, input); | 271 SetControlInput(block, input); |
| 270 if (block != end()) AddSuccessor(block, end()); | 272 if (block != end()) AddSuccessor(block, end()); |
| 273 if (input->opcode() == IrOpcode::kReturn) { |
| 274 // TODO(titzer): require a Return node here. (sloppy tests). |
| 275 SetBlockForNode(block, input); |
| 276 } |
| 271 } | 277 } |
| 272 | 278 |
| 273 // BasicBlock building: add a throw at the end of {block}. | 279 // BasicBlock building: add a throw at the end of {block}. |
| 274 void AddThrow(BasicBlock* block, Node* input) { | 280 void AddThrow(BasicBlock* block, Node* input) { |
| 275 DCHECK(block->control_ == BasicBlock::kNone); | 281 DCHECK(block->control_ == BasicBlock::kNone); |
| 276 block->control_ = BasicBlock::kThrow; | 282 block->control_ = BasicBlock::kThrow; |
| 277 SetControlInput(block, input); | 283 SetControlInput(block, input); |
| 278 if (block != end()) AddSuccessor(block, end()); | 284 if (block != end()) AddSuccessor(block, end()); |
| 279 } | 285 } |
| 280 | 286 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 309 if (node->id() >= length) { | 315 if (node->id() >= length) { |
| 310 nodeid_to_block_.resize(node->id() + 1); | 316 nodeid_to_block_.resize(node->id() + 1); |
| 311 } | 317 } |
| 312 nodeid_to_block_[node->id()] = block; | 318 nodeid_to_block_[node->id()] = block; |
| 313 } | 319 } |
| 314 | 320 |
| 315 Zone* zone_; | 321 Zone* zone_; |
| 316 BasicBlockVector all_blocks_; // All basic blocks in the schedule. | 322 BasicBlockVector all_blocks_; // All basic blocks in the schedule. |
| 317 BasicBlockVector nodeid_to_block_; // Map from node to containing block. | 323 BasicBlockVector nodeid_to_block_; // Map from node to containing block. |
| 318 BasicBlockVector rpo_order_; // Reverse-post-order block list. | 324 BasicBlockVector rpo_order_; // Reverse-post-order block list. |
| 319 BasicBlockVector immediate_dominator_; // Maps to a block's immediate | |
| 320 // dominator, indexed by block | |
| 321 // id. | |
| 322 }; | 325 }; |
| 323 | 326 |
| 324 OStream& operator<<(OStream& os, const Schedule& s); | 327 OStream& operator<<(OStream& os, const Schedule& s); |
| 325 } | 328 } |
| 326 } | 329 } |
| 327 } // namespace v8::internal::compiler | 330 } // namespace v8::internal::compiler |
| 328 | 331 |
| 329 #endif // V8_COMPILER_SCHEDULE_H_ | 332 #endif // V8_COMPILER_SCHEDULE_H_ |
| OLD | NEW |