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

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

Issue 426233002: Land the Fan (disabled) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback, rebase and "git cl format" Created 6 years, 4 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/representation-change.h ('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
(Empty)
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
3 // found in the LICENSE file.
4
5 #ifndef V8_COMPILER_SCHEDULE_H_
6 #define V8_COMPILER_SCHEDULE_H_
7
8 #include <vector>
9
10 #include "src/v8.h"
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"
17 #include "src/compiler/opcodes.h"
18 #include "src/zone.h"
19
20 namespace v8 {
21 namespace internal {
22 namespace compiler {
23
24 class BasicBlock;
25 class Graph;
26 class ConstructScheduleData;
27 class CodeGenerator; // Because of a namespace bug in clang.
28
29 class BasicBlockData {
30 public:
31 // Possible control nodes that can end a block.
32 enum Control {
33 kNone, // Control not initialized yet.
34 kGoto, // Goto a single successor block.
35 kBranch, // Branch if true to first successor, otherwise second.
36 kReturn, // Return a value from this method.
37 kThrow, // Throw an exception.
38 kCall, // Call to a possibly deoptimizing or throwing function.
39 kDeoptimize // Deoptimize.
40 };
41
42 int32_t rpo_number_; // special RPO number of the block.
43 BasicBlock* loop_header_; // Pointer to dominating loop header basic block,
44 // NULL if none. For loop headers, this points to
45 // enclosing loop header.
46 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 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
56 explicit BasicBlockData(Zone* zone)
57 : rpo_number_(-1),
58 loop_header_(NULL),
59 loop_depth_(0),
60 loop_end_(-1),
61 code_start_(-1),
62 code_end_(-1),
63 deferred_(false),
64 control_(kNone),
65 control_input_(NULL),
66 nodes_(NodeVector::allocator_type(zone)) {}
67
68 inline bool IsLoopHeader() const { return loop_end_ >= 0; }
69 inline bool LoopContains(BasicBlockData* block) const {
70 // RPO numbers must be initialized.
71 ASSERT(rpo_number_ >= 0);
72 ASSERT(block->rpo_number_ >= 0);
73 if (loop_end_ < 0) return false; // This is not a loop.
74 return block->rpo_number_ >= rpo_number_ && block->rpo_number_ < loop_end_;
75 }
76 int first_instruction_index() {
77 ASSERT(code_start_ >= 0);
78 ASSERT(code_end_ > 0);
79 ASSERT(code_end_ >= code_start_);
80 return code_start_;
81 }
82 int last_instruction_index() {
83 ASSERT(code_start_ >= 0);
84 ASSERT(code_end_ > 0);
85 ASSERT(code_end_ >= code_start_);
86 return code_end_ - 1;
87 }
88 };
89
90 OStream& operator<<(OStream& os, const BasicBlockData::Control& c);
91
92 // A basic block contains an ordered list of nodes and ends with a control
93 // node. Note that if a basic block has phis, then all phis must appear as the
94 // first nodes in the block.
95 class BasicBlock V8_FINAL : public GenericNode<BasicBlockData, BasicBlock> {
96 public:
97 BasicBlock(GenericGraphBase* graph, int input_count)
98 : GenericNode<BasicBlockData, BasicBlock>(graph, input_count) {}
99
100 typedef Uses Successors;
101 typedef Inputs Predecessors;
102
103 Successors successors() { return static_cast<Successors>(uses()); }
104 Predecessors predecessors() { return static_cast<Predecessors>(inputs()); }
105
106 int PredecessorCount() { return InputCount(); }
107 BasicBlock* PredecessorAt(int index) { return InputAt(index); }
108
109 int SuccessorCount() { return UseCount(); }
110 BasicBlock* SuccessorAt(int index) { return UseAt(index); }
111
112 int PredecessorIndexOf(BasicBlock* predecessor) {
113 BasicBlock::Predecessors predecessors = this->predecessors();
114 for (BasicBlock::Predecessors::iterator i = predecessors.begin();
115 i != predecessors.end(); ++i) {
116 if (*i == predecessor) return i.index();
117 }
118 return -1;
119 }
120
121 inline BasicBlock* loop_header() {
122 return static_cast<BasicBlock*>(loop_header_);
123 }
124 inline BasicBlock* ContainingLoop() {
125 if (IsLoopHeader()) return this;
126 return static_cast<BasicBlock*>(loop_header_);
127 }
128
129 typedef NodeVector::iterator iterator;
130 iterator begin() { return nodes_.begin(); }
131 iterator end() { return nodes_.end(); }
132
133 typedef NodeVector::const_iterator const_iterator;
134 const_iterator begin() const { return nodes_.begin(); }
135 const_iterator end() const { return nodes_.end(); }
136
137 typedef NodeVector::reverse_iterator reverse_iterator;
138 reverse_iterator rbegin() { return nodes_.rbegin(); }
139 reverse_iterator rend() { return nodes_.rend(); }
140
141 private:
142 DISALLOW_COPY_AND_ASSIGN(BasicBlock);
143 };
144
145 typedef GenericGraphVisit::NullNodeVisitor<BasicBlockData, BasicBlock>
146 NullBasicBlockVisitor;
147
148 typedef zone_allocator<BasicBlock*> BasicBlockPtrZoneAllocator;
149 typedef std::vector<BasicBlock*, BasicBlockPtrZoneAllocator> BasicBlockVector;
150 typedef BasicBlockVector::iterator BasicBlockVectorIter;
151 typedef BasicBlockVector::reverse_iterator BasicBlockVectorRIter;
152
153 // A schedule represents the result of assigning nodes to basic blocks
154 // 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
156 // by the graph's dependencies. A schedule is required to generate code.
157 class Schedule : public GenericGraph<BasicBlock> {
158 public:
159 explicit Schedule(Zone* zone)
160 : GenericGraph<BasicBlock>(zone),
161 zone_(zone),
162 all_blocks_(BasicBlockVector::allocator_type(zone)),
163 nodeid_to_block_(BasicBlockVector::allocator_type(zone)),
164 rpo_order_(BasicBlockVector::allocator_type(zone)),
165 immediate_dominator_(BasicBlockVector::allocator_type(zone)) {
166 NewBasicBlock(); // entry.
167 NewBasicBlock(); // exit.
168 SetStart(entry());
169 SetEnd(exit());
170 }
171
172 // TODO(titzer): rewrite users of these methods to use start() and end().
173 BasicBlock* entry() const { return all_blocks_[0]; } // Return entry block.
174 BasicBlock* exit() const { return all_blocks_[1]; } // Return exit block.
175
176 // Return the block which contains {node}, if any.
177 BasicBlock* block(Node* node) const {
178 if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) {
179 return nodeid_to_block_[node->id()];
180 }
181 return NULL;
182 }
183
184 BasicBlock* dominator(BasicBlock* block) {
185 return immediate_dominator_[block->id()];
186 }
187
188 bool IsScheduled(Node* node) {
189 int length = static_cast<int>(nodeid_to_block_.size());
190 if (node->id() >= length) return false;
191 return nodeid_to_block_[node->id()] != NULL;
192 }
193
194 BasicBlock* GetBlockById(int block_id) { return all_blocks_[block_id]; }
195
196 int BasicBlockCount() const { return NodeCount(); }
197 int RpoBlockCount() const { return rpo_order_.size(); }
198
199 typedef ContainerPointerWrapper<BasicBlockVector> BasicBlocks;
200
201 // Return a list of all the blocks in the schedule, in arbitrary order.
202 BasicBlocks all_blocks() { return BasicBlocks(&all_blocks_); }
203
204 // Check if nodes {a} and {b} are in the same block.
205 inline bool SameBasicBlock(Node* a, Node* b) const {
206 BasicBlock* block = this->block(a);
207 return block != NULL && block == this->block(b);
208 }
209
210 // BasicBlock building: create a new block.
211 inline BasicBlock* NewBasicBlock() {
212 BasicBlock* block =
213 BasicBlock::New(this, 0, static_cast<BasicBlock**>(NULL));
214 all_blocks_.push_back(block);
215 return block;
216 }
217
218 // BasicBlock building: records that a node will later be added to a block but
219 // doesn't actually add the node to the block.
220 inline void PlanNode(BasicBlock* block, Node* node) {
221 if (FLAG_trace_turbo_scheduler) {
222 PrintF("Planning node %d for future add to block %d\n", node->id(),
223 block->id());
224 }
225 ASSERT(this->block(node) == NULL);
226 SetBlockForNode(block, node);
227 }
228
229 // BasicBlock building: add a node to the end of the block.
230 inline void AddNode(BasicBlock* block, Node* node) {
231 if (FLAG_trace_turbo_scheduler) {
232 PrintF("Adding node %d to block %d\n", node->id(), block->id());
233 }
234 ASSERT(this->block(node) == NULL || this->block(node) == block);
235 block->nodes_.push_back(node);
236 SetBlockForNode(block, node);
237 }
238
239 // BasicBlock building: add a goto to the end of {block}.
240 void AddGoto(BasicBlock* block, BasicBlock* succ) {
241 ASSERT(block->control_ == BasicBlock::kNone);
242 block->control_ = BasicBlock::kGoto;
243 AddSuccessor(block, succ);
244 }
245
246 // BasicBlock building: add a (branching) call at the end of {block}.
247 void AddCall(BasicBlock* block, Node* call, BasicBlock* cont_block,
248 BasicBlock* deopt_block) {
249 ASSERT(block->control_ == BasicBlock::kNone);
250 ASSERT(call->opcode() == IrOpcode::kCall);
251 block->control_ = BasicBlock::kCall;
252 // Insert the deopt block first so that the RPO order builder picks
253 // it first (and thus it ends up late in the RPO order).
254 AddSuccessor(block, deopt_block);
255 AddSuccessor(block, cont_block);
256 SetControlInput(block, call);
257 }
258
259 // BasicBlock building: add a branch at the end of {block}.
260 void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
261 BasicBlock* fblock) {
262 ASSERT(block->control_ == BasicBlock::kNone);
263 ASSERT(branch->opcode() == IrOpcode::kBranch);
264 block->control_ = BasicBlock::kBranch;
265 AddSuccessor(block, tblock);
266 AddSuccessor(block, fblock);
267 SetControlInput(block, branch);
268 }
269
270 // BasicBlock building: add a return at the end of {block}.
271 void AddReturn(BasicBlock* block, Node* input) {
272 // TODO(titzer): require a Return node here.
273 ASSERT(block->control_ == BasicBlock::kNone);
274 block->control_ = BasicBlock::kReturn;
275 SetControlInput(block, input);
276 if (block != exit()) AddSuccessor(block, exit());
277 }
278
279 // BasicBlock building: add a throw at the end of {block}.
280 void AddThrow(BasicBlock* block, Node* input) {
281 ASSERT(block->control_ == BasicBlock::kNone);
282 block->control_ = BasicBlock::kThrow;
283 SetControlInput(block, input);
284 if (block != exit()) AddSuccessor(block, exit());
285 }
286
287 // BasicBlock building: add a deopt at the end of {block}.
288 void AddDeoptimize(BasicBlock* block, Node* state) {
289 ASSERT(block->control_ == BasicBlock::kNone);
290 block->control_ = BasicBlock::kDeoptimize;
291 SetControlInput(block, state);
292 block->deferred_ = true; // By default, consider deopts the slow path.
293 if (block != exit()) AddSuccessor(block, exit());
294 }
295
296 friend class Scheduler;
297 friend class CodeGenerator;
298
299 void AddSuccessor(BasicBlock* block, BasicBlock* succ) {
300 succ->AppendInput(zone_, block);
301 }
302
303 BasicBlockVector* rpo_order() { return &rpo_order_; }
304
305 private:
306 friend class ScheduleVisualizer;
307
308 void SetControlInput(BasicBlock* block, Node* node) {
309 block->control_input_ = node;
310 SetBlockForNode(block, node);
311 }
312
313 void SetBlockForNode(BasicBlock* block, Node* node) {
314 int length = static_cast<int>(nodeid_to_block_.size());
315 if (node->id() >= length) {
316 nodeid_to_block_.resize(node->id() + 1);
317 }
318 nodeid_to_block_[node->id()] = block;
319 }
320
321 Zone* zone_;
322 BasicBlockVector all_blocks_; // All basic blocks in the schedule.
323 BasicBlockVector nodeid_to_block_; // Map from node to containing block.
324 BasicBlockVector rpo_order_; // Reverse-post-order block list.
325 BasicBlockVector immediate_dominator_; // Maps to a block's immediate
326 // dominator, indexed by block
327 // id.
328 };
329
330 OStream& operator<<(OStream& os, const Schedule& s);
331 }
332 }
333 } // namespace v8::internal::compiler
334
335 #endif // V8_COMPILER_SCHEDULE_H_
OLDNEW
« no previous file with comments | « src/compiler/representation-change.h ('k') | src/compiler/schedule.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698