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_GENERIC_NODE_H_
6 #define V8_COMPILER_GENERIC_NODE_H_
10 #include "src/zone-containers.h"
16 class GenericGraphBase;
20 // A GenericNode<> is the basic primitive of graphs. GenericNode's are
21 // chained together by input/use chains but by default otherwise contain only an
22 // identifying number which specific applications of graphs and nodes can use
23 // to index auxiliary out-of-line data, especially transient data.
24 // Specializations of the templatized GenericNode<> class must provide a base
25 // class B that contains all of the members to be made available in each
26 // specialized Node instance. GenericNode uses a mixin template pattern to
27 // ensure that common accessors and methods expect the derived class S type
28 // rather than the GenericNode<B, S> type.
29 template <class B, class S>
30 class GenericNode : public B {
33 typedef S DerivedClass;
35 inline NodeId id() const { return id_; }
37 int InputCount() const { return input_count_; }
38 S* InputAt(int index) const {
39 return static_cast<S*>(GetInputRecordPtr(index)->to);
41 inline void ReplaceInput(int index, GenericNode* new_input);
42 inline void AppendInput(Zone* zone, GenericNode* new_input);
43 inline void InsertInput(Zone* zone, int index, GenericNode* new_input);
44 inline void RemoveInput(int index);
46 int UseCount() { return use_count_; }
48 DCHECK(index < use_count_);
49 Use* current = first_use_;
50 while (index-- != 0) {
51 current = current->next;
53 return static_cast<S*>(current->from);
55 inline void ReplaceUses(GenericNode* replace_to);
56 template <class UnaryPredicate>
57 inline void ReplaceUsesIf(UnaryPredicate pred, GenericNode* replace_to);
58 inline void RemoveAllInputs();
60 inline void TrimInputCount(int input_count);
68 explicit Inputs(GenericNode* node) : node_(node) {}
74 Inputs inputs() { return Inputs(this); }
81 bool empty() { return begin() == end(); }
83 explicit Uses(GenericNode* node) : node_(node) {}
89 Uses uses() { return Uses(this); }
93 bool OwnedBy(GenericNode* owner) const;
95 static S* New(GenericGraphBase* graph, int input_count, S** inputs);
98 friend class GenericGraphBase;
100 class Use : public ZoneObject {
113 void Update(GenericNode* new_to);
116 void EnsureAppendableInputs(Zone* zone);
118 Input* GetInputRecordPtr(int index) const {
119 if (has_appendable_inputs_) {
120 return &((*inputs_.appendable_)[index]);
122 return inputs_.static_ + index;
126 inline void AppendUse(Use* use);
127 inline void RemoveUse(Use* use);
129 void* operator new(size_t, void* location) { return location; }
131 GenericNode(GenericGraphBase* graph, int input_count);
134 void AssignUniqueID(GenericGraphBase* graph);
136 typedef ZoneDeque<Input> InputDeque;
139 int input_count_ : 31;
140 bool has_appendable_inputs_ : 1;
142 // When a node is initially allocated, it uses a static buffer to hold its
143 // inputs under the assumption that the number of outputs will not increase.
144 // When the first input is appended, the static buffer is converted into a
145 // deque to allow for space-efficient growing.
147 InputDeque* appendable_;
153 DISALLOW_COPY_AND_ASSIGN(GenericNode);
156 // An encapsulation for information associated with a single use of node as a
157 // input from another node, allowing access to both the defining node and
158 // the ndoe having the input.
159 template <class B, class S>
160 class GenericNode<B, S>::Edge {
162 S* from() const { return static_cast<S*>(input_->use->from); }
163 S* to() const { return static_cast<S*>(input_->to); }
165 int index = input_->use->input_index;
166 DCHECK(index < input_->use->from->input_count_);
171 friend class GenericNode<B, S>::Uses::iterator;
172 friend class GenericNode<B, S>::Inputs::iterator;
174 explicit Edge(typename GenericNode<B, S>::Input* input) : input_(input) {}
176 typename GenericNode<B, S>::Input* input_;
179 // A forward iterator to visit the nodes which are depended upon by a node
180 // in the order of input.
181 template <class B, class S>
182 class GenericNode<B, S>::Inputs::iterator {
184 iterator(const typename GenericNode<B, S>::Inputs::iterator& other) // NOLINT
185 : node_(other.node_),
186 index_(other.index_) {}
188 S* operator*() { return static_cast<S*>(GetInput()->to); }
189 typename GenericNode<B, S>::Edge edge() {
190 return typename GenericNode::Edge(GetInput());
192 bool operator==(const iterator& other) const {
193 return other.index_ == index_ && other.node_ == node_;
195 bool operator!=(const iterator& other) const { return !(other == *this); }
196 iterator& operator++() {
197 DCHECK(node_ != NULL);
198 DCHECK(index_ < node_->input_count_);
202 iterator& UpdateToAndIncrement(GenericNode<B, S>* new_to) {
203 typename GenericNode<B, S>::Input* input = GetInput();
204 input->Update(new_to);
208 int index() { return index_; }
211 friend class GenericNode;
213 explicit iterator(GenericNode* node, int index)
214 : node_(node), index_(index) {}
216 Input* GetInput() const { return node_->GetInputRecordPtr(index_); }
222 // A forward iterator to visit the uses of a node. The uses are returned in
223 // the order in which they were added as inputs.
224 template <class B, class S>
225 class GenericNode<B, S>::Uses::iterator {
227 iterator(const typename GenericNode<B, S>::Uses::iterator& other) // NOLINT
228 : current_(other.current_),
229 index_(other.index_) {}
231 S* operator*() { return static_cast<S*>(current_->from); }
232 typename GenericNode<B, S>::Edge edge() {
233 return typename GenericNode::Edge(CurrentInput());
236 bool operator==(const iterator& other) { return other.current_ == current_; }
237 bool operator!=(const iterator& other) { return other.current_ != current_; }
238 iterator& operator++() {
239 DCHECK(current_ != NULL);
241 current_ = current_->next;
244 iterator& UpdateToAndIncrement(GenericNode<B, S>* new_to) {
245 DCHECK(current_ != NULL);
247 typename GenericNode<B, S>::Input* input = CurrentInput();
248 current_ = current_->next;
249 input->Update(new_to);
252 int index() const { return index_; }
255 friend class GenericNode<B, S>::Uses;
257 iterator() : current_(NULL), index_(0) {}
258 explicit iterator(GenericNode<B, S>* node)
259 : current_(node->first_use_), index_(0) {}
261 Input* CurrentInput() const {
262 return current_->from->GetInputRecordPtr(current_->input_index);
265 typename GenericNode<B, S>::Use* current_;
270 } // namespace v8::internal::compiler
272 #endif // V8_COMPILER_GENERIC_NODE_H_