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.
5 #ifndef V8_COMPILER_NODE_H_
6 #define V8_COMPILER_NODE_H_
8 #include "src/compiler/opcodes.h"
9 #include "src/compiler/operator.h"
10 #include "src/types-inl.h"
11 #include "src/zone-containers.h"
17 // Forward declarations.
22 // Marks are used during traversal of the graph to distinguish states of nodes.
23 // Each node has a mark which is a monotonically increasing integer, and a
24 // {NodeMarker} has a range of values that indicate states of a node.
25 typedef uint32_t Mark;
28 // NodeIds are identifying numbers for nodes that can be used to index auxiliary
29 // out-of-line data associated with each node.
30 typedef int32_t NodeId;
33 // A Node is the basic primitive of graphs. Nodes are chained together by
34 // input/use chains but by default otherwise contain only an identifying number
35 // which specific applications of graphs and nodes can use to index auxiliary
36 // out-of-line data, especially transient data.
38 // In addition Nodes only contain a mutable Operator that may change during
39 // compilation, e.g. during lowering passes. Other information that needs to be
40 // associated with Nodes during compilation must be stored out-of-line indexed
44 static Node* New(Zone* zone, NodeId id, const Operator* op, int input_count,
45 Node** inputs, bool has_extensible_inputs);
47 bool IsDead() const { return InputCount() > 0 && !InputAt(0); }
50 const Operator* op() const { return op_; }
51 void set_op(const Operator* op) { op_ = op; }
53 IrOpcode::Value opcode() const {
54 DCHECK(op_->opcode() <= IrOpcode::kLast);
55 return static_cast<IrOpcode::Value>(op_->opcode());
58 NodeId id() const { return id_; }
60 int InputCount() const { return input_count(); }
61 Node* InputAt(int index) const { return GetInputRecordPtr(index)->to; }
62 inline void ReplaceInput(int index, Node* new_to);
63 void AppendInput(Zone* zone, Node* new_to);
64 void InsertInput(Zone* zone, int index, Node* new_to);
65 void RemoveInput(int index);
67 void TrimInputCount(int new_input_count);
70 void ReplaceUses(Node* replace_to);
72 class InputEdges FINAL {
74 typedef Edge value_type;
77 inline iterator begin() const;
78 inline iterator end() const;
82 explicit InputEdges(Node* node) : node_(node) {}
88 InputEdges input_edges() { return InputEdges(this); }
92 typedef Node* value_type;
95 inline const_iterator begin() const;
96 inline const_iterator end() const;
100 explicit Inputs(Node* node) : node_(node) {}
106 Inputs inputs() { return Inputs(this); }
108 class UseEdges FINAL {
110 typedef Edge value_type;
113 inline iterator begin() const;
114 inline iterator end() const;
118 explicit UseEdges(Node* node) : node_(node) {}
124 UseEdges use_edges() { return UseEdges(this); }
128 typedef Node* value_type;
130 class const_iterator;
131 inline const_iterator begin() const;
132 inline const_iterator end() const;
136 explicit Uses(Node* node) : node_(node) {}
142 Uses uses() { return Uses(this); }
144 // Returns true if {owner} is the user of {this} node.
145 bool OwnedBy(Node* owner) const {
146 return first_use_ && first_use_->from == owner && !first_use_->next;
150 struct Use FINAL : public ZoneObject {
162 void Update(Node* new_to);
165 inline Node(NodeId id, const Operator* op, int input_count,
166 int reserve_input_count);
168 inline void EnsureAppendableInputs(Zone* zone);
170 Input* GetInputRecordPtr(int index) {
171 return has_appendable_inputs() ? &((*inputs_.appendable_)[index])
172 : &inputs_.static_[index];
174 const Input* GetInputRecordPtr(int index) const {
175 return has_appendable_inputs() ? &((*inputs_.appendable_)[index])
176 : &inputs_.static_[index];
179 inline void AppendUse(Use* const use);
180 inline void RemoveUse(Use* const use);
182 void* operator new(size_t, void* location) { return location; }
184 typedef ZoneDeque<Input> InputDeque;
186 // Only NodeProperties should manipulate the bounds.
187 Bounds bounds() { return bounds_; }
188 void set_bounds(Bounds b) { bounds_ = b; }
190 // Only NodeMarkers should manipulate the marks on nodes.
191 Mark mark() { return mark_; }
192 void set_mark(Mark mark) { mark_ = mark; }
194 int input_count() const { return InputCountField::decode(bit_field_); }
195 void set_input_count(int input_count) {
196 DCHECK_LE(0, input_count);
197 bit_field_ = InputCountField::update(bit_field_, input_count);
200 int reserved_input_count() const {
201 return ReservedInputCountField::decode(bit_field_);
203 void set_reserved_input_count(int reserved_input_count) {
204 DCHECK_LE(0, reserved_input_count);
206 ReservedInputCountField::update(bit_field_, reserved_input_count);
209 bool has_appendable_inputs() const {
210 return HasAppendableInputsField::decode(bit_field_);
212 void set_has_appendable_inputs(bool has_appendable_inputs) {
214 HasAppendableInputsField::update(bit_field_, has_appendable_inputs);
217 typedef BitField<unsigned, 0, 29> InputCountField;
218 typedef BitField<unsigned, 29, 2> ReservedInputCountField;
219 typedef BitField<unsigned, 31, 1> HasAppendableInputsField;
220 static const int kDefaultReservedInputs = ReservedInputCountField::kMax;
229 // When a node is initially allocated, it uses a static buffer to hold its
230 // inputs under the assumption that the number of outputs will not increase.
231 // When the first input is appended, the static buffer is converted into a
232 // deque to allow for space-efficient growing.
234 InputDeque* appendable_;
238 friend class NodeMarkerBase;
239 friend class NodeProperties;
241 DISALLOW_COPY_AND_ASSIGN(Node);
245 std::ostream& operator<<(std::ostream& os, const Node& n);
248 // Typedefs to shorten commonly used Node containers.
249 typedef ZoneDeque<Node*> NodeDeque;
250 typedef ZoneSet<Node*> NodeSet;
251 typedef ZoneVector<Node*> NodeVector;
252 typedef ZoneVector<NodeVector> NodeVectorVector;
255 // Helper to extract parameters from Operator1<*> nodes.
256 template <typename T>
257 static inline const T& OpParameter(const Node* node) {
258 return OpParameter<T>(node->op());
262 // An encapsulation for information associated with a single use of node as a
263 // input from another node, allowing access to both the defining node and
264 // the node having the input.
267 Node* from() const { return input_->use->from; }
268 Node* to() const { return input_->to; }
270 int const index = input_->use->input_index;
271 DCHECK_LT(index, input_->use->from->input_count());
275 bool operator==(const Edge& other) { return input_ == other.input_; }
276 bool operator!=(const Edge& other) { return !(*this == other); }
278 void UpdateTo(Node* new_to) { input_->Update(new_to); }
281 friend class Node::UseEdges::iterator;
282 friend class Node::InputEdges::iterator;
284 explicit Edge(Node::Input* input) : input_(input) { DCHECK_NOT_NULL(input); }
290 // A forward iterator to visit the edges for the input dependencies of a node.
291 class Node::InputEdges::iterator FINAL {
293 typedef std::forward_iterator_tag iterator_category;
294 typedef int difference_type;
295 typedef Edge value_type;
296 typedef Edge* pointer;
297 typedef Edge& reference;
299 iterator() : input_(nullptr) {}
300 iterator(const iterator& other) : input_(other.input_) {}
302 Edge operator*() const { return Edge(input_); }
303 bool operator==(const iterator& other) const {
304 return input_ == other.input_;
306 bool operator!=(const iterator& other) const { return !(*this == other); }
307 iterator& operator++() {
308 SetInput(Edge(input_).from(), input_->use->input_index + 1);
311 iterator operator++(int);
316 explicit iterator(Node* from, int index = 0) : input_(nullptr) {
317 SetInput(from, index);
320 void SetInput(Node* from, int index) {
321 DCHECK(index >= 0 && index <= from->InputCount());
322 if (index < from->InputCount()) {
323 input_ = from->GetInputRecordPtr(index);
333 Node::InputEdges::iterator Node::InputEdges::begin() const {
334 return Node::InputEdges::iterator(this->node_, 0);
338 Node::InputEdges::iterator Node::InputEdges::end() const {
339 return Node::InputEdges::iterator(this->node_, this->node_->InputCount());
343 // A forward iterator to visit the inputs of a node.
344 class Node::Inputs::const_iterator FINAL {
346 typedef std::forward_iterator_tag iterator_category;
347 typedef int difference_type;
348 typedef Node* value_type;
349 typedef Node** pointer;
350 typedef Node*& reference;
352 const_iterator(const const_iterator& other) : iter_(other.iter_) {}
354 Node* operator*() const { return (*iter_).to(); }
355 bool operator==(const const_iterator& other) const {
356 return iter_ == other.iter_;
358 bool operator!=(const const_iterator& other) const {
359 return !(*this == other);
361 const_iterator& operator++() {
365 const_iterator operator++(int);
368 friend class Node::Inputs;
370 const_iterator(Node* node, int index) : iter_(node, index) {}
372 Node::InputEdges::iterator iter_;
376 Node::Inputs::const_iterator Node::Inputs::begin() const {
377 return const_iterator(this->node_, 0);
381 Node::Inputs::const_iterator Node::Inputs::end() const {
382 return const_iterator(this->node_, this->node_->InputCount());
386 // A forward iterator to visit the uses edges of a node. The edges are returned
388 // the order in which they were added as inputs.
389 class Node::UseEdges::iterator FINAL {
391 iterator(const iterator& other)
392 : current_(other.current_), next_(other.next_) {}
394 Edge operator*() const {
395 return Edge(current_->from->GetInputRecordPtr(current_->input_index));
398 bool operator==(const iterator& other) const {
399 return current_ == other.current_;
401 bool operator!=(const iterator& other) const { return !(*this == other); }
402 iterator& operator++() {
403 DCHECK_NOT_NULL(current_);
405 next_ = current_ ? current_->next : nullptr;
408 iterator operator++(int);
411 friend class Node::UseEdges;
413 iterator() : current_(nullptr), next_(nullptr) {}
414 explicit iterator(Node* node)
415 : current_(node->first_use_),
416 next_(current_ ? current_->next : nullptr) {}
423 Node::UseEdges::iterator Node::UseEdges::begin() const {
424 return Node::UseEdges::iterator(this->node_);
428 Node::UseEdges::iterator Node::UseEdges::end() const {
429 return Node::UseEdges::iterator();
433 // A forward iterator to visit the uses of a node. The uses are returned in
434 // the order in which they were added as inputs.
435 class Node::Uses::const_iterator FINAL {
437 typedef std::forward_iterator_tag iterator_category;
438 typedef int difference_type;
439 typedef Node* value_type;
440 typedef Node** pointer;
441 typedef Node*& reference;
443 const_iterator(const const_iterator& other) : current_(other.current_) {}
445 Node* operator*() const { return current_->from; }
446 bool operator==(const const_iterator& other) const {
447 return other.current_ == current_;
449 bool operator!=(const const_iterator& other) const {
450 return other.current_ != current_;
452 const_iterator& operator++() {
453 DCHECK_NOT_NULL(current_);
454 current_ = current_->next;
457 const_iterator operator++(int);
460 friend class Node::Uses;
462 const_iterator() : current_(nullptr) {}
463 explicit const_iterator(Node* node) : current_(node->first_use_) {}
469 Node::Uses::const_iterator Node::Uses::begin() const {
470 return const_iterator(this->node_);
474 Node::Uses::const_iterator Node::Uses::end() const { return const_iterator(); }
477 void Node::ReplaceInput(int index, Node* new_to) {
478 GetInputRecordPtr(index)->Update(new_to);
481 } // namespace compiler
482 } // namespace internal
485 #endif // V8_COMPILER_NODE_H_