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);
66 void RemoveAllInputs();
67 void TrimInputCount(int new_input_count);
70 Node* UseAt(int index) const;
71 void ReplaceUses(Node* replace_to);
73 class InputEdges FINAL {
75 typedef Edge value_type;
78 inline iterator begin() const;
79 inline iterator end() const;
83 explicit InputEdges(Node* node) : node_(node) {}
89 InputEdges input_edges() { return InputEdges(this); }
93 typedef Node* value_type;
96 inline const_iterator begin() const;
97 inline const_iterator end() const;
101 explicit Inputs(Node* node) : node_(node) {}
107 Inputs inputs() { return Inputs(this); }
109 class UseEdges FINAL {
111 typedef Edge value_type;
114 inline iterator begin() const;
115 inline iterator end() const;
119 explicit UseEdges(Node* node) : node_(node) {}
125 UseEdges use_edges() { return UseEdges(this); }
129 typedef Node* value_type;
131 class const_iterator;
132 inline const_iterator begin() const;
133 inline const_iterator end() const;
137 explicit Uses(Node* node) : node_(node) {}
143 Uses uses() { return Uses(this); }
145 // Returns true if {owner} is the user of {this} node.
146 bool OwnedBy(Node* owner) const {
147 return first_use_ && first_use_->from == owner && !first_use_->next;
151 struct Use FINAL : public ZoneObject {
163 void Update(Node* new_to);
166 inline Node(NodeId id, const Operator* op, int input_count,
167 int reserve_input_count);
169 inline void EnsureAppendableInputs(Zone* zone);
171 Input* GetInputRecordPtr(int index) {
172 return has_appendable_inputs() ? &((*inputs_.appendable_)[index])
173 : &inputs_.static_[index];
175 const Input* GetInputRecordPtr(int index) const {
176 return has_appendable_inputs() ? &((*inputs_.appendable_)[index])
177 : &inputs_.static_[index];
180 inline void AppendUse(Use* const use);
181 inline void RemoveUse(Use* const use);
183 void* operator new(size_t, void* location) { return location; }
185 typedef ZoneDeque<Input> InputDeque;
187 // Only NodeProperties should manipulate the bounds.
188 Bounds bounds() { return bounds_; }
189 void set_bounds(Bounds b) { bounds_ = b; }
191 // Only NodeMarkers should manipulate the marks on nodes.
192 Mark mark() { return mark_; }
193 void set_mark(Mark mark) { mark_ = mark; }
195 int input_count() const { return InputCountField::decode(bit_field_); }
196 void set_input_count(int input_count) {
197 DCHECK_LE(0, input_count);
198 bit_field_ = InputCountField::update(bit_field_, input_count);
201 int reserved_input_count() const {
202 return ReservedInputCountField::decode(bit_field_);
204 void set_reserved_input_count(int reserved_input_count) {
205 DCHECK_LE(0, reserved_input_count);
207 ReservedInputCountField::update(bit_field_, reserved_input_count);
210 bool has_appendable_inputs() const {
211 return HasAppendableInputsField::decode(bit_field_);
213 void set_has_appendable_inputs(bool has_appendable_inputs) {
215 HasAppendableInputsField::update(bit_field_, has_appendable_inputs);
218 typedef BitField<unsigned, 0, 29> InputCountField;
219 typedef BitField<unsigned, 29, 2> ReservedInputCountField;
220 typedef BitField<unsigned, 31, 1> HasAppendableInputsField;
221 static const int kDefaultReservedInputs = ReservedInputCountField::kMax;
231 // When a node is initially allocated, it uses a static buffer to hold its
232 // inputs under the assumption that the number of outputs will not increase.
233 // When the first input is appended, the static buffer is converted into a
234 // deque to allow for space-efficient growing.
236 InputDeque* appendable_;
240 friend class NodeMarkerBase;
241 friend class NodeProperties;
243 DISALLOW_COPY_AND_ASSIGN(Node);
247 std::ostream& operator<<(std::ostream& os, const Node& n);
250 // Typedefs to shorten commonly used Node containers.
251 typedef ZoneDeque<Node*> NodeDeque;
252 typedef ZoneVector<Node*> NodeVector;
253 typedef ZoneVector<NodeVector> NodeVectorVector;
256 // Helper to extract parameters from Operator1<*> nodes.
257 template <typename T>
258 static inline const T& OpParameter(const Node* node) {
259 return OpParameter<T>(node->op());
263 // An encapsulation for information associated with a single use of node as a
264 // input from another node, allowing access to both the defining node and
265 // the node having the input.
268 Node* from() const { return input_->use->from; }
269 Node* to() const { return input_->to; }
271 int const index = input_->use->input_index;
272 DCHECK_LT(index, input_->use->from->input_count());
276 bool operator==(const Edge& other) { return input_ == other.input_; }
277 bool operator!=(const Edge& other) { return !(*this == other); }
279 void UpdateTo(Node* new_to) { input_->Update(new_to); }
282 friend class Node::UseEdges::iterator;
283 friend class Node::InputEdges::iterator;
285 explicit Edge(Node::Input* input) : input_(input) { DCHECK_NOT_NULL(input); }
291 // A forward iterator to visit the edges for the input dependencies of a node.
292 class Node::InputEdges::iterator FINAL {
294 typedef std::forward_iterator_tag iterator_category;
295 typedef int difference_type;
296 typedef Edge value_type;
297 typedef Edge* pointer;
298 typedef Edge& reference;
300 iterator() : input_(nullptr) {}
301 iterator(const iterator& other) : input_(other.input_) {}
303 Edge operator*() const { return Edge(input_); }
304 bool operator==(const iterator& other) const {
305 return input_ == other.input_;
307 bool operator!=(const iterator& other) const { return !(*this == other); }
308 iterator& operator++() {
309 SetInput(Edge(input_).from(), input_->use->input_index + 1);
312 iterator operator++(int);
317 explicit iterator(Node* from, int index = 0) : input_(nullptr) {
318 SetInput(from, index);
321 void SetInput(Node* from, int index) {
322 DCHECK(index >= 0 && index <= from->InputCount());
323 if (index < from->InputCount()) {
324 input_ = from->GetInputRecordPtr(index);
334 Node::InputEdges::iterator Node::InputEdges::begin() const {
335 return Node::InputEdges::iterator(this->node_, 0);
339 Node::InputEdges::iterator Node::InputEdges::end() const {
340 return Node::InputEdges::iterator(this->node_, this->node_->InputCount());
344 // A forward iterator to visit the inputs of a node.
345 class Node::Inputs::const_iterator FINAL {
347 typedef std::forward_iterator_tag iterator_category;
348 typedef int difference_type;
349 typedef Node* value_type;
350 typedef Node** pointer;
351 typedef Node*& reference;
353 const_iterator(const const_iterator& other) : iter_(other.iter_) {}
355 Node* operator*() const { return (*iter_).to(); }
356 bool operator==(const const_iterator& other) const {
357 return iter_ == other.iter_;
359 bool operator!=(const const_iterator& other) const {
360 return !(*this == other);
362 const_iterator& operator++() {
366 const_iterator operator++(int);
369 friend class Node::Inputs;
371 const_iterator(Node* node, int index) : iter_(node, index) {}
373 Node::InputEdges::iterator iter_;
377 Node::Inputs::const_iterator Node::Inputs::begin() const {
378 return const_iterator(this->node_, 0);
382 Node::Inputs::const_iterator Node::Inputs::end() const {
383 return const_iterator(this->node_, this->node_->InputCount());
387 // A forward iterator to visit the uses edges of a node. The edges are returned
389 // the order in which they were added as inputs.
390 class Node::UseEdges::iterator FINAL {
392 iterator(const iterator& other)
393 : current_(other.current_), next_(other.next_) {}
395 Edge operator*() const {
396 return Edge(current_->from->GetInputRecordPtr(current_->input_index));
399 bool operator==(const iterator& other) const {
400 return current_ == other.current_;
402 bool operator!=(const iterator& other) const { return !(*this == other); }
403 iterator& operator++() {
404 DCHECK_NOT_NULL(current_);
406 next_ = current_ ? current_->next : nullptr;
409 iterator operator++(int);
412 friend class Node::UseEdges;
414 iterator() : current_(nullptr), next_(nullptr) {}
415 explicit iterator(Node* node)
416 : current_(node->first_use_),
417 next_(current_ ? current_->next : nullptr) {}
424 Node::UseEdges::iterator Node::UseEdges::begin() const {
425 return Node::UseEdges::iterator(this->node_);
429 Node::UseEdges::iterator Node::UseEdges::end() const {
430 return Node::UseEdges::iterator();
434 // A forward iterator to visit the uses of a node. The uses are returned in
435 // the order in which they were added as inputs.
436 class Node::Uses::const_iterator FINAL {
438 typedef std::forward_iterator_tag iterator_category;
439 typedef int difference_type;
440 typedef Node* value_type;
441 typedef Node** pointer;
442 typedef Node*& reference;
444 const_iterator(const const_iterator& other) : current_(other.current_) {}
446 Node* operator*() const { return current_->from; }
447 bool operator==(const const_iterator& other) const {
448 return other.current_ == current_;
450 bool operator!=(const const_iterator& other) const {
451 return other.current_ != current_;
453 const_iterator& operator++() {
454 DCHECK_NOT_NULL(current_);
455 current_ = current_->next;
458 const_iterator operator++(int);
461 friend class Node::Uses;
463 const_iterator() : current_(nullptr) {}
464 explicit const_iterator(Node* node) : current_(node->first_use_) {}
470 Node::Uses::const_iterator Node::Uses::begin() const {
471 return const_iterator(this->node_);
475 Node::Uses::const_iterator Node::Uses::end() const { return const_iterator(); }
478 void Node::ReplaceInput(int index, Node* new_to) {
479 GetInputRecordPtr(index)->Update(new_to);
482 } // namespace compiler
483 } // namespace internal
486 #endif // V8_COMPILER_NODE_H_