schedule.h revision 014dc512cdd3e367bee49a713fdc5ed92584a3e5
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 <iosfwd>
9
10#include "src/zone-containers.h"
11
12namespace v8 {
13namespace internal {
14namespace compiler {
15
16// Forward declarations.
17class BasicBlock;
18class BasicBlockInstrumentor;
19class Node;
20
21
22typedef ZoneVector<BasicBlock*> BasicBlockVector;
23typedef ZoneVector<Node*> NodeVector;
24
25
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.
29class BasicBlock final : public ZoneObject {
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    kCall,        // Call with continuation as first successor, exception
36                  // second.
37    kBranch,      // Branch if true to first successor, otherwise second.
38    kSwitch,      // Table dispatch to one of the successor blocks.
39    kDeoptimize,  // Return a value from this method.
40    kTailCall,    // Tail call another method from this method.
41    kReturn,      // Return a value from this method.
42    kThrow        // Throw an exception.
43  };
44
45  class Id {
46   public:
47    int ToInt() const { return static_cast<int>(index_); }
48    size_t ToSize() const { return index_; }
49    static Id FromSize(size_t index) { return Id(index); }
50    static Id FromInt(int index) { return Id(static_cast<size_t>(index)); }
51
52   private:
53    explicit Id(size_t index) : index_(index) {}
54    size_t index_;
55  };
56
57  BasicBlock(Zone* zone, Id id);
58
59  Id id() const { return id_; }
60
61  // Predecessors.
62  BasicBlockVector& predecessors() { return predecessors_; }
63  const BasicBlockVector& predecessors() const { return predecessors_; }
64  size_t PredecessorCount() const { return predecessors_.size(); }
65  BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; }
66  void ClearPredecessors() { predecessors_.clear(); }
67  void AddPredecessor(BasicBlock* predecessor);
68
69  // Successors.
70  BasicBlockVector& successors() { return successors_; }
71  const BasicBlockVector& successors() const { return successors_; }
72  size_t SuccessorCount() const { return successors_.size(); }
73  BasicBlock* SuccessorAt(size_t index) { return successors_[index]; }
74  void ClearSuccessors() { successors_.clear(); }
75  void AddSuccessor(BasicBlock* successor);
76
77  // Nodes in the basic block.
78  typedef Node* value_type;
79  bool empty() const { return nodes_.empty(); }
80  size_t size() const { return nodes_.size(); }
81  Node* NodeAt(size_t index) { return nodes_[index]; }
82  size_t NodeCount() const { return nodes_.size(); }
83
84  value_type& front() { return nodes_.front(); }
85  value_type const& front() const { return nodes_.front(); }
86
87  typedef NodeVector::iterator iterator;
88  iterator begin() { return nodes_.begin(); }
89  iterator end() { return nodes_.end(); }
90
91  typedef NodeVector::const_iterator const_iterator;
92  const_iterator begin() const { return nodes_.begin(); }
93  const_iterator end() const { return nodes_.end(); }
94
95  typedef NodeVector::reverse_iterator reverse_iterator;
96  reverse_iterator rbegin() { return nodes_.rbegin(); }
97  reverse_iterator rend() { return nodes_.rend(); }
98
99  void AddNode(Node* node);
100  template <class InputIterator>
101  void InsertNodes(iterator insertion_point, InputIterator insertion_start,
102                   InputIterator insertion_end) {
103    nodes_.insert(insertion_point, insertion_start, insertion_end);
104  }
105
106  // Accessors.
107  Control control() const { return control_; }
108  void set_control(Control control);
109
110  Node* control_input() const { return control_input_; }
111  void set_control_input(Node* control_input);
112
113  bool deferred() const { return deferred_; }
114  void set_deferred(bool deferred) { deferred_ = deferred; }
115
116  int32_t dominator_depth() const { return dominator_depth_; }
117  void set_dominator_depth(int32_t depth) { dominator_depth_ = depth; }
118
119  BasicBlock* dominator() const { return dominator_; }
120  void set_dominator(BasicBlock* dominator) { dominator_ = dominator; }
121
122  BasicBlock* rpo_next() const { return rpo_next_; }
123  void set_rpo_next(BasicBlock* rpo_next) { rpo_next_ = rpo_next; }
124
125  BasicBlock* loop_header() const { return loop_header_; }
126  void set_loop_header(BasicBlock* loop_header);
127
128  BasicBlock* loop_end() const { return loop_end_; }
129  void set_loop_end(BasicBlock* loop_end);
130
131  int32_t loop_depth() const { return loop_depth_; }
132  void set_loop_depth(int32_t loop_depth);
133
134  int32_t loop_number() const { return loop_number_; }
135  void set_loop_number(int32_t loop_number) { loop_number_ = loop_number; }
136
137  int32_t rpo_number() const { return rpo_number_; }
138  void set_rpo_number(int32_t rpo_number);
139
140  // Loop membership helpers.
141  inline bool IsLoopHeader() const { return loop_end_ != nullptr; }
142  bool LoopContains(BasicBlock* block) const;
143
144  // Computes the immediate common dominator of {b1} and {b2}. The worst time
145  // complexity is O(N) where N is the height of the dominator tree.
146  static BasicBlock* GetCommonDominator(BasicBlock* b1, BasicBlock* b2);
147
148 private:
149  int32_t loop_number_;      // loop number of the block.
150  int32_t rpo_number_;       // special RPO number of the block.
151  bool deferred_;            // true if the block contains deferred code.
152  int32_t dominator_depth_;  // Depth within the dominator tree.
153  BasicBlock* dominator_;    // Immediate dominator of the block.
154  BasicBlock* rpo_next_;     // Link to next block in special RPO order.
155  BasicBlock* loop_header_;  // Pointer to dominating loop header basic block,
156  // nullptr if none. For loop headers, this points to
157  // enclosing loop header.
158  BasicBlock* loop_end_;     // end of the loop, if this block is a loop header.
159  int32_t loop_depth_;       // loop nesting, 0 is top-level
160
161  Control control_;          // Control at the end of the block.
162  Node* control_input_;      // Input value for control.
163  NodeVector nodes_;         // nodes of this block in forward order.
164
165  BasicBlockVector successors_;
166  BasicBlockVector predecessors_;
167  Id id_;
168
169  DISALLOW_COPY_AND_ASSIGN(BasicBlock);
170};
171
172std::ostream& operator<<(std::ostream&, const BasicBlock::Control&);
173std::ostream& operator<<(std::ostream&, const BasicBlock::Id&);
174
175
176// A schedule represents the result of assigning nodes to basic blocks
177// and ordering them within basic blocks. Prior to computing a schedule,
178// a graph has no notion of control flow ordering other than that induced
179// by the graph's dependencies. A schedule is required to generate code.
180class Schedule final : public ZoneObject {
181 public:
182  explicit Schedule(Zone* zone, size_t node_count_hint = 0);
183
184  // Return the block which contains {node}, if any.
185  BasicBlock* block(Node* node) const;
186
187  bool IsScheduled(Node* node);
188  BasicBlock* GetBlockById(BasicBlock::Id block_id);
189
190  size_t BasicBlockCount() const { return all_blocks_.size(); }
191  size_t RpoBlockCount() const { return rpo_order_.size(); }
192
193  // Check if nodes {a} and {b} are in the same block.
194  bool SameBasicBlock(Node* a, Node* b) const;
195
196  // BasicBlock building: create a new block.
197  BasicBlock* NewBasicBlock();
198
199  // BasicBlock building: records that a node will later be added to a block but
200  // doesn't actually add the node to the block.
201  void PlanNode(BasicBlock* block, Node* node);
202
203  // BasicBlock building: add a node to the end of the block.
204  void AddNode(BasicBlock* block, Node* node);
205
206  // BasicBlock building: add a goto to the end of {block}.
207  void AddGoto(BasicBlock* block, BasicBlock* succ);
208
209  // BasicBlock building: add a call at the end of {block}.
210  void AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
211               BasicBlock* exception_block);
212
213  // BasicBlock building: add a branch at the end of {block}.
214  void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
215                 BasicBlock* fblock);
216
217  // BasicBlock building: add a switch at the end of {block}.
218  void AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
219                 size_t succ_count);
220
221  // BasicBlock building: add a deoptimize at the end of {block}.
222  void AddDeoptimize(BasicBlock* block, Node* input);
223
224  // BasicBlock building: add a tailcall at the end of {block}.
225  void AddTailCall(BasicBlock* block, Node* input);
226
227  // BasicBlock building: add a return at the end of {block}.
228  void AddReturn(BasicBlock* block, Node* input);
229
230  // BasicBlock building: add a throw at the end of {block}.
231  void AddThrow(BasicBlock* block, Node* input);
232
233  // BasicBlock mutation: insert a branch into the end of {block}.
234  void InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
235                    BasicBlock* tblock, BasicBlock* fblock);
236
237  // BasicBlock mutation: insert a switch into the end of {block}.
238  void InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
239                    BasicBlock** succ_blocks, size_t succ_count);
240
241  // Exposed publicly for testing only.
242  void AddSuccessorForTesting(BasicBlock* block, BasicBlock* succ) {
243    return AddSuccessor(block, succ);
244  }
245
246  BasicBlockVector* rpo_order() { return &rpo_order_; }
247  const BasicBlockVector* rpo_order() const { return &rpo_order_; }
248
249  BasicBlock* start() { return start_; }
250  BasicBlock* end() { return end_; }
251
252  Zone* zone() const { return zone_; }
253
254 private:
255  friend class Scheduler;
256  friend class BasicBlockInstrumentor;
257
258  void AddSuccessor(BasicBlock* block, BasicBlock* succ);
259  void MoveSuccessors(BasicBlock* from, BasicBlock* to);
260
261  void SetControlInput(BasicBlock* block, Node* node);
262  void SetBlockForNode(BasicBlock* block, Node* node);
263
264  Zone* zone_;
265  BasicBlockVector all_blocks_;           // All basic blocks in the schedule.
266  BasicBlockVector nodeid_to_block_;      // Map from node to containing block.
267  BasicBlockVector rpo_order_;            // Reverse-post-order block list.
268  BasicBlock* start_;
269  BasicBlock* end_;
270
271  DISALLOW_COPY_AND_ASSIGN(Schedule);
272};
273
274std::ostream& operator<<(std::ostream&, const Schedule&);
275
276}  // namespace compiler
277}  // namespace internal
278}  // namespace v8
279
280#endif  // V8_COMPILER_SCHEDULE_H_
281