Index: src/compiler/node.cc |
diff --git a/src/compiler/node.cc b/src/compiler/node.cc |
index b86b0bde51366b5fb2bb3a77ba38e81eecf9ab0c..1486d8a34d2655b3a6367810139d77bac6cbf67a 100644 |
--- a/src/compiler/node.cc |
+++ b/src/compiler/node.cc |
@@ -4,24 +4,12 @@ |
#include "src/compiler/node.h" |
+#include <algorithm> |
+ |
namespace v8 { |
namespace internal { |
namespace compiler { |
-Node::Node(NodeId id, const Operator* op, int input_count, |
- int reserved_input_count) |
- : op_(op), |
- mark_(0), |
- id_(id), |
- bit_field_(InputCountField::encode(input_count) | |
- ReservedInputCountField::encode(reserved_input_count) | |
- HasAppendableInputsField::encode(false)), |
- first_use_(nullptr), |
- last_use_(nullptr) { |
- inputs_.static_ = reinterpret_cast<Input*>(this + 1); |
-} |
- |
- |
Node* Node::New(Zone* zone, NodeId id, const Operator* op, int input_count, |
Node** inputs, bool has_extensible_inputs) { |
size_t node_size = sizeof(Node); |
@@ -57,28 +45,67 @@ void Node::Kill() { |
} |
-void Node::CollectProjections(NodeVector* projections) { |
- for (size_t i = 0; i < projections->size(); i++) { |
- (*projections)[i] = NULL; |
+void Node::AppendInput(Zone* zone, Node* new_to) { |
+ DCHECK_NOT_NULL(zone); |
+ DCHECK_NOT_NULL(new_to); |
+ Use* new_use = new (zone) Use; |
+ Input new_input; |
+ new_input.to = new_to; |
+ new_input.use = new_use; |
+ if (reserved_input_count() > 0) { |
+ DCHECK(!has_appendable_inputs()); |
+ set_reserved_input_count(reserved_input_count() - 1); |
+ inputs_.static_[input_count()] = new_input; |
+ } else { |
+ EnsureAppendableInputs(zone); |
+ inputs_.appendable_->push_back(new_input); |
} |
- for (UseIter i = uses().begin(); i != uses().end(); ++i) { |
- if ((*i)->opcode() != IrOpcode::kProjection) continue; |
- size_t index = OpParameter<size_t>(*i); |
- DCHECK_LT(index, projections->size()); |
- DCHECK_EQ(NULL, (*projections)[index]); |
- (*projections)[index] = *i; |
+ new_use->input_index = input_count(); |
+ new_use->from = this; |
+ new_to->AppendUse(new_use); |
+ set_input_count(input_count() + 1); |
+} |
+ |
+ |
+void Node::InsertInput(Zone* zone, int index, Node* new_to) { |
+ DCHECK_NOT_NULL(zone); |
+ DCHECK_LE(0, index); |
+ DCHECK_LT(index, InputCount()); |
+ AppendInput(zone, InputAt(InputCount() - 1)); |
+ for (int i = InputCount() - 1; i > index; --i) { |
+ ReplaceInput(i, InputAt(i - 1)); |
} |
+ ReplaceInput(index, new_to); |
} |
-Node* Node::FindProjection(size_t projection_index) { |
- for (UseIter i = uses().begin(); i != uses().end(); ++i) { |
- if ((*i)->opcode() == IrOpcode::kProjection && |
- OpParameter<size_t>(*i) == projection_index) { |
- return *i; |
- } |
+void Node::RemoveInput(int index) { |
+ DCHECK_LE(0, index); |
+ DCHECK_LT(index, InputCount()); |
+ for (; index < InputCount() - 1; ++index) { |
+ ReplaceInput(index, InputAt(index + 1)); |
+ } |
+ TrimInputCount(InputCount() - 1); |
+} |
+ |
+ |
+void Node::RemoveAllInputs() { |
+ for (Edge edge : input_edges()) edge.UpdateTo(nullptr); |
+} |
+ |
+ |
+void Node::TrimInputCount(int new_input_count) { |
+ DCHECK_LE(new_input_count, input_count()); |
+ if (new_input_count == input_count()) return; // Nothing to do. |
+ for (int index = new_input_count; index < input_count(); ++index) { |
+ ReplaceInput(index, nullptr); |
+ } |
+ if (!has_appendable_inputs()) { |
+ set_reserved_input_count(std::min<int>( |
+ ReservedInputCountField::kMax, |
+ reserved_input_count() + (input_count() - new_input_count))); |
} |
- return NULL; |
+ set_input_count(new_input_count); |
} |
@@ -94,11 +121,102 @@ int Node::UseCount() const { |
Node* Node::UseAt(int index) const { |
DCHECK_LE(0, index); |
DCHECK_LT(index, UseCount()); |
- Use* current = first_use_; |
+ const Use* use = first_use_; |
while (index-- != 0) { |
- current = current->next; |
+ use = use->next; |
+ } |
+ return use->from; |
+} |
+ |
+ |
+void Node::ReplaceUses(Node* replace_to) { |
+ for (Use* use = first_use_; use; use = use->next) { |
+ use->from->GetInputRecordPtr(use->input_index)->to = replace_to; |
+ } |
+ if (!replace_to->last_use_) { |
+ DCHECK_EQ(nullptr, replace_to->first_use_); |
+ replace_to->first_use_ = first_use_; |
+ replace_to->last_use_ = last_use_; |
+ } else if (first_use_) { |
+ DCHECK_NOT_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_; |
+ } |
+ first_use_ = nullptr; |
+ last_use_ = nullptr; |
+} |
+ |
+ |
+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) { |
+ old_to->RemoveUse(use); |
+ } |
+ to = new_to; |
+ // And put it into the new node's use list. |
+ if (new_to) { |
+ new_to->AppendUse(use); |
+ } else { |
+ use->next = nullptr; |
+ use->prev = nullptr; |
+ } |
+} |
+ |
+ |
+Node::Node(NodeId id, const Operator* op, int input_count, |
+ int reserved_input_count) |
+ : op_(op), |
+ mark_(0), |
+ id_(id), |
+ bit_field_(InputCountField::encode(input_count) | |
+ ReservedInputCountField::encode(reserved_input_count) | |
+ HasAppendableInputsField::encode(false)), |
+ first_use_(nullptr), |
+ last_use_(nullptr) { |
+ inputs_.static_ = reinterpret_cast<Input*>(this + 1); |
+} |
+ |
+ |
+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; |
+ set_has_appendable_inputs(true); |
+ } |
+} |
+ |
+ |
+void Node::AppendUse(Use* const use) { |
+ use->next = nullptr; |
+ use->prev = last_use_; |
+ if (last_use_) { |
+ last_use_->next = use; |
+ } else { |
+ first_use_ = use; |
+ } |
+ last_use_ = use; |
+} |
+ |
+ |
+void Node::RemoveUse(Use* const use) { |
+ if (use == last_use_) { |
+ last_use_ = use->prev; |
+ } |
+ if (use->prev) { |
+ use->prev->next = use->next; |
+ } else { |
+ first_use_ = use->next; |
+ } |
+ if (use->next) { |
+ use->next->prev = use->prev; |
} |
- return current->from; |
} |
@@ -115,6 +233,46 @@ std::ostream& operator<<(std::ostream& os, const Node& n) { |
return os; |
} |
+ |
+Node::InputEdges::iterator Node::InputEdges::iterator::operator++(int n) { |
+ iterator result(*this); |
+ ++(*this); |
+ return result; |
+} |
+ |
+ |
+bool Node::InputEdges::empty() const { return begin() == end(); } |
+ |
+ |
+Node::Inputs::const_iterator Node::Inputs::const_iterator::operator++(int n) { |
+ const_iterator result(*this); |
+ ++(*this); |
+ return result; |
+} |
+ |
+ |
+bool Node::Inputs::empty() const { return begin() == end(); } |
+ |
+ |
+Node::UseEdges::iterator Node::UseEdges::iterator::operator++(int n) { |
+ iterator result(*this); |
+ ++(*this); |
+ return result; |
+} |
+ |
+ |
+bool Node::UseEdges::empty() const { return begin() == end(); } |
+ |
+ |
+Node::Uses::const_iterator Node::Uses::const_iterator::operator++(int n) { |
+ const_iterator result(*this); |
+ ++(*this); |
+ return result; |
+} |
+ |
+ |
+bool Node::Uses::empty() const { return begin() == end(); } |
+ |
} // namespace compiler |
} // namespace internal |
} // namespace v8 |