De-generify the GenericNode.

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/756073004

Cr-Commit-Position: refs/heads/master@{#25572}
This commit is contained in:
mstarzinger 2014-11-28 07:21:33 -08:00 committed by Commit bot
parent cec0acad38
commit 70093d719c
36 changed files with 473 additions and 605 deletions

View File

@ -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",

View File

@ -8,9 +8,8 @@
#include <vector>
#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 {

View File

@ -7,13 +7,15 @@
#include <stack>
#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<Visitor, Traits>(graph, zone, &array[0], &array[1], visitor);
}
template <class B, class S>
struct NullNodeVisitor {
void Pre(GenericNode<B, S>* node) {}
void Post(GenericNode<B, S>* node) {}
void PreEdge(GenericNode<B, S>* from, int index, GenericNode<B, S>* to) {}
void PostEdge(GenericNode<B, S>* from, int index, GenericNode<B, S>* 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:

View File

@ -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 <class B, class S>
GenericNode<B, S>::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<Input*>(this + 1);
AssignUniqueID(graph);
}
template <class B, class S>
inline void GenericNode<B, S>::AssignUniqueID(Graph* 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(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<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_

View File

@ -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<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(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<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_

View File

@ -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"

View File

@ -8,8 +8,6 @@
#include <string>
#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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -7,8 +7,6 @@
#include <cmath>
#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"

View File

@ -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"

View File

@ -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<Input*>(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<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;
}
void Node::Kill() {
DCHECK_NOT_NULL(op());
RemoveAllInputs();

View File

@ -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

View File

@ -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 {

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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;

View File

@ -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"

View File

@ -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"

View File

@ -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;

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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',