Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1194)

Side by Side Diff: src/compiler/schedule.h

Issue 606403003: Refactor BasicBlock, no inheritance from GenericNode (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Attempt n+1 to address the size_t madness Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/compiler/register-allocator.cc ('k') | src/compiler/schedule.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.cc ('k') | src/compiler/schedule.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698