| 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" |
| 11 | 11 |
| 12 #include "src/compiler/generic-algorithm.h" | |
| 13 #include "src/compiler/generic-graph.h" | |
| 14 #include "src/compiler/generic-node.h" | |
| 15 #include "src/compiler/generic-node-inl.h" | |
| 16 #include "src/compiler/node.h" | 12 #include "src/compiler/node.h" |
| 17 #include "src/compiler/opcodes.h" | 13 #include "src/compiler/opcodes.h" |
| 18 #include "src/zone.h" | 14 #include "src/zone.h" |
| 19 | 15 |
| 20 namespace v8 { | 16 namespace v8 { |
| 21 namespace internal { | 17 namespace internal { |
| 22 namespace compiler { | 18 namespace compiler { |
| 23 | 19 |
| 24 class BasicBlock; | 20 class BasicBlock; |
| 25 class BasicBlockInstrumentor; | 21 class BasicBlockInstrumentor; |
| 26 class Graph; | 22 class Graph; |
| 27 class ConstructScheduleData; | 23 class ConstructScheduleData; |
| 28 class CodeGenerator; // Because of a namespace bug in clang. | 24 class CodeGenerator; // Because of a namespace bug in clang. |
| 29 | 25 |
| 30 class BasicBlockData { | 26 // A basic block contains an ordered list of nodes and ends with a control |
| 27 // node. Note that if a basic block has phis, then all phis must appear as the |
| 28 // first nodes in the block. |
| 29 class BasicBlock FINAL : public ZoneObject { |
| 31 public: | 30 public: |
| 32 // Possible control nodes that can end a block. | 31 // Possible control nodes that can end a block. |
| 33 enum Control { | 32 enum Control { |
| 34 kNone, // Control not initialized yet. | 33 kNone, // Control not initialized yet. |
| 35 kGoto, // Goto a single successor block. | 34 kGoto, // Goto a single successor block. |
| 36 kBranch, // Branch if true to first successor, otherwise second. | 35 kBranch, // Branch if true to first successor, otherwise second. |
| 37 kReturn, // Return a value from this method. | 36 kReturn, // Return a value from this method. |
| 38 kThrow // Throw an exception. | 37 kThrow // Throw an exception. |
| 39 }; | 38 }; |
| 40 | 39 |
| 41 int32_t rpo_number_; // special RPO number of the block. | 40 class Id { |
| 42 BasicBlock* dominator_; // Immediate dominator of the block. | 41 public: |
| 43 BasicBlock* loop_header_; // Pointer to dominating loop header basic block, | 42 int ToInt() const { return static_cast<int>(index_); } |
| 44 // NULL if none. For loop headers, this points to | 43 size_t ToSize() const { return index_; } |
| 45 // enclosing loop header. | 44 static Id FromSize(size_t index) { return Id(index); } |
| 46 int32_t loop_depth_; // loop nesting, 0 is top-level | 45 static Id FromInt(int index) { return Id(static_cast<size_t>(index)); } |
| 47 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_end_; // end index of arch-specific code. | |
| 50 bool deferred_; // {true} if this block is considered the slow | |
| 51 // path. | |
| 52 Control control_; // Control at the end of the block. | |
| 53 Node* control_input_; // Input value for control. | |
| 54 NodeVector nodes_; // nodes of this block in forward order. | |
| 55 | 46 |
| 56 explicit BasicBlockData(Zone* zone) | 47 private: |
| 57 : rpo_number_(-1), | 48 explicit Id(size_t index) : index_(index) {} |
| 58 dominator_(NULL), | 49 size_t index_; |
| 59 loop_header_(NULL), | 50 }; |
| 60 loop_depth_(0), | |
| 61 loop_end_(-1), | |
| 62 code_start_(-1), | |
| 63 code_end_(-1), | |
| 64 deferred_(false), | |
| 65 control_(kNone), | |
| 66 control_input_(NULL), | |
| 67 nodes_(zone) {} | |
| 68 | 51 |
| 69 inline bool IsLoopHeader() const { return loop_end_ >= 0; } | 52 BasicBlock(Zone* zone, Id id); |
| 70 inline bool LoopContains(BasicBlockData* block) const { | 53 |
| 71 // RPO numbers must be initialized. | 54 Id id() const { return id_; } |
| 72 DCHECK(rpo_number_ >= 0); | 55 |
| 73 DCHECK(block->rpo_number_ >= 0); | 56 // Instruction indexes (used by the register allocator). |
| 74 if (loop_end_ < 0) return false; // This is not a loop. | |
| 75 return block->rpo_number_ >= rpo_number_ && block->rpo_number_ < loop_end_; | |
| 76 } | |
| 77 int first_instruction_index() { | 57 int first_instruction_index() { |
| 78 DCHECK(code_start_ >= 0); | 58 DCHECK(code_start_ >= 0); |
| 79 DCHECK(code_end_ > 0); | 59 DCHECK(code_end_ > 0); |
| 80 DCHECK(code_end_ >= code_start_); | 60 DCHECK(code_end_ >= code_start_); |
| 81 return code_start_; | 61 return code_start_; |
| 82 } | 62 } |
| 83 int last_instruction_index() { | 63 int last_instruction_index() { |
| 84 DCHECK(code_start_ >= 0); | 64 DCHECK(code_start_ >= 0); |
| 85 DCHECK(code_end_ > 0); | 65 DCHECK(code_end_ > 0); |
| 86 DCHECK(code_end_ >= code_start_); | 66 DCHECK(code_end_ >= code_start_); |
| 87 return code_end_ - 1; | 67 return code_end_ - 1; |
| 88 } | 68 } |
| 89 }; | |
| 90 | 69 |
| 91 OStream& operator<<(OStream& os, const BasicBlockData::Control& c); | 70 // Predecessors and successors. |
| 71 typedef ZoneVector<BasicBlock*> Predecessors; |
| 72 Predecessors::iterator predecessors_begin() { return predecessors_.begin(); } |
| 73 Predecessors::iterator predecessors_end() { return predecessors_.end(); } |
| 74 size_t PredecessorCount() const { return predecessors_.size(); } |
| 75 BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; } |
| 76 size_t PredecessorIndexOf(BasicBlock* predecessor); |
| 77 void AddPredecessor(BasicBlock* predecessor); |
| 92 | 78 |
| 93 // A basic block contains an ordered list of nodes and ends with a control | 79 typedef ZoneVector<BasicBlock*> Successors; |
| 94 // node. Note that if a basic block has phis, then all phis must appear as the | 80 Successors::iterator successors_begin() { return successors_.begin(); } |
| 95 // first nodes in the block. | 81 Successors::iterator successors_end() { return successors_.end(); } |
| 96 class BasicBlock FINAL : public GenericNode<BasicBlockData, BasicBlock> { | 82 size_t SuccessorCount() const { return successors_.size(); } |
| 97 public: | 83 BasicBlock* SuccessorAt(size_t index) { return successors_[index]; } |
| 98 BasicBlock(GenericGraphBase* graph, int input_count) | 84 void AddSuccessor(BasicBlock* successor); |
| 99 : GenericNode<BasicBlockData, BasicBlock>(graph, input_count) {} | |
| 100 | 85 |
| 101 typedef Uses Successors; | 86 // Nodes in the basic block. |
| 102 typedef Inputs Predecessors; | 87 Node* NodeAt(size_t index) { return nodes_[index]; } |
| 103 | 88 size_t NodeCount() const { return nodes_.size(); } |
| 104 Successors successors() { return static_cast<Successors>(uses()); } | |
| 105 Predecessors predecessors() { return static_cast<Predecessors>(inputs()); } | |
| 106 | |
| 107 int PredecessorCount() { return InputCount(); } | |
| 108 BasicBlock* PredecessorAt(int index) { return InputAt(index); } | |
| 109 | |
| 110 int SuccessorCount() { return UseCount(); } | |
| 111 BasicBlock* SuccessorAt(int index) { return UseAt(index); } | |
| 112 | |
| 113 int PredecessorIndexOf(BasicBlock* predecessor) { | |
| 114 BasicBlock::Predecessors predecessors = this->predecessors(); | |
| 115 for (BasicBlock::Predecessors::iterator i = predecessors.begin(); | |
| 116 i != predecessors.end(); ++i) { | |
| 117 if (*i == predecessor) return i.index(); | |
| 118 } | |
| 119 return -1; | |
| 120 } | |
| 121 | |
| 122 inline BasicBlock* loop_header() { | |
| 123 return static_cast<BasicBlock*>(loop_header_); | |
| 124 } | |
| 125 inline BasicBlock* ContainingLoop() { | |
| 126 if (IsLoopHeader()) return this; | |
| 127 return static_cast<BasicBlock*>(loop_header_); | |
| 128 } | |
| 129 | 89 |
| 130 typedef NodeVector::iterator iterator; | 90 typedef NodeVector::iterator iterator; |
| 131 iterator begin() { return nodes_.begin(); } | 91 iterator begin() { return nodes_.begin(); } |
| 132 iterator end() { return nodes_.end(); } | 92 iterator end() { return nodes_.end(); } |
| 133 | 93 |
| 134 typedef NodeVector::const_iterator const_iterator; | 94 typedef NodeVector::const_iterator const_iterator; |
| 135 const_iterator begin() const { return nodes_.begin(); } | 95 const_iterator begin() const { return nodes_.begin(); } |
| 136 const_iterator end() const { return nodes_.end(); } | 96 const_iterator end() const { return nodes_.end(); } |
| 137 | 97 |
| 138 typedef NodeVector::reverse_iterator reverse_iterator; | 98 typedef NodeVector::reverse_iterator reverse_iterator; |
| 139 reverse_iterator rbegin() { return nodes_.rbegin(); } | 99 reverse_iterator rbegin() { return nodes_.rbegin(); } |
| 140 reverse_iterator rend() { return nodes_.rend(); } | 100 reverse_iterator rend() { return nodes_.rend(); } |
| 141 | 101 |
| 102 void AddNode(Node* node); |
| 103 template <class InputIterator> |
| 104 void InsertNodes(iterator insertion_point, InputIterator insertion_start, |
| 105 InputIterator insertion_end) { |
| 106 nodes_.insert(insertion_point, insertion_start, insertion_end); |
| 107 } |
| 108 |
| 109 // Accessors. |
| 110 Control control() const { return control_; } |
| 111 void set_control(Control control); |
| 112 |
| 113 Node* control_input() const { return control_input_; } |
| 114 void set_control_input(Node* control_input); |
| 115 |
| 116 BasicBlock* dominator() const { return dominator_; } |
| 117 void set_dominator(BasicBlock* dominator); |
| 118 |
| 119 BasicBlock* loop_header() const { return loop_header_; } |
| 120 void set_loop_header(BasicBlock* loop_header); |
| 121 |
| 122 int32_t loop_depth() const { return loop_depth_; } |
| 123 void set_loop_depth(int32_t loop_depth); |
| 124 |
| 125 int32_t loop_end() const { return loop_end_; } |
| 126 void set_loop_end(int32_t loop_end); |
| 127 |
| 128 int32_t rpo_number() const { return rpo_number_; } |
| 129 void set_rpo_number(int32_t rpo_number); |
| 130 |
| 131 int32_t code_start() const { return code_start_; } |
| 132 void set_code_start(int32_t start); |
| 133 |
| 134 int32_t code_end() const { return code_end_; } |
| 135 void set_code_end(int32_t end); |
| 136 |
| 137 bool deferred() const { return deferred_; } |
| 138 |
| 139 // Loop membership helpers. |
| 140 inline bool IsLoopHeader() const { return loop_end_ >= 0; } |
| 141 bool LoopContains(BasicBlock* block) const; |
| 142 BasicBlock* ContainingLoop(); |
| 143 |
| 142 private: | 144 private: |
| 145 int32_t rpo_number_; // special RPO number of the block. |
| 146 BasicBlock* dominator_; // Immediate dominator of the block. |
| 147 BasicBlock* loop_header_; // Pointer to dominating loop header basic block, |
| 148 // NULL if none. For loop headers, this points to |
| 149 // enclosing loop header. |
| 150 int32_t loop_depth_; // loop nesting, 0 is top-level |
| 151 int32_t loop_end_; // end of the loop, if this block is a loop header. |
| 152 int32_t code_start_; // start index of arch-specific code. |
| 153 int32_t code_end_; // end index of arch-specific code. |
| 154 bool deferred_; // {true} if this block is considered the slow |
| 155 // path. |
| 156 Control control_; // Control at the end of the block. |
| 157 Node* control_input_; // Input value for control. |
| 158 NodeVector nodes_; // nodes of this block in forward order. |
| 159 |
| 160 Successors successors_; |
| 161 Predecessors predecessors_; |
| 162 Id id_; |
| 163 |
| 143 DISALLOW_COPY_AND_ASSIGN(BasicBlock); | 164 DISALLOW_COPY_AND_ASSIGN(BasicBlock); |
| 144 }; | 165 }; |
| 145 | 166 |
| 146 typedef GenericGraphVisit::NullNodeVisitor<BasicBlockData, BasicBlock> | 167 OStream& operator<<(OStream& os, const BasicBlock::Control& c); |
| 147 NullBasicBlockVisitor; | 168 OStream& operator<<(OStream& os, const BasicBlock::Id& id); |
| 148 | 169 |
| 149 typedef ZoneVector<BasicBlock*> BasicBlockVector; | 170 typedef ZoneVector<BasicBlock*> BasicBlockVector; |
| 150 typedef BasicBlockVector::iterator BasicBlockVectorIter; | 171 typedef BasicBlockVector::iterator BasicBlockVectorIter; |
| 151 typedef BasicBlockVector::reverse_iterator BasicBlockVectorRIter; | 172 typedef BasicBlockVector::reverse_iterator BasicBlockVectorRIter; |
| 152 | 173 |
| 153 // A schedule represents the result of assigning nodes to basic blocks | 174 // A schedule represents the result of assigning nodes to basic blocks |
| 154 // and ordering them within basic blocks. Prior to computing a schedule, | 175 // 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 | 176 // 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. | 177 // by the graph's dependencies. A schedule is required to generate code. |
| 157 class Schedule : public GenericGraph<BasicBlock> { | 178 class Schedule FINAL : public ZoneObject { |
| 158 public: | 179 public: |
| 159 explicit Schedule(Zone* zone, size_t node_count_hint = 0) | 180 explicit Schedule(Zone* zone, size_t node_count_hint = 0); |
| 160 : GenericGraph<BasicBlock>(zone), | |
| 161 zone_(zone), | |
| 162 all_blocks_(zone), | |
| 163 nodeid_to_block_(zone), | |
| 164 rpo_order_(zone) { | |
| 165 SetStart(NewBasicBlock()); // entry. | |
| 166 SetEnd(NewBasicBlock()); // exit. | |
| 167 nodeid_to_block_.reserve(node_count_hint); | |
| 168 } | |
| 169 | 181 |
| 170 // Return the block which contains {node}, if any. | 182 // Return the block which contains {node}, if any. |
| 171 BasicBlock* block(Node* node) const { | 183 BasicBlock* block(Node* node) const; |
| 172 if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) { | |
| 173 return nodeid_to_block_[node->id()]; | |
| 174 } | |
| 175 return NULL; | |
| 176 } | |
| 177 | 184 |
| 178 bool IsScheduled(Node* node) { | 185 bool IsScheduled(Node* node); |
| 179 int length = static_cast<int>(nodeid_to_block_.size()); | 186 BasicBlock* GetBlockById(BasicBlock::Id block_id); |
| 180 if (node->id() >= length) return false; | |
| 181 return nodeid_to_block_[node->id()] != NULL; | |
| 182 } | |
| 183 | 187 |
| 184 BasicBlock* GetBlockById(int block_id) { return all_blocks_[block_id]; } | 188 size_t BasicBlockCount() const { return all_blocks_.size(); } |
| 185 | 189 size_t RpoBlockCount() const { return rpo_order_.size(); } |
| 186 int BasicBlockCount() const { return NodeCount(); } | |
| 187 int RpoBlockCount() const { return static_cast<int>(rpo_order_.size()); } | |
| 188 | |
| 189 typedef ContainerPointerWrapper<BasicBlockVector> BasicBlocks; | |
| 190 | |
| 191 // Return a list of all the blocks in the schedule, in arbitrary order. | |
| 192 BasicBlocks all_blocks() { return BasicBlocks(&all_blocks_); } | |
| 193 | 190 |
| 194 // Check if nodes {a} and {b} are in the same block. | 191 // Check if nodes {a} and {b} are in the same block. |
| 195 inline bool SameBasicBlock(Node* a, Node* b) const { | 192 bool SameBasicBlock(Node* a, Node* b) const; |
| 196 BasicBlock* block = this->block(a); | |
| 197 return block != NULL && block == this->block(b); | |
| 198 } | |
| 199 | 193 |
| 200 // BasicBlock building: create a new block. | 194 // BasicBlock building: create a new block. |
| 201 inline BasicBlock* NewBasicBlock() { | 195 BasicBlock* NewBasicBlock(); |
| 202 BasicBlock* block = | |
| 203 BasicBlock::New(this, 0, static_cast<BasicBlock**>(NULL)); | |
| 204 all_blocks_.push_back(block); | |
| 205 return block; | |
| 206 } | |
| 207 | 196 |
| 208 // BasicBlock building: records that a node will later be added to a block but | 197 // BasicBlock building: records that a node will later be added to a block but |
| 209 // doesn't actually add the node to the block. | 198 // doesn't actually add the node to the block. |
| 210 inline void PlanNode(BasicBlock* block, Node* node) { | 199 void PlanNode(BasicBlock* block, Node* node); |
| 211 if (FLAG_trace_turbo_scheduler) { | |
| 212 PrintF("Planning #%d:%s for future add to B%d\n", node->id(), | |
| 213 node->op()->mnemonic(), block->id()); | |
| 214 } | |
| 215 DCHECK(this->block(node) == NULL); | |
| 216 SetBlockForNode(block, node); | |
| 217 } | |
| 218 | 200 |
| 219 // BasicBlock building: add a node to the end of the block. | 201 // BasicBlock building: add a node to the end of the block. |
| 220 inline void AddNode(BasicBlock* block, Node* node) { | 202 void AddNode(BasicBlock* block, Node* node); |
| 221 if (FLAG_trace_turbo_scheduler) { | |
| 222 PrintF("Adding #%d:%s to B%d\n", node->id(), node->op()->mnemonic(), | |
| 223 block->id()); | |
| 224 } | |
| 225 DCHECK(this->block(node) == NULL || this->block(node) == block); | |
| 226 block->nodes_.push_back(node); | |
| 227 SetBlockForNode(block, node); | |
| 228 } | |
| 229 | 203 |
| 230 // BasicBlock building: add a goto to the end of {block}. | 204 // BasicBlock building: add a goto to the end of {block}. |
| 231 void AddGoto(BasicBlock* block, BasicBlock* succ) { | 205 void AddGoto(BasicBlock* block, BasicBlock* succ); |
| 232 DCHECK(block->control_ == BasicBlock::kNone); | |
| 233 block->control_ = BasicBlock::kGoto; | |
| 234 AddSuccessor(block, succ); | |
| 235 } | |
| 236 | 206 |
| 237 // BasicBlock building: add a branch at the end of {block}. | 207 // BasicBlock building: add a branch at the end of {block}. |
| 238 void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock, | 208 void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock, |
| 239 BasicBlock* fblock) { | 209 BasicBlock* fblock); |
| 240 DCHECK(block->control_ == BasicBlock::kNone); | |
| 241 DCHECK(branch->opcode() == IrOpcode::kBranch); | |
| 242 block->control_ = BasicBlock::kBranch; | |
| 243 AddSuccessor(block, tblock); | |
| 244 AddSuccessor(block, fblock); | |
| 245 SetControlInput(block, branch); | |
| 246 if (branch->opcode() == IrOpcode::kBranch) { | |
| 247 // TODO(titzer): require a Branch node here. (sloppy tests). | |
| 248 SetBlockForNode(block, branch); | |
| 249 } | |
| 250 } | |
| 251 | 210 |
| 252 // BasicBlock building: add a return at the end of {block}. | 211 // BasicBlock building: add a return at the end of {block}. |
| 253 void AddReturn(BasicBlock* block, Node* input) { | 212 void AddReturn(BasicBlock* block, Node* input); |
| 254 DCHECK(block->control_ == BasicBlock::kNone); | |
| 255 block->control_ = BasicBlock::kReturn; | |
| 256 SetControlInput(block, input); | |
| 257 if (block != end()) AddSuccessor(block, end()); | |
| 258 if (input->opcode() == IrOpcode::kReturn) { | |
| 259 // TODO(titzer): require a Return node here. (sloppy tests). | |
| 260 SetBlockForNode(block, input); | |
| 261 } | |
| 262 } | |
| 263 | 213 |
| 264 // BasicBlock building: add a throw at the end of {block}. | 214 // BasicBlock building: add a throw at the end of {block}. |
| 265 void AddThrow(BasicBlock* block, Node* input) { | 215 void AddThrow(BasicBlock* block, Node* input); |
| 266 DCHECK(block->control_ == BasicBlock::kNone); | |
| 267 block->control_ = BasicBlock::kThrow; | |
| 268 SetControlInput(block, input); | |
| 269 if (block != end()) AddSuccessor(block, end()); | |
| 270 } | |
| 271 | 216 |
| 272 friend class Scheduler; | 217 void AddSuccessor(BasicBlock* block, BasicBlock* succ); |
| 273 friend class CodeGenerator; | |
| 274 | |
| 275 void AddSuccessor(BasicBlock* block, BasicBlock* succ) { | |
| 276 succ->AppendInput(zone_, block); | |
| 277 } | |
| 278 | 218 |
| 279 BasicBlockVector* rpo_order() { return &rpo_order_; } | 219 BasicBlockVector* rpo_order() { return &rpo_order_; } |
| 280 | 220 |
| 221 BasicBlock* start() { return start_; } |
| 222 BasicBlock* end() { return end_; } |
| 223 |
| 224 Zone* zone() { return zone_; } |
| 225 |
| 281 private: | 226 private: |
| 227 friend class Scheduler; |
| 228 friend class CodeGenerator; |
| 282 friend class ScheduleVisualizer; | 229 friend class ScheduleVisualizer; |
| 283 friend class BasicBlockInstrumentor; | 230 friend class BasicBlockInstrumentor; |
| 284 | 231 |
| 285 void SetControlInput(BasicBlock* block, Node* node) { | 232 void SetControlInput(BasicBlock* block, Node* node); |
| 286 block->control_input_ = node; | 233 void SetBlockForNode(BasicBlock* block, Node* node); |
| 287 SetBlockForNode(block, node); | |
| 288 } | |
| 289 | |
| 290 void SetBlockForNode(BasicBlock* block, Node* node) { | |
| 291 int length = static_cast<int>(nodeid_to_block_.size()); | |
| 292 if (node->id() >= length) { | |
| 293 nodeid_to_block_.resize(node->id() + 1); | |
| 294 } | |
| 295 nodeid_to_block_[node->id()] = block; | |
| 296 } | |
| 297 | 234 |
| 298 Zone* zone_; | 235 Zone* zone_; |
| 299 BasicBlockVector all_blocks_; // All basic blocks in the schedule. | 236 BasicBlockVector all_blocks_; // All basic blocks in the schedule. |
| 300 BasicBlockVector nodeid_to_block_; // Map from node to containing block. | 237 BasicBlockVector nodeid_to_block_; // Map from node to containing block. |
| 301 BasicBlockVector rpo_order_; // Reverse-post-order block list. | 238 BasicBlockVector rpo_order_; // Reverse-post-order block list. |
| 239 BasicBlock* start_; |
| 240 BasicBlock* end_; |
| 302 }; | 241 }; |
| 303 | 242 |
| 304 OStream& operator<<(OStream& os, const Schedule& s); | 243 OStream& operator<<(OStream& os, const Schedule& s); |
| 305 } | 244 } |
| 306 } | 245 } |
| 307 } // namespace v8::internal::compiler | 246 } // namespace v8::internal::compiler |
| 308 | 247 |
| 309 #endif // V8_COMPILER_SCHEDULE_H_ | 248 #endif // V8_COMPILER_SCHEDULE_H_ |
| OLD | NEW |