diff --git a/BUILD.gn b/BUILD.gn index 8f36fec4fa..31aa95fc6f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -499,8 +499,6 @@ source_set("v8_base") { "src/compiler/gap-resolver.h", "src/compiler/generic-algorithm-inl.h", "src/compiler/generic-algorithm.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", diff --git a/src/compiler/generic-algorithm-inl.h b/src/compiler/generic-algorithm-inl.h index 120a716324..02292969d6 100644 --- a/src/compiler/generic-algorithm-inl.h +++ b/src/compiler/generic-algorithm-inl.h @@ -8,9 +8,8 @@ #include #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/node.h" namespace v8 { namespace internal { diff --git a/src/compiler/generic-algorithm.h b/src/compiler/generic-algorithm.h index 841cdd15b4..a755d24860 100644 --- a/src/compiler/generic-algorithm.h +++ b/src/compiler/generic-algorithm.h @@ -7,13 +7,15 @@ #include -#include "src/compiler/generic-node.h" #include "src/zone-containers.h" namespace v8 { namespace internal { namespace compiler { +class Graph; +class Node; + // GenericGraphVisit allows visitation of graphs of nodes and edges in pre- and // post-order. Visitation uses an explicitly allocated stack rather than the // execution stack to avoid stack overflow. Although GenericGraphVisit is @@ -88,12 +90,11 @@ class GenericGraphVisit { Visit(graph, zone, &array[0], &array[1], visitor); } - template struct NullNodeVisitor { - void Pre(GenericNode* node) {} - void Post(GenericNode* node) {} - void PreEdge(GenericNode* from, int index, GenericNode* to) {} - void PostEdge(GenericNode* from, int index, GenericNode* to) {} + void Pre(Node* node) {} + void Post(Node* node) {} + void PreEdge(Node* from, int index, Node* to) {} + void PostEdge(Node* from, int index, Node* to) {} }; private: diff --git a/src/compiler/generic-node-inl.h b/src/compiler/generic-node-inl.h deleted file mode 100644 index 97978b8ad1..0000000000 --- a/src/compiler/generic-node-inl.h +++ /dev/null @@ -1,267 +0,0 @@ -// 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-node.h" -#include "src/compiler/graph.h" -#include "src/zone.h" - -namespace v8 { -namespace internal { -namespace compiler { - -template -GenericNode::GenericNode(Graph* 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(this + 1); - AssignUniqueID(graph); -} - -template -inline void GenericNode::AssignUniqueID(Graph* graph) { - id_ = graph->NextNodeID(); -} - -template -inline typename GenericNode::Inputs::iterator -GenericNode::Inputs::begin() { - return typename GenericNode::Inputs::iterator(this->node_, 0); -} - -template -inline typename GenericNode::Inputs::iterator -GenericNode::Inputs::end() { - return typename GenericNode::Inputs::iterator( - this->node_, this->node_->InputCount()); -} - -template -inline typename GenericNode::Uses::iterator -GenericNode::Uses::begin() { - return typename GenericNode::Uses::iterator(this->node_); -} - -template -inline typename GenericNode::Uses::iterator -GenericNode::Uses::end() { - return typename GenericNode::Uses::iterator(); -} - -template -void GenericNode::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 -template -void GenericNode::ReplaceUsesIf(UnaryPredicate pred, - GenericNode* replace_to) { - for (Use* use = first_use_; use != NULL;) { - Use* next = use->next; - if (pred(static_cast(use->from))) { - RemoveUse(use); - replace_to->AppendUse(use); - use->from->GetInputRecordPtr(use->input_index)->to = replace_to; - } - use = next; - } -} - -template -void GenericNode::RemoveAllInputs() { - for (typename Inputs::iterator iter(inputs().begin()); iter != inputs().end(); - ++iter) { - iter.GetInput()->Update(NULL); - } -} - -template -void GenericNode::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::Input* input = GetInputRecordPtr(i); - input->Update(NULL); - } - input_count_ = new_input_count; -} - -template -void GenericNode::ReplaceInput(int index, GenericNode* new_to) { - Input* input = GetInputRecordPtr(index); - input->Update(new_to); -} - -template -void GenericNode::Input::Update(GenericNode* 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 -void GenericNode::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 -void GenericNode::AppendInput(Zone* zone, GenericNode* 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 -void GenericNode::InsertInput(Zone* zone, int index, - GenericNode* 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 -void GenericNode::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 -void GenericNode::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 -void GenericNode::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 -inline bool GenericNode::OwnedBy(GenericNode* owner) const { - return first_use_ != NULL && first_use_->from == owner && - first_use_->next == NULL; -} - -template -S* GenericNode::New(Graph* 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(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(reinterpret_cast(buffer) + node_size); - Use* use = - reinterpret_cast(reinterpret_cast(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_ diff --git a/src/compiler/generic-node.h b/src/compiler/generic-node.h deleted file mode 100644 index b52492bc63..0000000000 --- a/src/compiler/generic-node.h +++ /dev/null @@ -1,278 +0,0 @@ -// 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 Graph; - -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 type. -template -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(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(current->from); - } - inline void ReplaceUses(GenericNode* replace_to); - template - 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(Graph* graph, int input_count, S** inputs, - bool has_extensible_inputs); - - protected: - friend class Graph; - - 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(Graph* graph, int input_count, int reserved_input_count); - - private: - void AssignUniqueID(Graph* graph); - - typedef ZoneDeque 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 GenericNode::Edge { - public: - S* from() const { return static_cast(input_->use->from); } - S* to() const { return static_cast(input_->to); } - int index() const { - int index = input_->use->input_index; - DCHECK(index < input_->use->from->input_count_); - return index; - } - - private: - friend class GenericNode::Uses::iterator; - friend class GenericNode::Inputs::iterator; - - explicit Edge(typename GenericNode::Input* input) : input_(input) {} - - typename GenericNode::Input* input_; -}; - -// A forward iterator to visit the nodes which are depended upon by a node -// in the order of input. -template -class GenericNode::Inputs::iterator { - public: - iterator(const typename GenericNode::Inputs::iterator& other) // NOLINT - : node_(other.node_), - index_(other.index_) {} - - S* operator*() { return static_cast(GetInput()->to); } - typename GenericNode::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* new_to) { - typename GenericNode::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 GenericNode::Uses::iterator { - public: - iterator(const typename GenericNode::Uses::iterator& other) // NOLINT - : current_(other.current_), - index_(other.index_) {} - - S* operator*() { return static_cast(current_->from); } - typename GenericNode::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* new_to) { - DCHECK(current_ != NULL); - index_++; - typename GenericNode::Input* input = CurrentInput(); - current_ = current_->next; - input->Update(new_to); - return *this; - } - int index() const { return index_; } - - private: - friend class GenericNode::Uses; - - iterator() : current_(NULL), index_(0) {} - explicit iterator(GenericNode* node) - : current_(node->first_use_), index_(0) {} - - Input* CurrentInput() const { - return current_->from->GetInputRecordPtr(current_->input_index); - } - - typename GenericNode::Use* current_; - int index_; -}; -} -} -} // namespace v8::internal::compiler - -#endif // V8_COMPILER_GENERIC_NODE_H_ diff --git a/src/compiler/graph-builder.cc b/src/compiler/graph-builder.cc index 6802f888dd..0e460aa413 100644 --- a/src/compiler/graph-builder.cc +++ b/src/compiler/graph-builder.cc @@ -5,9 +5,8 @@ #include "src/compiler/graph-builder.h" #include "src/compiler.h" -#include "src/compiler/generic-node.h" -#include "src/compiler/generic-node-inl.h" #include "src/compiler/graph-visualizer.h" +#include "src/compiler/node.h" #include "src/compiler/node-properties.h" #include "src/compiler/node-properties-inl.h" #include "src/compiler/operator-properties.h" diff --git a/src/compiler/graph-visualizer.cc b/src/compiler/graph-visualizer.cc index 032bc9fac0..c23672e0a1 100644 --- a/src/compiler/graph-visualizer.cc +++ b/src/compiler/graph-visualizer.cc @@ -8,8 +8,6 @@ #include #include "src/code-stubs.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" diff --git a/src/compiler/graph.cc b/src/compiler/graph.cc index 6533d57ffe..619a8deb75 100644 --- a/src/compiler/graph.cc +++ b/src/compiler/graph.cc @@ -5,7 +5,6 @@ #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" diff --git a/src/compiler/instruction-selector-impl.h b/src/compiler/instruction-selector-impl.h index 7813e9b6b9..d1e27f0466 100644 --- a/src/compiler/instruction-selector-impl.h +++ b/src/compiler/instruction-selector-impl.h @@ -5,7 +5,6 @@ #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" diff --git a/src/compiler/instruction.cc b/src/compiler/instruction.cc index 3afc970e99..6cab71f16b 100644 --- a/src/compiler/instruction.cc +++ b/src/compiler/instruction.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "src/compiler/common-operator.h" -#include "src/compiler/generic-node-inl.h" #include "src/compiler/graph.h" #include "src/compiler/instruction.h" diff --git a/src/compiler/js-context-specialization.cc b/src/compiler/js-context-specialization.cc index 8c4bb17f19..d11bc66711 100644 --- a/src/compiler/js-context-specialization.cc +++ b/src/compiler/js-context-specialization.cc @@ -3,7 +3,6 @@ // 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" diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc index 8646317948..ec6ab90584 100644 --- a/src/compiler/js-inlining.cc +++ b/src/compiler/js-inlining.cc @@ -7,7 +7,6 @@ #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" diff --git a/src/compiler/js-intrinsic-builder.cc b/src/compiler/js-intrinsic-builder.cc index d4c0dcf5ce..80b69682ca 100644 --- a/src/compiler/js-intrinsic-builder.cc +++ b/src/compiler/js-intrinsic-builder.cc @@ -5,7 +5,6 @@ #include "src/compiler/access-builder.h" #include "src/compiler/common-operator.h" #include "src/compiler/diamond.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" diff --git a/src/compiler/machine-operator-reducer.cc b/src/compiler/machine-operator-reducer.cc index 652b26910e..fe579689bf 100644 --- a/src/compiler/machine-operator-reducer.cc +++ b/src/compiler/machine-operator-reducer.cc @@ -8,7 +8,6 @@ #include "src/base/division-by-constant.h" #include "src/codegen.h" #include "src/compiler/diamond.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" diff --git a/src/compiler/node-matchers.h b/src/compiler/node-matchers.h index e0db825a76..6636794b37 100644 --- a/src/compiler/node-matchers.h +++ b/src/compiler/node-matchers.h @@ -7,8 +7,6 @@ #include -#include "src/compiler/generic-node.h" -#include "src/compiler/generic-node-inl.h" #include "src/compiler/node.h" #include "src/compiler/operator.h" #include "src/unique.h" diff --git a/src/compiler/node-properties-inl.h b/src/compiler/node-properties-inl.h index 541c302e70..a0319e7b9b 100644 --- a/src/compiler/node-properties-inl.h +++ b/src/compiler/node-properties-inl.h @@ -8,7 +8,6 @@ #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" diff --git a/src/compiler/node.cc b/src/compiler/node.cc index 673ef3290e..be63517787 100644 --- a/src/compiler/node.cc +++ b/src/compiler/node.cc @@ -3,13 +3,56 @@ // found in the LICENSE file. #include "src/compiler/node.h" - -#include "src/compiler/generic-node-inl.h" +#include "src/compiler/graph.h" +#include "src/zone.h" namespace v8 { namespace internal { namespace compiler { +Node::Node(Graph* graph, int input_count, int reserve_input_count) + : NodeData(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(this + 1); + id_ = graph->NextNodeID(); +} + + +Node* Node::New(Graph* 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(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(reinterpret_cast(buffer) + node_size); + Use* use = + reinterpret_cast(reinterpret_cast(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; +} + + void Node::Kill() { DCHECK_NOT_NULL(op()); RemoveAllInputs(); diff --git a/src/compiler/node.h b/src/compiler/node.h index 1731f866b5..1df1fb6631 100644 --- a/src/compiler/node.h +++ b/src/compiler/node.h @@ -9,18 +9,22 @@ #include #include +#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 { - public: - Node(Graph* graph, int input_count, int reserve_input_count) - : GenericNode(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 { void CollectProjections(ZoneVector* 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 + 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 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 NullNodeVisitor; +typedef GenericGraphVisit::NullNodeVisitor NullNodeVisitor; typedef std::set, zone_allocator > NodeSet; typedef NodeSet::iterator NodeSetIter; @@ -104,6 +337,179 @@ static inline const T& OpParameter(const Node* node) { return OpParameter(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 +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 diff --git a/src/compiler/select-lowering.cc b/src/compiler/select-lowering.cc index cb2b04245e..edecf58fb8 100644 --- a/src/compiler/select-lowering.cc +++ b/src/compiler/select-lowering.cc @@ -6,8 +6,8 @@ #include "src/compiler/common-operator.h" #include "src/compiler/diamond.h" -#include "src/compiler/generic-node-inl.h" #include "src/compiler/graph.h" +#include "src/compiler/node.h" namespace v8 { namespace internal { diff --git a/src/compiler/simplified-operator-reducer.cc b/src/compiler/simplified-operator-reducer.cc index a1a6a02bc8..afc08858d7 100644 --- a/src/compiler/simplified-operator-reducer.cc +++ b/src/compiler/simplified-operator-reducer.cc @@ -2,7 +2,6 @@ // 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" diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index b30b72786b..b739fe39ab 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -11,8 +11,6 @@ #include "src/bit-vector.h" #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" diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc index 7882253b21..14c8f4db14 100644 --- a/src/compiler/x64/instruction-selector-x64.cc +++ b/src/compiler/x64/instruction-selector-x64.cc @@ -2,7 +2,6 @@ // 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" diff --git a/test/cctest/compiler/codegen-tester.cc b/test/cctest/compiler/codegen-tester.cc index 51970ccbcf..5311001714 100644 --- a/test/cctest/compiler/codegen-tester.cc +++ b/test/cctest/compiler/codegen-tester.cc @@ -4,7 +4,6 @@ #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" diff --git a/test/cctest/compiler/test-basic-block-profiler.cc b/test/cctest/compiler/test-basic-block-profiler.cc index dd96499a35..703fc176ad 100644 --- a/test/cctest/compiler/test-basic-block-profiler.cc +++ b/test/cctest/compiler/test-basic-block-profiler.cc @@ -5,7 +5,6 @@ #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" diff --git a/test/cctest/compiler/test-branch-combine.cc b/test/cctest/compiler/test-branch-combine.cc index 52590c0453..cd3472d6bb 100644 --- a/test/cctest/compiler/test-branch-combine.cc +++ b/test/cctest/compiler/test-branch-combine.cc @@ -4,7 +4,6 @@ #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" diff --git a/test/cctest/compiler/test-changes-lowering.cc b/test/cctest/compiler/test-changes-lowering.cc index d6b639e855..5795754c45 100644 --- a/test/cctest/compiler/test-changes-lowering.cc +++ b/test/cctest/compiler/test-changes-lowering.cc @@ -6,7 +6,6 @@ #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" diff --git a/test/cctest/compiler/test-graph-reducer.cc b/test/cctest/compiler/test-graph-reducer.cc index 576fee29e9..70b57b9da9 100644 --- a/test/cctest/compiler/test-graph-reducer.cc +++ b/test/cctest/compiler/test-graph-reducer.cc @@ -5,7 +5,6 @@ #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; diff --git a/test/cctest/compiler/test-graph-visualizer.cc b/test/cctest/compiler/test-graph-visualizer.cc index 9d394bbbf6..ce3e6b71e9 100644 --- a/test/cctest/compiler/test-graph-visualizer.cc +++ b/test/cctest/compiler/test-graph-visualizer.cc @@ -6,8 +6,6 @@ #include "test/cctest/cctest.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" diff --git a/test/cctest/compiler/test-linkage.cc b/test/cctest/compiler/test-linkage.cc index 2f454eaedb..117caf22d8 100644 --- a/test/cctest/compiler/test-linkage.cc +++ b/test/cctest/compiler/test-linkage.cc @@ -8,7 +8,6 @@ #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" diff --git a/test/cctest/compiler/test-node-algorithm.cc b/test/cctest/compiler/test-node-algorithm.cc index 1dea8b46d7..842d18272e 100644 --- a/test/cctest/compiler/test-node-algorithm.cc +++ b/test/cctest/compiler/test-node-algorithm.cc @@ -8,11 +8,10 @@ #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/compiler/node.h" #include "src/compiler/operator.h" using namespace v8::internal; diff --git a/test/cctest/compiler/test-node.cc b/test/cctest/compiler/test-node.cc index 5ac2e4a683..36a9b4994e 100644 --- a/test/cctest/compiler/test-node.cc +++ b/test/cctest/compiler/test-node.cc @@ -7,7 +7,6 @@ #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" diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc index fb2fabbbd5..974d4cef54 100644 --- a/test/cctest/compiler/test-run-machops.cc +++ b/test/cctest/compiler/test-run-machops.cc @@ -8,7 +8,6 @@ #include "src/base/bits.h" #include "src/codegen.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" diff --git a/test/cctest/compiler/test-schedule.cc b/test/cctest/compiler/test-schedule.cc index d2a52c7627..1eb3547187 100644 --- a/test/cctest/compiler/test-schedule.cc +++ b/test/cctest/compiler/test-schedule.cc @@ -5,7 +5,6 @@ #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" diff --git a/test/cctest/compiler/test-scheduler.cc b/test/cctest/compiler/test-scheduler.cc index 0b7cdab996..06e22db662 100644 --- a/test/cctest/compiler/test-scheduler.cc +++ b/test/cctest/compiler/test-scheduler.cc @@ -6,8 +6,6 @@ #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" diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc index a878317287..32da19b84f 100644 --- a/test/cctest/compiler/test-simplified-lowering.cc +++ b/test/cctest/compiler/test-simplified-lowering.cc @@ -7,7 +7,6 @@ #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" diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 365695f8aa..4a6a397221 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -431,8 +431,6 @@ '../../src/compiler/gap-resolver.h', '../../src/compiler/generic-algorithm-inl.h', '../../src/compiler/generic-algorithm.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',