Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Unified Diff: src/compiler/node.h

Issue 756073004: De-generify the GenericNode. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix compilation on Windows. Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/machine-operator-reducer.cc ('k') | src/compiler/node.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/node.h
diff --git a/src/compiler/node.h b/src/compiler/node.h
index 1731f866b51597a0b1c576d5f0c2eb5f156ad6e2..1df1fb66312ec038245c0ef206dd411d91a1d048 100644
--- a/src/compiler/node.h
+++ b/src/compiler/node.h
@@ -9,18 +9,22 @@
#include <set>
#include <vector>
+#include "src/v8.h"
+
#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 {
+class Graph;
+
// Marks are used during traversal of the graph to distinguish states of nodes.
// Each node has a mark which is a monotonically increasing integer, and a
// {NodeMarker} has a range of values that indicate states of a node.
@@ -54,16 +58,19 @@ class NodeData {
void set_mark(Mark mark) { mark_ = mark; }
};
-// 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:
- Node(Graph* graph, int input_count, int reserve_input_count)
- : GenericNode<NodeData, Node>(graph, input_count, reserve_input_count) {}
+typedef int NodeId;
+// A Node is the basic primitive of graphs. Nodes 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.
+//
+// In addition 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 NodeData {
+ public:
void Initialize(const Operator* op) {
set_op(op);
set_mark(0);
@@ -74,11 +81,237 @@ class Node FINAL : public GenericNode<NodeData, Node> {
void CollectProjections(ZoneVector<Node*>* projections);
Node* FindProjection(size_t projection_index);
+
+ inline NodeId id() const { return id_; }
+
+ int InputCount() const { return input_count_; }
+ Node* InputAt(int index) const { return GetInputRecordPtr(index)->to; }
+ inline void ReplaceInput(int index, Node* new_input);
+ inline void AppendInput(Zone* zone, Node* new_input);
+ inline void InsertInput(Zone* zone, int index, Node* new_input);
+ inline 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;
+ }
+ inline void ReplaceUses(Node* replace_to);
+ template <class UnaryPredicate>
+ inline void ReplaceUsesIf(UnaryPredicate pred, Node* replace_to);
+ inline void RemoveAllInputs();
+
+ inline 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();
+
+ explicit Uses(Node* node) : node_(node) {}
+
+ private:
+ Node* node_;
+ };
+
+ Uses uses() { return Uses(this); }
+
+ class Edge;
+
+ bool OwnedBy(Node* owner) const;
+
+ static Node* New(Graph* graph, int input_count, Node** inputs,
+ bool has_extensible_inputs);
+
+ protected:
+ friend class Graph;
+
+ 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;
+ }
+ }
+
+ inline void AppendUse(Use* use);
+ inline void RemoveUse(Use* use);
+
+ void* operator new(size_t, void* location) { return location; }
+
+ private:
+ Node(Graph* graph, int input_count, int reserve_input_count);
+
+ 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);
+};
+
+// 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.
+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 {
+ 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;
+
+ iterator() : current_(NULL), index_(0) {}
+ explicit iterator(Node* node) : current_(node->first_use_), index_(0) {}
+
+ Input* CurrentInput() const {
+ return current_->from->GetInputRecordPtr(current_->input_index);
+ }
+
+ Node::Use* current_;
+ int index_;
};
std::ostream& operator<<(std::ostream& os, const Node& n);
-typedef GenericGraphVisit::NullNodeVisitor<NodeData, Node> NullNodeVisitor;
+typedef GenericGraphVisit::NullNodeVisitor NullNodeVisitor;
typedef std::set<Node*, std::less<Node*>, zone_allocator<Node*> > NodeSet;
typedef NodeSet::iterator NodeSetIter;
@@ -104,6 +337,179 @@ static inline const T& OpParameter(const Node* node) {
return OpParameter<T>(node->op());
}
+inline Node::Inputs::iterator Node::Inputs::begin() {
+ return Node::Inputs::iterator(this->node_, 0);
+}
+
+inline Node::Inputs::iterator Node::Inputs::end() {
+ return Node::Inputs::iterator(this->node_, this->node_->InputCount());
+}
+
+inline Node::Uses::iterator Node::Uses::begin() {
+ return Node::Uses::iterator(this->node_);
+}
+
+inline Node::Uses::iterator Node::Uses::end() { return Node::Uses::iterator(); }
+
+inline bool Node::Uses::empty() { return begin() == end(); }
+
+inline 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;
+}
+
+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;
+ }
+}
+
+inline void Node::RemoveAllInputs() {
+ for (Inputs::iterator iter(inputs().begin()); iter != inputs().end();
+ ++iter) {
+ iter.GetInput()->Update(NULL);
+ }
+}
+
+inline 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;
+}
+
+inline void Node::ReplaceInput(int index, Node* new_to) {
+ Input* input = GetInputRecordPtr(index);
+ input->Update(new_to);
+}
+
+inline 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;
+ }
+}
+
+inline 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;
+ }
+}
+
+inline 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_++;
+}
+
+inline 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);
+}
+
+inline 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);
+}
+
+inline 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_;
+}
+
+inline 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_;
+}
+
+inline bool Node::OwnedBy(Node* owner) const {
+ return first_use_ != NULL && first_use_->from == owner &&
+ first_use_->next == NULL;
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
« no previous file with comments | « src/compiler/machine-operator-reducer.cc ('k') | src/compiler/node.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698