| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/node.h" | 5 #include "src/compiler/node.h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 8 |
| 7 namespace v8 { | 9 namespace v8 { |
| 8 namespace internal { | 10 namespace internal { |
| 9 namespace compiler { | 11 namespace compiler { |
| 10 | 12 |
| 11 Node::Node(NodeId id, const Operator* op, int input_count, | |
| 12 int reserved_input_count) | |
| 13 : op_(op), | |
| 14 mark_(0), | |
| 15 id_(id), | |
| 16 bit_field_(InputCountField::encode(input_count) | | |
| 17 ReservedInputCountField::encode(reserved_input_count) | | |
| 18 HasAppendableInputsField::encode(false)), | |
| 19 first_use_(nullptr), | |
| 20 last_use_(nullptr) { | |
| 21 inputs_.static_ = reinterpret_cast<Input*>(this + 1); | |
| 22 } | |
| 23 | |
| 24 | |
| 25 Node* Node::New(Zone* zone, NodeId id, const Operator* op, int input_count, | 13 Node* Node::New(Zone* zone, NodeId id, const Operator* op, int input_count, |
| 26 Node** inputs, bool has_extensible_inputs) { | 14 Node** inputs, bool has_extensible_inputs) { |
| 27 size_t node_size = sizeof(Node); | 15 size_t node_size = sizeof(Node); |
| 28 int reserve_input_count = has_extensible_inputs ? kDefaultReservedInputs : 0; | 16 int reserve_input_count = has_extensible_inputs ? kDefaultReservedInputs : 0; |
| 29 size_t inputs_size = (input_count + reserve_input_count) * sizeof(Input); | 17 size_t inputs_size = (input_count + reserve_input_count) * sizeof(Input); |
| 30 size_t uses_size = input_count * sizeof(Use); | 18 size_t uses_size = input_count * sizeof(Use); |
| 31 int size = static_cast<int>(node_size + inputs_size + uses_size); | 19 int size = static_cast<int>(node_size + inputs_size + uses_size); |
| 32 void* buffer = zone->New(size); | 20 void* buffer = zone->New(size); |
| 33 Node* result = new (buffer) Node(id, op, input_count, reserve_input_count); | 21 Node* result = new (buffer) Node(id, op, input_count, reserve_input_count); |
| 34 Input* input = | 22 Input* input = |
| (...skipping 15 matching lines...) Expand all Loading... |
| 50 } | 38 } |
| 51 | 39 |
| 52 | 40 |
| 53 void Node::Kill() { | 41 void Node::Kill() { |
| 54 DCHECK_NOT_NULL(op()); | 42 DCHECK_NOT_NULL(op()); |
| 55 RemoveAllInputs(); | 43 RemoveAllInputs(); |
| 56 DCHECK(uses().empty()); | 44 DCHECK(uses().empty()); |
| 57 } | 45 } |
| 58 | 46 |
| 59 | 47 |
| 60 void Node::CollectProjections(NodeVector* projections) { | 48 void Node::AppendInput(Zone* zone, Node* new_to) { |
| 61 for (size_t i = 0; i < projections->size(); i++) { | 49 DCHECK_NOT_NULL(zone); |
| 62 (*projections)[i] = NULL; | 50 DCHECK_NOT_NULL(new_to); |
| 51 Use* new_use = new (zone) Use; |
| 52 Input new_input; |
| 53 new_input.to = new_to; |
| 54 new_input.use = new_use; |
| 55 if (reserved_input_count() > 0) { |
| 56 DCHECK(!has_appendable_inputs()); |
| 57 set_reserved_input_count(reserved_input_count() - 1); |
| 58 inputs_.static_[input_count()] = new_input; |
| 59 } else { |
| 60 EnsureAppendableInputs(zone); |
| 61 inputs_.appendable_->push_back(new_input); |
| 63 } | 62 } |
| 64 for (UseIter i = uses().begin(); i != uses().end(); ++i) { | 63 new_use->input_index = input_count(); |
| 65 if ((*i)->opcode() != IrOpcode::kProjection) continue; | 64 new_use->from = this; |
| 66 size_t index = OpParameter<size_t>(*i); | 65 new_to->AppendUse(new_use); |
| 67 DCHECK_LT(index, projections->size()); | 66 set_input_count(input_count() + 1); |
| 68 DCHECK_EQ(NULL, (*projections)[index]); | |
| 69 (*projections)[index] = *i; | |
| 70 } | |
| 71 } | 67 } |
| 72 | 68 |
| 73 | 69 |
| 74 Node* Node::FindProjection(size_t projection_index) { | 70 void Node::InsertInput(Zone* zone, int index, Node* new_to) { |
| 75 for (UseIter i = uses().begin(); i != uses().end(); ++i) { | 71 DCHECK_NOT_NULL(zone); |
| 76 if ((*i)->opcode() == IrOpcode::kProjection && | 72 DCHECK_LE(0, index); |
| 77 OpParameter<size_t>(*i) == projection_index) { | 73 DCHECK_LT(index, InputCount()); |
| 78 return *i; | 74 AppendInput(zone, InputAt(InputCount() - 1)); |
| 79 } | 75 for (int i = InputCount() - 1; i > index; --i) { |
| 76 ReplaceInput(i, InputAt(i - 1)); |
| 80 } | 77 } |
| 81 return NULL; | 78 ReplaceInput(index, new_to); |
| 82 } | 79 } |
| 83 | 80 |
| 84 | 81 |
| 82 void Node::RemoveInput(int index) { |
| 83 DCHECK_LE(0, index); |
| 84 DCHECK_LT(index, InputCount()); |
| 85 for (; index < InputCount() - 1; ++index) { |
| 86 ReplaceInput(index, InputAt(index + 1)); |
| 87 } |
| 88 TrimInputCount(InputCount() - 1); |
| 89 } |
| 90 |
| 91 |
| 92 void Node::RemoveAllInputs() { |
| 93 for (Edge edge : input_edges()) edge.UpdateTo(nullptr); |
| 94 } |
| 95 |
| 96 |
| 97 void Node::TrimInputCount(int new_input_count) { |
| 98 DCHECK_LE(new_input_count, input_count()); |
| 99 if (new_input_count == input_count()) return; // Nothing to do. |
| 100 for (int index = new_input_count; index < input_count(); ++index) { |
| 101 ReplaceInput(index, nullptr); |
| 102 } |
| 103 if (!has_appendable_inputs()) { |
| 104 set_reserved_input_count(std::min<int>( |
| 105 ReservedInputCountField::kMax, |
| 106 reserved_input_count() + (input_count() - new_input_count))); |
| 107 } |
| 108 set_input_count(new_input_count); |
| 109 } |
| 110 |
| 111 |
| 85 int Node::UseCount() const { | 112 int Node::UseCount() const { |
| 86 int use_count = 0; | 113 int use_count = 0; |
| 87 for (const Use* use = first_use_; use; use = use->next) { | 114 for (const Use* use = first_use_; use; use = use->next) { |
| 88 ++use_count; | 115 ++use_count; |
| 89 } | 116 } |
| 90 return use_count; | 117 return use_count; |
| 91 } | 118 } |
| 92 | 119 |
| 93 | 120 |
| 94 Node* Node::UseAt(int index) const { | 121 Node* Node::UseAt(int index) const { |
| 95 DCHECK_LE(0, index); | 122 DCHECK_LE(0, index); |
| 96 DCHECK_LT(index, UseCount()); | 123 DCHECK_LT(index, UseCount()); |
| 97 Use* current = first_use_; | 124 const Use* use = first_use_; |
| 98 while (index-- != 0) { | 125 while (index-- != 0) { |
| 99 current = current->next; | 126 use = use->next; |
| 100 } | 127 } |
| 101 return current->from; | 128 return use->from; |
| 102 } | 129 } |
| 103 | 130 |
| 104 | 131 |
| 132 void Node::ReplaceUses(Node* replace_to) { |
| 133 for (Use* use = first_use_; use; use = use->next) { |
| 134 use->from->GetInputRecordPtr(use->input_index)->to = replace_to; |
| 135 } |
| 136 if (!replace_to->last_use_) { |
| 137 DCHECK_EQ(nullptr, replace_to->first_use_); |
| 138 replace_to->first_use_ = first_use_; |
| 139 replace_to->last_use_ = last_use_; |
| 140 } else if (first_use_) { |
| 141 DCHECK_NOT_NULL(replace_to->first_use_); |
| 142 replace_to->last_use_->next = first_use_; |
| 143 first_use_->prev = replace_to->last_use_; |
| 144 replace_to->last_use_ = last_use_; |
| 145 } |
| 146 first_use_ = nullptr; |
| 147 last_use_ = nullptr; |
| 148 } |
| 149 |
| 150 |
| 151 void Node::Input::Update(Node* new_to) { |
| 152 Node* old_to = this->to; |
| 153 if (new_to == old_to) return; // Nothing to do. |
| 154 // Snip out the use from where it used to be |
| 155 if (old_to) { |
| 156 old_to->RemoveUse(use); |
| 157 } |
| 158 to = new_to; |
| 159 // And put it into the new node's use list. |
| 160 if (new_to) { |
| 161 new_to->AppendUse(use); |
| 162 } else { |
| 163 use->next = nullptr; |
| 164 use->prev = nullptr; |
| 165 } |
| 166 } |
| 167 |
| 168 |
| 169 Node::Node(NodeId id, const Operator* op, int input_count, |
| 170 int reserved_input_count) |
| 171 : op_(op), |
| 172 mark_(0), |
| 173 id_(id), |
| 174 bit_field_(InputCountField::encode(input_count) | |
| 175 ReservedInputCountField::encode(reserved_input_count) | |
| 176 HasAppendableInputsField::encode(false)), |
| 177 first_use_(nullptr), |
| 178 last_use_(nullptr) { |
| 179 inputs_.static_ = reinterpret_cast<Input*>(this + 1); |
| 180 } |
| 181 |
| 182 |
| 183 void Node::EnsureAppendableInputs(Zone* zone) { |
| 184 if (!has_appendable_inputs()) { |
| 185 void* deque_buffer = zone->New(sizeof(InputDeque)); |
| 186 InputDeque* deque = new (deque_buffer) InputDeque(zone); |
| 187 for (int i = 0; i < input_count(); ++i) { |
| 188 deque->push_back(inputs_.static_[i]); |
| 189 } |
| 190 inputs_.appendable_ = deque; |
| 191 set_has_appendable_inputs(true); |
| 192 } |
| 193 } |
| 194 |
| 195 |
| 196 void Node::AppendUse(Use* const use) { |
| 197 use->next = nullptr; |
| 198 use->prev = last_use_; |
| 199 if (last_use_) { |
| 200 last_use_->next = use; |
| 201 } else { |
| 202 first_use_ = use; |
| 203 } |
| 204 last_use_ = use; |
| 205 } |
| 206 |
| 207 |
| 208 void Node::RemoveUse(Use* const use) { |
| 209 if (use == last_use_) { |
| 210 last_use_ = use->prev; |
| 211 } |
| 212 if (use->prev) { |
| 213 use->prev->next = use->next; |
| 214 } else { |
| 215 first_use_ = use->next; |
| 216 } |
| 217 if (use->next) { |
| 218 use->next->prev = use->prev; |
| 219 } |
| 220 } |
| 221 |
| 222 |
| 105 std::ostream& operator<<(std::ostream& os, const Node& n) { | 223 std::ostream& operator<<(std::ostream& os, const Node& n) { |
| 106 os << n.id() << ": " << *n.op(); | 224 os << n.id() << ": " << *n.op(); |
| 107 if (n.InputCount() > 0) { | 225 if (n.InputCount() > 0) { |
| 108 os << "("; | 226 os << "("; |
| 109 for (int i = 0; i < n.InputCount(); ++i) { | 227 for (int i = 0; i < n.InputCount(); ++i) { |
| 110 if (i != 0) os << ", "; | 228 if (i != 0) os << ", "; |
| 111 os << n.InputAt(i)->id(); | 229 os << n.InputAt(i)->id(); |
| 112 } | 230 } |
| 113 os << ")"; | 231 os << ")"; |
| 114 } | 232 } |
| 115 return os; | 233 return os; |
| 116 } | 234 } |
| 117 | 235 |
| 236 |
| 237 Node::InputEdges::iterator Node::InputEdges::iterator::operator++(int n) { |
| 238 iterator result(*this); |
| 239 ++(*this); |
| 240 return result; |
| 241 } |
| 242 |
| 243 |
| 244 bool Node::InputEdges::empty() const { return begin() == end(); } |
| 245 |
| 246 |
| 247 Node::Inputs::const_iterator Node::Inputs::const_iterator::operator++(int n) { |
| 248 const_iterator result(*this); |
| 249 ++(*this); |
| 250 return result; |
| 251 } |
| 252 |
| 253 |
| 254 bool Node::Inputs::empty() const { return begin() == end(); } |
| 255 |
| 256 |
| 257 Node::UseEdges::iterator Node::UseEdges::iterator::operator++(int n) { |
| 258 iterator result(*this); |
| 259 ++(*this); |
| 260 return result; |
| 261 } |
| 262 |
| 263 |
| 264 bool Node::UseEdges::empty() const { return begin() == end(); } |
| 265 |
| 266 |
| 267 Node::Uses::const_iterator Node::Uses::const_iterator::operator++(int n) { |
| 268 const_iterator result(*this); |
| 269 ++(*this); |
| 270 return result; |
| 271 } |
| 272 |
| 273 |
| 274 bool Node::Uses::empty() const { return begin() == end(); } |
| 275 |
| 118 } // namespace compiler | 276 } // namespace compiler |
| 119 } // namespace internal | 277 } // namespace internal |
| 120 } // namespace v8 | 278 } // namespace v8 |
| OLD | NEW |