v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
schedule.h
Go to the documentation of this file.
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
11#include "src/common/globals.h"
13
14namespace v8 {
15namespace internal {
16namespace compiler {
17
18// Forward declarations.
19class BasicBlock;
20class BasicBlockInstrumentor;
21class Node;
22
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.
30 : public NON_EXPORTED_BASE(ZoneObject) {
31 public:
32 // Possible control nodes that can end a block.
33 enum Control {
34 kNone, // Control not initialized yet.
35 kGoto, // Goto a single successor block.
36 kCall, // Call with continuation as first successor, exception
37 // second.
38 kBranch, // Branch if true to first successor, otherwise second.
39 kSwitch, // Table dispatch to one of the successor blocks.
40 kDeoptimize, // Return a value from this method.
41 kTailCall, // Tail call another method from this method.
42 kReturn, // Return a value from this method.
43 kThrow // Throw an exception.
44 };
45
46 class Id {
47 public:
48 int ToInt() const { return static_cast<int>(index_); }
49 size_t ToSize() const { return index_; }
50 static Id FromSize(size_t index) { return Id(index); }
51 static Id FromInt(int index) { return Id(static_cast<size_t>(index)); }
52
53 private:
54 explicit Id(size_t index) : index_(index) {}
55 size_t index_;
56 };
57
58 BasicBlock(Zone* zone, Id id);
59 BasicBlock(const BasicBlock&) = delete;
60 BasicBlock& operator=(const BasicBlock&) = delete;
61
62 Id id() const { return id_; }
63#if DEBUG
64 void set_debug_info(AssemblerDebugInfo debug_info) {
65 debug_info_ = debug_info;
66 }
67 AssemblerDebugInfo debug_info() const { return debug_info_; }
68#endif // DEBUG
69
70 void Print();
71
72 // Predecessors.
73 BasicBlockVector& predecessors() { return predecessors_; }
74 const BasicBlockVector& predecessors() const { return predecessors_; }
75 size_t PredecessorCount() const { return predecessors_.size(); }
76 BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; }
77 void ClearPredecessors() { predecessors_.clear(); }
78 void AddPredecessor(BasicBlock* predecessor);
79 void RemovePredecessor(size_t index);
80
81 // Successors.
82 BasicBlockVector& successors() { return successors_; }
83 const BasicBlockVector& successors() const { return successors_; }
84 size_t SuccessorCount() const { return successors_.size(); }
85 BasicBlock* SuccessorAt(size_t index) { return successors_[index]; }
86 void ClearSuccessors() { successors_.clear(); }
87 void AddSuccessor(BasicBlock* successor);
88
89 // Nodes in the basic block.
90 using value_type = Node*;
91 bool empty() const { return nodes_.empty(); }
92 size_t size() const { return nodes_.size(); }
93 Node* NodeAt(size_t index) { return nodes_[index]; }
94 size_t NodeCount() const { return nodes_.size(); }
95
96 value_type& front() { return nodes_.front(); }
97 value_type const& front() const { return nodes_.front(); }
98
100 iterator begin() { return nodes_.begin(); }
101 iterator end() { return nodes_.end(); }
102
103 void RemoveNode(iterator it) { nodes_.erase(it); }
104
106 const_iterator begin() const { return nodes_.begin(); }
107 const_iterator end() const { return nodes_.end(); }
108
110 reverse_iterator rbegin() { return nodes_.rbegin(); }
111 reverse_iterator rend() { return nodes_.rend(); }
112
113 void AddNode(Node* node);
114 template <class InputIterator>
115 void InsertNodes(iterator insertion_point, InputIterator insertion_start,
116 InputIterator insertion_end) {
117 nodes_.insert(insertion_point, insertion_start, insertion_end);
118 }
119
120 // Trim basic block to end at {new_end}.
121 void TrimNodes(iterator new_end);
122
123 void ResetRPOInfo();
124
125 // Accessors.
126 Control control() const { return control_; }
127 void set_control(Control control);
128
129 Node* control_input() const { return control_input_; }
130 void set_control_input(Node* control_input);
131
132 bool deferred() const { return deferred_; }
133 void set_deferred(bool deferred) { deferred_ = deferred; }
134
135 int32_t dominator_depth() const { return dominator_depth_; }
136 void set_dominator_depth(int32_t depth) { dominator_depth_ = depth; }
137
138 BasicBlock* dominator() const { return dominator_; }
139 void set_dominator(BasicBlock* dominator) { dominator_ = dominator; }
140
141 BasicBlock* rpo_next() const { return rpo_next_; }
142 void set_rpo_next(BasicBlock* rpo_next) { rpo_next_ = rpo_next; }
143
144 BasicBlock* loop_header() const { return loop_header_; }
145 void set_loop_header(BasicBlock* loop_header);
146
147 BasicBlock* loop_end() const { return loop_end_; }
148 void set_loop_end(BasicBlock* loop_end);
149
150 int32_t loop_depth() const { return loop_depth_; }
151 void set_loop_depth(int32_t loop_depth);
152
153 int32_t loop_number() const { return loop_number_; }
154 void set_loop_number(int32_t loop_number) { loop_number_ = loop_number; }
155
156 int32_t rpo_number() const { return rpo_number_; }
157 void set_rpo_number(int32_t rpo_number);
158
159 NodeVector* nodes() { return &nodes_; }
160
161#ifdef LOG_BUILTIN_BLOCK_COUNT
162 uint64_t pgo_execution_count() { return pgo_execution_count_; }
163 void set_pgo_execution_count(uint64_t count) { pgo_execution_count_ = count; }
164#endif
165
166 // Loop membership helpers.
167 inline bool IsLoopHeader() const { return loop_end_ != nullptr; }
168 bool LoopContains(BasicBlock* block) const;
169
170 // Computes the immediate common dominator of {b1} and {b2}. The worst time
171 // complexity is O(N) where N is the height of the dominator tree.
172 static BasicBlock* GetCommonDominator(BasicBlock* b1, BasicBlock* b2);
173
174 private:
175 int32_t loop_number_; // loop number of the block.
176 int32_t rpo_number_; // special RPO number of the block.
177 bool deferred_; // true if the block contains deferred code.
178 int32_t dominator_depth_; // Depth within the dominator tree.
179 BasicBlock* dominator_; // Immediate dominator of the block.
180 BasicBlock* rpo_next_; // Link to next block in special RPO order.
181 BasicBlock* loop_header_; // Pointer to dominating loop header basic block,
182 // nullptr if none. For loop headers, this points to
183 // enclosing loop header.
184 BasicBlock* loop_end_; // end of the loop, if this block is a loop header.
185 int32_t loop_depth_; // loop nesting, 0 is top-level
186
187 Control control_; // Control at the end of the block.
188 Node* control_input_; // Input value for control.
189 NodeVector nodes_; // nodes of this block in forward order.
190
193#if DEBUG
194 AssemblerDebugInfo debug_info_;
195#endif
196#ifdef LOG_BUILTIN_BLOCK_COUNT
197 uint64_t pgo_execution_count_;
198#endif
200};
201
202std::ostream& operator<<(std::ostream&, const BasicBlock&);
203std::ostream& operator<<(std::ostream&, const BasicBlock::Control&);
204std::ostream& operator<<(std::ostream&, const BasicBlock::Id&);
205
206// A schedule represents the result of assigning nodes to basic blocks
207// and ordering them within basic blocks. Prior to computing a schedule,
208// a graph has no notion of control flow ordering other than that induced
209// by the graph's dependencies. A schedule is required to generate code.
210class V8_EXPORT_PRIVATE Schedule final : public NON_EXPORTED_BASE(ZoneObject) {
211 public:
212 explicit Schedule(Zone* zone, size_t node_count_hint = 0);
213 Schedule(const Schedule&) = delete;
214 Schedule& operator=(const Schedule&) = delete;
215
216 // Return the block which contains {node}, if any.
217 BasicBlock* block(Node* node) const;
218
219 bool IsScheduled(Node* node);
220 BasicBlock* GetBlockById(BasicBlock::Id block_id);
221 void ClearBlockById(BasicBlock::Id block_id);
222
223 size_t BasicBlockCount() const { return all_blocks_.size(); }
224 size_t RpoBlockCount() const { return rpo_order_.size(); }
225
226 // Check if nodes {a} and {b} are in the same block.
227 bool SameBasicBlock(Node* a, Node* b) const;
228
229 // BasicBlock building: create a new block.
230 BasicBlock* NewBasicBlock();
231
232 // BasicBlock building: records that a node will later be added to a block but
233 // doesn't actually add the node to the block.
234 void PlanNode(BasicBlock* block, Node* node);
235
236 // BasicBlock building: add a node to the end of the block.
237 void AddNode(BasicBlock* block, Node* node);
238
239 // BasicBlock building: add a goto to the end of {block}.
240 void AddGoto(BasicBlock* block, BasicBlock* succ);
241
242 // BasicBlock building: add a call at the end of {block}.
243 void AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
244 BasicBlock* exception_block);
245
246 // BasicBlock building: add a branch at the end of {block}.
247 void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
248 BasicBlock* fblock);
249
250 // BasicBlock building: add a switch at the end of {block}.
251 void AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
252 size_t succ_count);
253
254 // BasicBlock building: add a deoptimize at the end of {block}.
255 void AddDeoptimize(BasicBlock* block, Node* input);
256
257 // BasicBlock building: add a tailcall at the end of {block}.
258 void AddTailCall(BasicBlock* block, Node* input);
259
260 // BasicBlock building: add a return at the end of {block}.
261 void AddReturn(BasicBlock* block, Node* input);
262
263 // BasicBlock building: add a throw at the end of {block}.
264 void AddThrow(BasicBlock* block, Node* input);
265
266 // BasicBlock mutation: insert a branch into the end of {block}.
267 void InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
268 BasicBlock* tblock, BasicBlock* fblock);
269
270 // BasicBlock mutation: insert a switch into the end of {block}.
271 void InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
272 BasicBlock** succ_blocks, size_t succ_count);
273
274 // Exposed publicly for testing only.
276 return AddSuccessor(block, succ);
277 }
278
279 const BasicBlockVector* all_blocks() const { return &all_blocks_; }
280 BasicBlockVector* rpo_order() { return &rpo_order_; }
281 const BasicBlockVector* rpo_order() const { return &rpo_order_; }
282
283 BasicBlock* start() { return start_; }
284 BasicBlock* end() { return end_; }
285
286 Zone* zone() const { return zone_; }
287
288 private:
289 friend class GraphAssembler;
290 friend class Scheduler;
293
294 // For CSA/Torque: Ensure properties of the CFG assumed by further stages.
295 void EnsureCFGWellFormedness();
296 // For CSA/Torque: Eliminates unnecessary phi nodes, including phis with a
297 // single input. The latter is necessary to ensure the property required for
298 // SSA deconstruction that the target block of a control flow split has no
299 // phis.
300 void EliminateRedundantPhiNodes();
301 // Ensure split-edge form for a hand-assembled schedule.
302 void EnsureSplitEdgeForm(BasicBlock* block);
303 // Move Phi operands to newly created merger blocks
304 void MovePhis(BasicBlock* from, BasicBlock* to);
305 // Copy deferred block markers down as far as possible
306 void PropagateDeferredMark();
307
308 void AddSuccessor(BasicBlock* block, BasicBlock* succ);
309 void MoveSuccessors(BasicBlock* from, BasicBlock* to);
310
311 void SetControlInput(BasicBlock* block, Node* node);
312 void SetBlockForNode(BasicBlock* block, Node* node);
313
315 BasicBlockVector all_blocks_; // All basic blocks in the schedule.
316 BasicBlockVector nodeid_to_block_; // Map from node to containing block.
317 BasicBlockVector rpo_order_; // Reverse-post-order block list.
320};
321
322V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, const Schedule&);
323
324} // namespace compiler
325} // namespace internal
326} // namespace v8
327
328#endif // V8_COMPILER_SCHEDULE_H_
std::reverse_iterator< Node ** > reverse_iterator
static Id FromSize(size_t index)
Definition schedule.h:50
Node * NodeAt(size_t index)
Definition schedule.h:93
void set_rpo_next(BasicBlock *rpo_next)
Definition schedule.h:142
void set_deferred(bool deferred)
Definition schedule.h:133
BasicBlock * SuccessorAt(size_t index)
Definition schedule.h:85
value_type const & front() const
Definition schedule.h:97
NodeVector::const_iterator const_iterator
Definition schedule.h:105
BasicBlock * dominator() const
Definition schedule.h:138
void set_dominator(BasicBlock *dominator)
Definition schedule.h:139
BasicBlock * PredecessorAt(size_t index)
Definition schedule.h:76
NodeVector::iterator iterator
Definition schedule.h:99
BasicBlock & operator=(const BasicBlock &)=delete
BasicBlock * loop_header() const
Definition schedule.h:144
const_iterator begin() const
Definition schedule.h:106
void set_loop_number(int32_t loop_number)
Definition schedule.h:154
BasicBlock(const BasicBlock &)=delete
BasicBlockVector & successors()
Definition schedule.h:82
BasicBlockVector & predecessors()
Definition schedule.h:73
BasicBlock * loop_end() const
Definition schedule.h:147
void set_dominator_depth(int32_t depth)
Definition schedule.h:136
void InsertNodes(iterator insertion_point, InputIterator insertion_start, InputIterator insertion_end)
Definition schedule.h:115
const_iterator end() const
Definition schedule.h:107
const BasicBlockVector & successors() const
Definition schedule.h:83
const BasicBlockVector & predecessors() const
Definition schedule.h:74
BasicBlock * rpo_next() const
Definition schedule.h:141
NodeVector::reverse_iterator reverse_iterator
Definition schedule.h:109
BasicBlockVector * rpo_order()
Definition schedule.h:280
const BasicBlockVector * all_blocks() const
Definition schedule.h:279
Schedule & operator=(const Schedule &)=delete
void AddSuccessorForTesting(BasicBlock *block, BasicBlock *succ)
Definition schedule.h:275
const BasicBlockVector * rpo_order() const
Definition schedule.h:281
Schedule(const Schedule &)=delete
BasicBlockVector nodeid_to_block_
Definition schedule.h:316
Zone * zone_
Register const index_
uint8_t *const start_
Definition assembler.cc:131
const v8::base::TimeTicks end_
Definition sweeper.cc:54
uint32_t count
int end
ZoneLinkedList< BFEntry > nodes_
OptionalOpIndex index
Control control_
RpoNumber block
std::ostream & operator<<(std::ostream &os, AccessMode access_mode)
#define NON_EXPORTED_BASE(code)
#define V8_EXPORT_PRIVATE
Definition macros.h:460