"src/compiler/generic-algorithm-inl.h",
"src/compiler/generic-algorithm.h",
"src/compiler/generic-graph.h",
+ "src/compiler/generic-node-inl.h",
+ "src/compiler/generic-node.h",
"src/compiler/graph-builder.cc",
"src/compiler/graph-builder.h",
"src/compiler/graph-inl.h",
#include "src/compiler/generic-algorithm.h"
#include "src/compiler/generic-graph.h"
+#include "src/compiler/generic-node.h"
+#include "src/compiler/generic-node-inl.h"
namespace v8 {
namespace internal {
#include <stack>
#include "src/compiler/generic-graph.h"
+#include "src/compiler/generic-node.h"
#include "src/zone-containers.h"
namespace v8 {
Visit<Visitor, Traits>(graph, zone, &array[0], &array[1], visitor);
}
- template <class Node>
+ template <class B, class S>
struct NullNodeVisitor {
- Control Pre(Node* node) { return CONTINUE; }
- Control Post(Node* node) { return CONTINUE; }
- void PreEdge(Node* from, int index, Node* to) {}
- void PostEdge(Node* from, int index, Node* to) {}
+ Control Pre(GenericNode<B, S>* node) { return CONTINUE; }
+ Control Post(GenericNode<B, S>* node) { return CONTINUE; }
+ void PreEdge(GenericNode<B, S>* from, int index, GenericNode<B, S>* to) {}
+ void PostEdge(GenericNode<B, S>* from, int index, GenericNode<B, S>* to) {}
};
private:
#ifndef V8_COMPILER_GENERIC_GRAPH_H_
#define V8_COMPILER_GENERIC_GRAPH_H_
-#include "src/zone.h"
+#include "src/compiler/generic-node.h"
namespace v8 {
namespace internal {
-namespace compiler {
-typedef int NodeId;
+class Zone;
+
+namespace compiler {
class GenericGraphBase : public ZoneObject {
public:
--- /dev/null
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_GENERIC_NODE_INL_H_
+#define V8_COMPILER_GENERIC_NODE_INL_H_
+
+#include "src/v8.h"
+
+#include "src/compiler/generic-graph.h"
+#include "src/compiler/generic-node.h"
+#include "src/zone.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+template <class B, class S>
+GenericNode<B, S>::GenericNode(GenericGraphBase* graph, int input_count,
+ int reserve_input_count)
+ : BaseClass(graph->zone()),
+ input_count_(input_count),
+ reserve_input_count_(reserve_input_count),
+ has_appendable_inputs_(false),
+ use_count_(0),
+ first_use_(NULL),
+ last_use_(NULL) {
+ DCHECK(reserve_input_count <= kMaxReservedInputs);
+ inputs_.static_ = reinterpret_cast<Input*>(this + 1);
+ AssignUniqueID(graph);
+}
+
+template <class B, class S>
+inline void GenericNode<B, S>::AssignUniqueID(GenericGraphBase* graph) {
+ id_ = graph->NextNodeID();
+}
+
+template <class B, class S>
+inline typename GenericNode<B, S>::Inputs::iterator
+GenericNode<B, S>::Inputs::begin() {
+ return typename GenericNode<B, S>::Inputs::iterator(this->node_, 0);
+}
+
+template <class B, class S>
+inline typename GenericNode<B, S>::Inputs::iterator
+GenericNode<B, S>::Inputs::end() {
+ return typename GenericNode<B, S>::Inputs::iterator(
+ this->node_, this->node_->InputCount());
+}
+
+template <class B, class S>
+inline typename GenericNode<B, S>::Uses::iterator
+GenericNode<B, S>::Uses::begin() {
+ return typename GenericNode<B, S>::Uses::iterator(this->node_);
+}
+
+template <class B, class S>
+inline typename GenericNode<B, S>::Uses::iterator
+GenericNode<B, S>::Uses::end() {
+ return typename GenericNode<B, S>::Uses::iterator();
+}
+
+template <class B, class S>
+void GenericNode<B, S>::ReplaceUses(GenericNode* replace_to) {
+ for (Use* use = first_use_; use != NULL; use = use->next) {
+ use->from->GetInputRecordPtr(use->input_index)->to = replace_to;
+ }
+ if (replace_to->last_use_ == NULL) {
+ DCHECK_EQ(NULL, replace_to->first_use_);
+ replace_to->first_use_ = first_use_;
+ replace_to->last_use_ = last_use_;
+ } else if (first_use_ != NULL) {
+ DCHECK_NE(NULL, replace_to->first_use_);
+ replace_to->last_use_->next = first_use_;
+ first_use_->prev = replace_to->last_use_;
+ replace_to->last_use_ = last_use_;
+ }
+ replace_to->use_count_ += use_count_;
+ use_count_ = 0;
+ first_use_ = NULL;
+ last_use_ = NULL;
+}
+
+template <class B, class S>
+template <class UnaryPredicate>
+void GenericNode<B, S>::ReplaceUsesIf(UnaryPredicate pred,
+ GenericNode* replace_to) {
+ for (Use* use = first_use_; use != NULL;) {
+ Use* next = use->next;
+ if (pred(static_cast<S*>(use->from))) {
+ RemoveUse(use);
+ replace_to->AppendUse(use);
+ use->from->GetInputRecordPtr(use->input_index)->to = replace_to;
+ }
+ use = next;
+ }
+}
+
+template <class B, class S>
+void GenericNode<B, S>::RemoveAllInputs() {
+ for (typename Inputs::iterator iter(inputs().begin()); iter != inputs().end();
+ ++iter) {
+ iter.GetInput()->Update(NULL);
+ }
+}
+
+template <class B, class S>
+void GenericNode<B, S>::TrimInputCount(int new_input_count) {
+ if (new_input_count == input_count_) return; // Nothing to do.
+
+ DCHECK(new_input_count < input_count_);
+
+ // Update inline inputs.
+ for (int i = new_input_count; i < input_count_; i++) {
+ typename GenericNode<B, S>::Input* input = GetInputRecordPtr(i);
+ input->Update(NULL);
+ }
+ input_count_ = new_input_count;
+}
+
+template <class B, class S>
+void GenericNode<B, S>::ReplaceInput(int index, GenericNode<B, S>* new_to) {
+ Input* input = GetInputRecordPtr(index);
+ input->Update(new_to);
+}
+
+template <class B, class S>
+void GenericNode<B, S>::Input::Update(GenericNode<B, S>* new_to) {
+ GenericNode* old_to = this->to;
+ if (new_to == old_to) return; // Nothing to do.
+ // Snip out the use from where it used to be
+ if (old_to != NULL) {
+ old_to->RemoveUse(use);
+ }
+ to = new_to;
+ // And put it into the new node's use list.
+ if (new_to != NULL) {
+ new_to->AppendUse(use);
+ } else {
+ use->next = NULL;
+ use->prev = NULL;
+ }
+}
+
+template <class B, class S>
+void GenericNode<B, S>::EnsureAppendableInputs(Zone* zone) {
+ if (!has_appendable_inputs_) {
+ void* deque_buffer = zone->New(sizeof(InputDeque));
+ InputDeque* deque = new (deque_buffer) InputDeque(zone);
+ for (int i = 0; i < input_count_; ++i) {
+ deque->push_back(inputs_.static_[i]);
+ }
+ inputs_.appendable_ = deque;
+ has_appendable_inputs_ = true;
+ }
+}
+
+template <class B, class S>
+void GenericNode<B, S>::AppendInput(Zone* zone, GenericNode<B, S>* to_append) {
+ Use* new_use = new (zone) Use;
+ Input new_input;
+ new_input.to = to_append;
+ new_input.use = new_use;
+ if (reserve_input_count_ > 0) {
+ DCHECK(!has_appendable_inputs_);
+ reserve_input_count_--;
+ inputs_.static_[input_count_] = new_input;
+ } else {
+ EnsureAppendableInputs(zone);
+ inputs_.appendable_->push_back(new_input);
+ }
+ new_use->input_index = input_count_;
+ new_use->from = this;
+ to_append->AppendUse(new_use);
+ input_count_++;
+}
+
+template <class B, class S>
+void GenericNode<B, S>::InsertInput(Zone* zone, int index,
+ GenericNode<B, S>* to_insert) {
+ DCHECK(index >= 0 && index < InputCount());
+ // TODO(turbofan): Optimize this implementation!
+ AppendInput(zone, InputAt(InputCount() - 1));
+ for (int i = InputCount() - 1; i > index; --i) {
+ ReplaceInput(i, InputAt(i - 1));
+ }
+ ReplaceInput(index, to_insert);
+}
+
+template <class B, class S>
+void GenericNode<B, S>::RemoveInput(int index) {
+ DCHECK(index >= 0 && index < InputCount());
+ // TODO(turbofan): Optimize this implementation!
+ for (; index < InputCount() - 1; ++index) {
+ ReplaceInput(index, InputAt(index + 1));
+ }
+ TrimInputCount(InputCount() - 1);
+}
+
+template <class B, class S>
+void GenericNode<B, S>::AppendUse(Use* use) {
+ use->next = NULL;
+ use->prev = last_use_;
+ if (last_use_ == NULL) {
+ first_use_ = use;
+ } else {
+ last_use_->next = use;
+ }
+ last_use_ = use;
+ ++use_count_;
+}
+
+template <class B, class S>
+void GenericNode<B, S>::RemoveUse(Use* use) {
+ if (last_use_ == use) {
+ last_use_ = use->prev;
+ }
+ if (use->prev != NULL) {
+ use->prev->next = use->next;
+ } else {
+ first_use_ = use->next;
+ }
+ if (use->next != NULL) {
+ use->next->prev = use->prev;
+ }
+ --use_count_;
+}
+
+template <class B, class S>
+inline bool GenericNode<B, S>::OwnedBy(GenericNode* owner) const {
+ return first_use_ != NULL && first_use_->from == owner &&
+ first_use_->next == NULL;
+}
+
+template <class B, class S>
+S* GenericNode<B, S>::New(GenericGraphBase* graph, int input_count, S** inputs,
+ bool has_extensible_inputs) {
+ size_t node_size = sizeof(GenericNode);
+ int reserve_input_count = has_extensible_inputs ? kDefaultReservedInputs : 0;
+ size_t inputs_size = (input_count + reserve_input_count) * sizeof(Input);
+ size_t uses_size = input_count * sizeof(Use);
+ int size = static_cast<int>(node_size + inputs_size + uses_size);
+ Zone* zone = graph->zone();
+ void* buffer = zone->New(size);
+ S* result = new (buffer) S(graph, input_count, reserve_input_count);
+ Input* input =
+ reinterpret_cast<Input*>(reinterpret_cast<char*>(buffer) + node_size);
+ Use* use =
+ reinterpret_cast<Use*>(reinterpret_cast<char*>(input) + inputs_size);
+
+ for (int current = 0; current < input_count; ++current) {
+ GenericNode* to = *inputs++;
+ input->to = to;
+ input->use = use;
+ use->input_index = current;
+ use->from = result;
+ to->AppendUse(use);
+ ++use;
+ ++input;
+ }
+ return result;
+}
+}
+}
+} // namespace v8::internal::compiler
+
+#endif // V8_COMPILER_GENERIC_NODE_INL_H_
--- /dev/null
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_GENERIC_NODE_H_
+#define V8_COMPILER_GENERIC_NODE_H_
+
+#include "src/v8.h"
+
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class GenericGraphBase;
+
+typedef int NodeId;
+
+// A GenericNode<> is the basic primitive of graphs. GenericNode's are
+// chained together by input/use chains but by default otherwise contain only an
+// identifying number which specific applications of graphs and nodes can use
+// to index auxiliary out-of-line data, especially transient data.
+// Specializations of the templatized GenericNode<> class must provide a base
+// class B that contains all of the members to be made available in each
+// specialized Node instance. GenericNode uses a mixin template pattern to
+// ensure that common accessors and methods expect the derived class S type
+// rather than the GenericNode<B, S> type.
+template <class B, class S>
+class GenericNode : public B {
+ public:
+ typedef B BaseClass;
+ typedef S DerivedClass;
+
+ inline NodeId id() const { return id_; }
+
+ int InputCount() const { return input_count_; }
+ S* InputAt(int index) const {
+ return static_cast<S*>(GetInputRecordPtr(index)->to);
+ }
+ inline void ReplaceInput(int index, GenericNode* new_input);
+ inline void AppendInput(Zone* zone, GenericNode* new_input);
+ inline void InsertInput(Zone* zone, int index, GenericNode* new_input);
+ inline void RemoveInput(int index);
+
+ int UseCount() { return use_count_; }
+ S* UseAt(int index) {
+ DCHECK(index < use_count_);
+ Use* current = first_use_;
+ while (index-- != 0) {
+ current = current->next;
+ }
+ return static_cast<S*>(current->from);
+ }
+ inline void ReplaceUses(GenericNode* replace_to);
+ template <class UnaryPredicate>
+ inline void ReplaceUsesIf(UnaryPredicate pred, GenericNode* replace_to);
+ inline void RemoveAllInputs();
+
+ inline void TrimInputCount(int input_count);
+
+ class Inputs {
+ public:
+ class iterator;
+ iterator begin();
+ iterator end();
+
+ explicit Inputs(GenericNode* node) : node_(node) {}
+
+ private:
+ GenericNode* node_;
+ };
+
+ Inputs inputs() { return Inputs(this); }
+
+ class Uses {
+ public:
+ class iterator;
+ iterator begin();
+ iterator end();
+ bool empty() { return begin() == end(); }
+
+ explicit Uses(GenericNode* node) : node_(node) {}
+
+ private:
+ GenericNode* node_;
+ };
+
+ Uses uses() { return Uses(this); }
+
+ class Edge;
+
+ bool OwnedBy(GenericNode* owner) const;
+
+ static S* New(GenericGraphBase* graph, int input_count, S** inputs,
+ bool has_extensible_inputs);
+
+ protected:
+ friend class GenericGraphBase;
+
+ class Use : public ZoneObject {
+ public:
+ GenericNode* from;
+ Use* next;
+ Use* prev;
+ int input_index;
+ };
+
+ class Input {
+ public:
+ GenericNode* to;
+ Use* use;
+
+ void Update(GenericNode* new_to);
+ };
+
+ void EnsureAppendableInputs(Zone* zone);
+
+ Input* GetInputRecordPtr(int index) const {
+ if (has_appendable_inputs_) {
+ return &((*inputs_.appendable_)[index]);
+ } else {
+ return inputs_.static_ + index;
+ }
+ }
+
+ inline void AppendUse(Use* use);
+ inline void RemoveUse(Use* use);
+
+ void* operator new(size_t, void* location) { return location; }
+
+ GenericNode(GenericGraphBase* graph, int input_count,
+ int reserved_input_count);
+
+ private:
+ void AssignUniqueID(GenericGraphBase* graph);
+
+ typedef ZoneDeque<Input> InputDeque;
+
+ static const int kReservedInputCountBits = 2;
+ static const int kMaxReservedInputs = (1 << kReservedInputCountBits) - 1;
+ static const int kDefaultReservedInputs = kMaxReservedInputs;
+
+ NodeId id_;
+ int input_count_ : 29;
+ unsigned int reserve_input_count_ : kReservedInputCountBits;
+ bool has_appendable_inputs_ : 1;
+ union {
+ // When a node is initially allocated, it uses a static buffer to hold its
+ // inputs under the assumption that the number of outputs will not increase.
+ // When the first input is appended, the static buffer is converted into a
+ // deque to allow for space-efficient growing.
+ Input* static_;
+ InputDeque* appendable_;
+ } inputs_;
+ int use_count_;
+ Use* first_use_;
+ Use* last_use_;
+
+ DISALLOW_COPY_AND_ASSIGN(GenericNode);
+};
+
+// An encapsulation for information associated with a single use of node as a
+// input from another node, allowing access to both the defining node and
+// the ndoe having the input.
+template <class B, class S>
+class GenericNode<B, S>::Edge {
+ public:
+ S* from() const { return static_cast<S*>(input_->use->from); }
+ S* to() const { return static_cast<S*>(input_->to); }
+ int index() const {
+ int index = input_->use->input_index;
+ DCHECK(index < input_->use->from->input_count_);
+ return index;
+ }
+
+ private:
+ friend class GenericNode<B, S>::Uses::iterator;
+ friend class GenericNode<B, S>::Inputs::iterator;
+
+ explicit Edge(typename GenericNode<B, S>::Input* input) : input_(input) {}
+
+ typename GenericNode<B, S>::Input* input_;
+};
+
+// A forward iterator to visit the nodes which are depended upon by a node
+// in the order of input.
+template <class B, class S>
+class GenericNode<B, S>::Inputs::iterator {
+ public:
+ iterator(const typename GenericNode<B, S>::Inputs::iterator& other) // NOLINT
+ : node_(other.node_),
+ index_(other.index_) {}
+
+ S* operator*() { return static_cast<S*>(GetInput()->to); }
+ typename GenericNode<B, S>::Edge edge() {
+ return typename GenericNode::Edge(GetInput());
+ }
+ bool operator==(const iterator& other) const {
+ return other.index_ == index_ && other.node_ == node_;
+ }
+ bool operator!=(const iterator& other) const { return !(other == *this); }
+ iterator& operator++() {
+ DCHECK(node_ != NULL);
+ DCHECK(index_ < node_->input_count_);
+ ++index_;
+ return *this;
+ }
+ iterator& UpdateToAndIncrement(GenericNode<B, S>* new_to) {
+ typename GenericNode<B, S>::Input* input = GetInput();
+ input->Update(new_to);
+ index_++;
+ return *this;
+ }
+ int index() { return index_; }
+
+ private:
+ friend class GenericNode;
+
+ explicit iterator(GenericNode* node, int index)
+ : node_(node), index_(index) {}
+
+ Input* GetInput() const { return node_->GetInputRecordPtr(index_); }
+
+ GenericNode* node_;
+ int index_;
+};
+
+// A forward iterator to visit the uses of a node. The uses are returned in
+// the order in which they were added as inputs.
+template <class B, class S>
+class GenericNode<B, S>::Uses::iterator {
+ public:
+ iterator(const typename GenericNode<B, S>::Uses::iterator& other) // NOLINT
+ : current_(other.current_),
+ index_(other.index_) {}
+
+ S* operator*() { return static_cast<S*>(current_->from); }
+ typename GenericNode<B, S>::Edge edge() {
+ return typename GenericNode::Edge(CurrentInput());
+ }
+
+ bool operator==(const iterator& other) { return other.current_ == current_; }
+ bool operator!=(const iterator& other) { return other.current_ != current_; }
+ iterator& operator++() {
+ DCHECK(current_ != NULL);
+ index_++;
+ current_ = current_->next;
+ return *this;
+ }
+ iterator& UpdateToAndIncrement(GenericNode<B, S>* new_to) {
+ DCHECK(current_ != NULL);
+ index_++;
+ typename GenericNode<B, S>::Input* input = CurrentInput();
+ current_ = current_->next;
+ input->Update(new_to);
+ return *this;
+ }
+ int index() const { return index_; }
+
+ private:
+ friend class GenericNode<B, S>::Uses;
+
+ iterator() : current_(NULL), index_(0) {}
+ explicit iterator(GenericNode<B, S>* node)
+ : current_(node->first_use_), index_(0) {}
+
+ Input* CurrentInput() const {
+ return current_->from->GetInputRecordPtr(current_->input_index);
+ }
+
+ typename GenericNode<B, S>::Use* current_;
+ int index_;
+};
+}
+}
+} // namespace v8::internal::compiler
+
+#endif // V8_COMPILER_GENERIC_NODE_H_
#include "src/compiler.h"
#include "src/compiler/generic-graph.h"
+#include "src/compiler/generic-node.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node-properties-inl.h"
#include <string>
#include "src/compiler/generic-algorithm.h"
+#include "src/compiler/generic-node.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/node.h"
#include "src/compiler/graph.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/node.h"
#include "src/compiler/node-aux-data-inl.h"
#ifndef V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
#define V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/instruction.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/linkage.h"
#include "src/compiler/instruction.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h"
namespace v8 {
// found in the LICENSE file.
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/ast-graph-builder.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/js-inlining.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/js-intrinsic-builder.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/simplified-operator.h"
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/codegen.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-matchers.h"
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <cstring>
-
-#include "src/v8.h"
-
#include "src/compiler/node-cache.h"
+#include <cstring>
+
#include "src/zone.h"
#include "src/zone-containers.h"
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/node-matchers.h"
namespace v8 {
#include "src/v8.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "src/compiler/node.h"
+#include "src/compiler/generic-node-inl.h"
+
namespace v8 {
namespace internal {
namespace compiler {
}
-Node::Node(GenericGraphBase* graph, int input_count, int reserve_input_count)
- : input_count_(input_count),
- reserve_input_count_(reserve_input_count),
- has_appendable_inputs_(false),
- use_count_(0),
- first_use_(NULL),
- last_use_(NULL) {
- DCHECK(reserve_input_count <= kMaxReservedInputs);
- inputs_.static_ = reinterpret_cast<Input*>(this + 1);
- AssignUniqueID(graph);
-}
-
-
void Node::CollectProjections(NodeVector* projections) {
for (size_t i = 0; i < projections->size(); i++) {
(*projections)[i] = NULL;
}
-void Node::AssignUniqueID(GenericGraphBase* graph) {
- id_ = graph->NextNodeID();
-}
-
-
-Node::Inputs::iterator Node::Inputs::begin() {
- return Node::Inputs::iterator(this->node_, 0);
-}
-
-
-Node::Inputs::iterator Node::Inputs::end() {
- return Node::Inputs::iterator(this->node_, this->node_->InputCount());
-}
-
-
-Node::Uses::iterator Node::Uses::begin() {
- return Node::Uses::iterator(this->node_);
-}
-
-
-Node::Uses::iterator Node::Uses::end() { return Node::Uses::iterator(); }
-
-
-void Node::ReplaceUses(Node* replace_to) {
- for (Use* use = first_use_; use != NULL; use = use->next) {
- use->from->GetInputRecordPtr(use->input_index)->to = replace_to;
- }
- if (replace_to->last_use_ == NULL) {
- DCHECK_EQ(NULL, replace_to->first_use_);
- replace_to->first_use_ = first_use_;
- replace_to->last_use_ = last_use_;
- } else if (first_use_ != NULL) {
- DCHECK_NE(NULL, replace_to->first_use_);
- replace_to->last_use_->next = first_use_;
- first_use_->prev = replace_to->last_use_;
- replace_to->last_use_ = last_use_;
- }
- replace_to->use_count_ += use_count_;
- use_count_ = 0;
- first_use_ = NULL;
- last_use_ = NULL;
-}
-
-
-void Node::RemoveAllInputs() {
- for (Inputs::iterator iter(inputs().begin()); iter != inputs().end();
- ++iter) {
- iter.GetInput()->Update(NULL);
- }
-}
-
-
-void Node::TrimInputCount(int new_input_count) {
- if (new_input_count == input_count_) return; // Nothing to do.
-
- DCHECK(new_input_count < input_count_);
-
- // Update inline inputs.
- for (int i = new_input_count; i < input_count_; i++) {
- Node::Input* input = GetInputRecordPtr(i);
- input->Update(NULL);
- }
- input_count_ = new_input_count;
-}
-
-
-void Node::ReplaceInput(int index, Node* new_to) {
- Input* input = GetInputRecordPtr(index);
- input->Update(new_to);
-}
-
-
-void Node::Input::Update(Node* new_to) {
- Node* old_to = this->to;
- if (new_to == old_to) return; // Nothing to do.
- // Snip out the use from where it used to be
- if (old_to != NULL) {
- old_to->RemoveUse(use);
- }
- to = new_to;
- // And put it into the new node's use list.
- if (new_to != NULL) {
- new_to->AppendUse(use);
- } else {
- use->next = NULL;
- use->prev = NULL;
- }
-}
-
-
-void Node::EnsureAppendableInputs(Zone* zone) {
- if (!has_appendable_inputs_) {
- void* deque_buffer = zone->New(sizeof(InputDeque));
- InputDeque* deque = new (deque_buffer) InputDeque(zone);
- for (int i = 0; i < input_count_; ++i) {
- deque->push_back(inputs_.static_[i]);
- }
- inputs_.appendable_ = deque;
- has_appendable_inputs_ = true;
- }
-}
-
-
-void Node::AppendInput(Zone* zone, Node* to_append) {
- Use* new_use = new (zone) Use;
- Input new_input;
- new_input.to = to_append;
- new_input.use = new_use;
- if (reserve_input_count_ > 0) {
- DCHECK(!has_appendable_inputs_);
- reserve_input_count_--;
- inputs_.static_[input_count_] = new_input;
- } else {
- EnsureAppendableInputs(zone);
- inputs_.appendable_->push_back(new_input);
- }
- new_use->input_index = input_count_;
- new_use->from = this;
- to_append->AppendUse(new_use);
- input_count_++;
-}
-
-
-void Node::InsertInput(Zone* zone, int index, Node* to_insert) {
- DCHECK(index >= 0 && index < InputCount());
- // TODO(turbofan): Optimize this implementation!
- AppendInput(zone, InputAt(InputCount() - 1));
- for (int i = InputCount() - 1; i > index; --i) {
- ReplaceInput(i, InputAt(i - 1));
- }
- ReplaceInput(index, to_insert);
-}
-
-
-void Node::RemoveInput(int index) {
- DCHECK(index >= 0 && index < InputCount());
- // TODO(turbofan): Optimize this implementation!
- for (; index < InputCount() - 1; ++index) {
- ReplaceInput(index, InputAt(index + 1));
- }
- TrimInputCount(InputCount() - 1);
-}
-
-
-void Node::AppendUse(Use* use) {
- use->next = NULL;
- use->prev = last_use_;
- if (last_use_ == NULL) {
- first_use_ = use;
- } else {
- last_use_->next = use;
- }
- last_use_ = use;
- ++use_count_;
-}
-
-
-void Node::RemoveUse(Use* use) {
- if (last_use_ == use) {
- last_use_ = use->prev;
- }
- if (use->prev != NULL) {
- use->prev->next = use->next;
- } else {
- first_use_ = use->next;
- }
- if (use->next != NULL) {
- use->next->prev = use->prev;
- }
- --use_count_;
-}
-
-
-bool Node::OwnedBy(Node* owner) const {
- return first_use_ != NULL && first_use_->from == owner &&
- first_use_->next == NULL;
-}
-
-
-Node* Node::New(GenericGraphBase* graph, int input_count, Node** inputs,
- bool has_extensible_inputs) {
- size_t node_size = sizeof(Node);
- int reserve_input_count = has_extensible_inputs ? kDefaultReservedInputs : 0;
- size_t inputs_size = (input_count + reserve_input_count) * sizeof(Input);
- size_t uses_size = input_count * sizeof(Use);
- int size = static_cast<int>(node_size + inputs_size + uses_size);
- Zone* zone = graph->zone();
- void* buffer = zone->New(size);
- Node* result = new (buffer) Node(graph, input_count, reserve_input_count);
- Input* input =
- reinterpret_cast<Input*>(reinterpret_cast<char*>(buffer) + node_size);
- Use* use =
- reinterpret_cast<Use*>(reinterpret_cast<char*>(input) + inputs_size);
-
- for (int current = 0; current < input_count; ++current) {
- Node* to = *inputs++;
- input->to = to;
- input->use = use;
- use->input_index = current;
- use->from = result;
- to->AppendUse(use);
- ++use;
- ++input;
- }
- return result;
-}
-
-
-bool Node::Uses::empty() { return begin() == end(); }
-
-
std::ostream& operator<<(std::ostream& os, const Node& n) {
os << n.id() << ": " << *n.op();
if (n.op()->InputCount() != 0) {
#include <vector>
#include "src/compiler/generic-algorithm.h"
+#include "src/compiler/generic-node.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
#include "src/types.h"
#include "src/zone.h"
#include "src/zone-allocator.h"
-#include "src/zone-containers.h"
namespace v8 {
namespace internal {
namespace compiler {
-// A Node is the basic primitive of an IR graph. In addition to the graph
-// book-keeping Nodes only contain a mutable Operator that may change
-// during compilation, e.g. during lowering passes. Other information that
-// needs to be associated with Nodes during compilation must be stored
-// out-of-line indexed by the Node's id.
-class Node FINAL {
+class NodeData {
public:
- Node(GenericGraphBase* graph, int input_count, int reserve_input_count);
-
- void Initialize(const Operator* op) { set_op(op); }
-
- bool IsDead() const { return InputCount() > 0 && InputAt(0) == NULL; }
- void Kill();
-
- void CollectProjections(ZoneVector<Node*>* projections);
- Node* FindProjection(size_t projection_index);
-
const Operator* op() const { return op_; }
void set_op(const Operator* op) { op_ = op; }
return static_cast<IrOpcode::Value>(op_->opcode());
}
- inline NodeId id() const { return id_; }
-
- int InputCount() const { return input_count_; }
- Node* InputAt(int index) const {
- return static_cast<Node*>(GetInputRecordPtr(index)->to);
- }
-
- void ReplaceInput(int index, Node* new_input);
- void AppendInput(Zone* zone, Node* new_input);
- void InsertInput(Zone* zone, int index, Node* new_input);
- void RemoveInput(int index);
-
- int UseCount() { return use_count_; }
- Node* UseAt(int index) {
- DCHECK(index < use_count_);
- Use* current = first_use_;
- while (index-- != 0) {
- current = current->next;
- }
- return current->from;
- }
- void ReplaceUses(Node* replace_to);
- template <class UnaryPredicate>
- inline void ReplaceUsesIf(UnaryPredicate pred, Node* replace_to);
- void RemoveAllInputs();
-
- void TrimInputCount(int input_count);
-
- class Inputs {
- public:
- class iterator;
- iterator begin();
- iterator end();
-
- explicit Inputs(Node* node) : node_(node) {}
-
- private:
- Node* node_;
- };
-
- Inputs inputs() { return Inputs(this); }
-
- class Uses {
- public:
- class iterator;
- iterator begin();
- iterator end();
- bool empty(); // { return begin() == end(); }
-
- explicit Uses(Node* node) : node_(node) {}
-
- private:
- Node* node_;
- };
-
- Uses uses() { return Uses(this); }
-
- class Edge;
-
- bool OwnedBy(Node* owner) const;
-
- static Node* New(GenericGraphBase* graph, int input_count, Node** inputs,
- bool has_extensible_inputs);
-
-
- private:
+ protected:
const Operator* op_;
Bounds bounds_;
+ explicit NodeData(Zone* zone) {}
friend class NodeProperties;
Bounds bounds() { return bounds_; }
void set_bounds(Bounds b) { bounds_ = b; }
-
- friend class GenericGraphBase;
-
- class Use : public ZoneObject {
- public:
- Node* from;
- Use* next;
- Use* prev;
- int input_index;
- };
-
- class Input {
- public:
- Node* to;
- Use* use;
-
- void Update(Node* new_to);
- };
-
- void EnsureAppendableInputs(Zone* zone);
-
- Input* GetInputRecordPtr(int index) const {
- if (has_appendable_inputs_) {
- return &((*inputs_.appendable_)[index]);
- } else {
- return inputs_.static_ + index;
- }
- }
-
- void AppendUse(Use* use);
- void RemoveUse(Use* use);
-
- void* operator new(size_t, void* location) { return location; }
-
- void AssignUniqueID(GenericGraphBase* graph);
-
- typedef ZoneDeque<Input> InputDeque;
-
- static const int kReservedInputCountBits = 2;
- static const int kMaxReservedInputs = (1 << kReservedInputCountBits) - 1;
- static const int kDefaultReservedInputs = kMaxReservedInputs;
-
- NodeId id_;
- int input_count_ : 29;
- unsigned int reserve_input_count_ : kReservedInputCountBits;
- bool has_appendable_inputs_ : 1;
- union {
- // When a node is initially allocated, it uses a static buffer to hold its
- // inputs under the assumption that the number of outputs will not increase.
- // When the first input is appended, the static buffer is converted into a
- // deque to allow for space-efficient growing.
- Input* static_;
- InputDeque* appendable_;
- } inputs_;
- int use_count_;
- Use* first_use_;
- Use* last_use_;
-
- DISALLOW_COPY_AND_ASSIGN(Node);
-};
-
-class Node::Edge {
- public:
- Node* from() const { return input_->use->from; }
- Node* to() const { return input_->to; }
- int index() const {
- int index = input_->use->input_index;
- DCHECK(index < input_->use->from->input_count_);
- return index;
- }
-
- private:
- friend class Node::Uses::iterator;
- friend class Node::Inputs::iterator;
-
- explicit Edge(Node::Input* input) : input_(input) {}
-
- Node::Input* input_;
};
-
-// A forward iterator to visit the nodes which are depended upon by a node
-// in the order of input.
-class Node::Inputs::iterator {
- public:
- iterator(const Node::Inputs::iterator& other) // NOLINT
- : node_(other.node_),
- index_(other.index_) {}
-
- Node* operator*() { return GetInput()->to; }
- Node::Edge edge() { return Node::Edge(GetInput()); }
- bool operator==(const iterator& other) const {
- return other.index_ == index_ && other.node_ == node_;
- }
- bool operator!=(const iterator& other) const { return !(other == *this); }
- iterator& operator++() {
- DCHECK(node_ != NULL);
- DCHECK(index_ < node_->input_count_);
- ++index_;
- return *this;
- }
- iterator& UpdateToAndIncrement(Node* new_to) {
- Node::Input* input = GetInput();
- input->Update(new_to);
- index_++;
- return *this;
- }
- int index() { return index_; }
-
- private:
- friend class Node;
-
- explicit iterator(Node* node, int index) : node_(node), index_(index) {}
-
- Input* GetInput() const { return node_->GetInputRecordPtr(index_); }
-
- Node* node_;
- int index_;
-};
-
-// A forward iterator to visit the uses of a node. The uses are returned in
-// the order in which they were added as inputs.
-class Node::Uses::iterator {
+// A Node is the basic primitive of an IR graph. In addition to the members
+// inherited from Vector, Nodes only contain a mutable Operator that may change
+// during compilation, e.g. during lowering passes. Other information that
+// needs to be associated with Nodes during compilation must be stored
+// out-of-line indexed by the Node's id.
+class Node FINAL : public GenericNode<NodeData, Node> {
public:
- iterator(const Node::Uses::iterator& other) // NOLINT
- : current_(other.current_),
- index_(other.index_) {}
-
- Node* operator*() { return current_->from; }
- Node::Edge edge() { return Node::Edge(CurrentInput()); }
-
- bool operator==(const iterator& other) { return other.current_ == current_; }
- bool operator!=(const iterator& other) { return other.current_ != current_; }
- iterator& operator++() {
- DCHECK(current_ != NULL);
- index_++;
- current_ = current_->next;
- return *this;
- }
- iterator& UpdateToAndIncrement(Node* new_to) {
- DCHECK(current_ != NULL);
- index_++;
- Node::Input* input = CurrentInput();
- current_ = current_->next;
- input->Update(new_to);
- return *this;
- }
- int index() const { return index_; }
-
- private:
- friend class Node::Uses;
+ Node(GenericGraphBase* graph, int input_count, int reserve_input_count)
+ : GenericNode<NodeData, Node>(graph, input_count, reserve_input_count) {}
- iterator() : current_(NULL), index_(0) {}
- explicit iterator(Node* node) : current_(node->first_use_), index_(0) {}
+ void Initialize(const Operator* op) { set_op(op); }
- Input* CurrentInput() const {
- return current_->from->GetInputRecordPtr(current_->input_index);
- }
+ bool IsDead() const { return InputCount() > 0 && InputAt(0) == NULL; }
+ void Kill();
- Node::Use* current_;
- int index_;
+ void CollectProjections(ZoneVector<Node*>* projections);
+ Node* FindProjection(size_t projection_index);
};
-
-template <class UnaryPredicate>
-inline void Node::ReplaceUsesIf(UnaryPredicate pred, Node* replace_to) {
- for (Use* use = first_use_; use != NULL;) {
- Use* next = use->next;
- if (pred(use->from)) {
- RemoveUse(use);
- replace_to->AppendUse(use);
- use->from->GetInputRecordPtr(use->input_index)->to = replace_to;
- }
- use = next;
- }
-}
-
std::ostream& operator<<(std::ostream& os, const Node& n);
-typedef GenericGraphVisit::NullNodeVisitor<Node> NullNodeVisitor;
+typedef GenericGraphVisit::NullNodeVisitor<NodeData, Node> NullNodeVisitor;
typedef std::set<Node*, std::less<Node*>, zone_allocator<Node*> > NodeSet;
typedef NodeSet::iterator NodeSetIter;
#ifndef V8_COMPILER_PHI_REDUCER_H_
#define V8_COMPILER_PHI_REDUCER_H_
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph-reducer.h"
namespace v8 {
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-matchers.h"
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <cstring>
-
-#include "src/v8.h"
-
#include "src/compiler/value-numbering-reducer.h"
+#include <cstring>
+
#include "src/base/functional.h"
#include "src/compiler/node.h"
#include <string>
#include "src/compiler/generic-algorithm.h"
+#include "src/compiler/generic-node-inl.h"
+#include "src/compiler/generic-node.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/graph.h"
#include "src/compiler/node.h"
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/instruction-selector-impl.h"
#include "src/compiler/node-matchers.h"
#include "src/v8.h"
+#include "src/compiler/generic-node-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
#include "test/cctest/compiler/value-helper.h"
#include "src/v8.h"
#include "src/basic-block-profiler.h"
+#include "src/compiler/generic-node-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
#include "src/v8.h"
+#include "src/compiler/generic-node-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
#include "test/cctest/compiler/value-helper.h"
#include "src/compiler/change-lowering.h"
#include "src/compiler/control-builders.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties-inl.h"
#include "src/compiler/pipeline.h"
#include "src/v8.h"
#include "graph-tester.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph-reducer.h"
using namespace v8::internal;
#include "src/zone.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/machine-operator.h"
#include "graph-tester.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/graph-visualizer.h"
#include "src/v8.h"
#include "graph-tester.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include <limits>
#include "src/base/bits.h"
+#include "src/compiler/generic-node-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
#include "test/cctest/compiler/value-helper.h"
#include "src/v8.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
+#include "src/compiler/generic-node.h"
#include "src/compiler/graph.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/change-lowering.h"
#include "src/compiler/control-builders.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/node-properties-inl.h"
'../../src/compiler/generic-algorithm-inl.h',
'../../src/compiler/generic-algorithm.h',
'../../src/compiler/generic-graph.h',
+ '../../src/compiler/generic-node-inl.h',
+ '../../src/compiler/generic-node.h',
'../../src/compiler/graph-builder.cc',
'../../src/compiler/graph-builder.h',
'../../src/compiler/graph-inl.h',