Chromium Code Reviews| 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 #ifndef V8_COMPILER_NODE_H_ | 5 #ifndef V8_COMPILER_NODE_H_ |
| 6 #define V8_COMPILER_NODE_H_ | 6 #define V8_COMPILER_NODE_H_ |
| 7 | 7 |
| 8 #include "src/compiler/opcodes.h" | 8 #include "src/compiler/opcodes.h" |
| 9 #include "src/compiler/operator.h" | 9 #include "src/compiler/operator.h" |
| 10 #include "src/types-inl.h" | 10 #include "src/types-inl.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 48 void Kill(); | 48 void Kill(); |
| 49 | 49 |
| 50 const Operator* op() const { return op_; } | 50 const Operator* op() const { return op_; } |
| 51 void set_op(const Operator* op) { op_ = op; } | 51 void set_op(const Operator* op) { op_ = op; } |
| 52 | 52 |
| 53 IrOpcode::Value opcode() const { | 53 IrOpcode::Value opcode() const { |
| 54 DCHECK(op_->opcode() <= IrOpcode::kLast); | 54 DCHECK(op_->opcode() <= IrOpcode::kLast); |
| 55 return static_cast<IrOpcode::Value>(op_->opcode()); | 55 return static_cast<IrOpcode::Value>(op_->opcode()); |
| 56 } | 56 } |
| 57 | 57 |
| 58 NodeId id() const { return id_; } | 58 NodeId id() const { return IdField::decode(bit_field_); } |
| 59 | 59 |
| 60 int InputCount() const { return input_count(); } | 60 int InputCount() const { |
| 61 return has_inline_inputs() ? InlineCountField::decode(bit_field_) | |
| 62 : inputs_.outline_->count_; | |
| 63 } | |
| 64 | |
| 65 #if DEBUG | |
| 66 #define BOUNDS_CHECK(index) \ | |
| 67 do { \ | |
| 68 if (index < 0 || index >= InputCount()) { \ | |
| 69 V8_Fatal(__FILE__, __LINE__, "Node #%d:%s->InputAt(%d) out of bounds", \ | |
| 70 id(), op()->mnemonic(), index); \ | |
| 71 } \ | |
| 72 } while (false) | |
| 73 #else | |
| 74 #define BOUNDS_CHECK(index) \ | |
| 75 do { \ | |
| 76 } while (false) | |
| 77 #endif | |
| 78 | |
| 61 Node* InputAt(int index) const { | 79 Node* InputAt(int index) const { |
| 62 #if DEBUG | 80 BOUNDS_CHECK(index); |
| 63 if (index < 0 || index >= InputCount()) { | 81 return *GetInputPtrConst(index); |
| 64 V8_Fatal(__FILE__, __LINE__, "Node #%d:%s->InputAt(%d) out of bounds", | 82 } |
| 65 id(), op()->mnemonic(), index); | 83 |
| 84 void ReplaceInput(int index, Node* new_to) { | |
| 85 BOUNDS_CHECK(index); | |
| 86 Node** input_ptr = GetInputPtr(index); | |
| 87 Node* old_to = *input_ptr; | |
| 88 if (old_to != new_to) { | |
| 89 Use* use = GetUsePtr(index); | |
| 90 if (old_to) old_to->RemoveUse(use); | |
| 91 *input_ptr = new_to; | |
| 92 if (new_to) new_to->AppendUse(use); | |
| 66 } | 93 } |
| 67 #endif | |
| 68 return GetInputRecordPtr(index)->to; | |
| 69 } | 94 } |
| 70 inline void ReplaceInput(int index, Node* new_to); | 95 |
|
Michael Starzinger
2015/05/21 14:14:02
nit: Maybe #undef BOUNDS_CHECK here again.
titzer
2015/05/21 15:11:19
Done.
| |
| 71 void AppendInput(Zone* zone, Node* new_to); | 96 void AppendInput(Zone* zone, Node* new_to); |
| 72 void InsertInput(Zone* zone, int index, Node* new_to); | 97 void InsertInput(Zone* zone, int index, Node* new_to); |
| 73 void RemoveInput(int index); | 98 void RemoveInput(int index); |
| 74 void NullAllInputs(); | 99 void NullAllInputs(); |
| 75 void TrimInputCount(int new_input_count); | 100 void TrimInputCount(int new_input_count); |
| 76 | 101 |
| 77 int UseCount() const; | 102 int UseCount() const; |
| 78 void ReplaceUses(Node* replace_to); | 103 void ReplaceUses(Node* replace_to); |
| 79 | 104 |
| 80 class InputEdges final { | 105 class InputEdges final { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 explicit Uses(Node* node) : node_(node) {} | 169 explicit Uses(Node* node) : node_(node) {} |
| 145 | 170 |
| 146 private: | 171 private: |
| 147 Node* node_; | 172 Node* node_; |
| 148 }; | 173 }; |
| 149 | 174 |
| 150 Uses uses() { return Uses(this); } | 175 Uses uses() { return Uses(this); } |
| 151 | 176 |
| 152 // Returns true if {owner} is the user of {this} node. | 177 // Returns true if {owner} is the user of {this} node. |
| 153 bool OwnedBy(Node* owner) const { | 178 bool OwnedBy(Node* owner) const { |
| 154 return first_use_ && first_use_->from == owner && !first_use_->next; | 179 return first_use_ && first_use_->from() == owner && !first_use_->next; |
| 155 } | 180 } |
| 156 | 181 |
| 157 // Returns true if {owner1} and {owner2} are the only users of {this} node. | 182 // Returns true if {owner1} and {owner2} are the only users of {this} node. |
| 158 bool OwnedBy(Node const* owner1, Node const* owner2) const; | 183 bool OwnedBy(Node const* owner1, Node const* owner2) const; |
| 159 | 184 |
| 160 private: | 185 private: |
| 161 struct Use final : public ZoneObject { | 186 struct Use; |
| 162 Node* from; | 187 // Out of line storage for inputs when the number of inputs overflowed the |
| 188 // capacity of the inline-allocated space. | |
| 189 struct OutOfLineInputs { | |
| 190 Node* node_; | |
| 191 int count_; | |
| 192 int capacity_; | |
| 193 Node* inputs_[1]; | |
| 194 | |
| 195 static OutOfLineInputs* New(Zone* zone, int capacity); | |
| 196 void ExtractFrom(Use* use_ptr, Node** input_ptr, int count); | |
| 197 }; | |
| 198 | |
| 199 // A link in the use chain for a node. Every input {i} to a node {n} has an | |
| 200 // associated {Use} which is linked into the use chain of the {i} node. | |
| 201 struct Use { | |
| 163 Use* next; | 202 Use* next; |
| 164 Use* prev; | 203 Use* prev; |
| 165 int input_index; | 204 uint32_t bit_field_; |
| 205 | |
| 206 int input_index() const { return InputIndexField::decode(bit_field_); } | |
| 207 int output_index() const { return OutputIndexField::decode(bit_field_); } | |
| 208 bool is_inline_use() const { return InlineField::decode(bit_field_); } | |
| 209 Node** input_ptr() { | |
| 210 int index = input_index(); | |
| 211 Use* start = this + 1 + index; | |
| 212 Node** inputs = is_inline_use() | |
| 213 ? reinterpret_cast<Node*>(start)->inputs_.inline_ | |
| 214 : reinterpret_cast<OutOfLineInputs*>(start)->inputs_; | |
| 215 return &inputs[index]; | |
| 216 } | |
| 217 | |
| 218 Node* from() { | |
| 219 Use* start = this + 1 + input_index(); | |
| 220 return is_inline_use() ? reinterpret_cast<Node*>(start) | |
| 221 : reinterpret_cast<OutOfLineInputs*>(start)->node_; | |
| 222 } | |
| 223 | |
| 224 typedef BitField<bool, 0, 1> InlineField; | |
| 225 typedef BitField<unsigned, 1, 17> InputIndexField; | |
| 226 typedef BitField<unsigned, 18, 14> OutputIndexField; | |
| 166 }; | 227 }; |
| 167 | 228 |
| 168 class Input final { | 229 //============================================================================ |
| 169 public: | 230 //== Memory layout =========================================================== |
| 170 Node* to; | 231 //============================================================================ |
| 171 Use* use; | 232 // Saving space for big graphs is important. We use a memory layout trick to |
| 233 // be able to map {Node} objects to {Use} objects and vice-versa in a | |
| 234 // space-efficient manner. | |
| 235 // | |
| 236 // {Use} links are laid out in memory directly before a {Node}, followed by | |
| 237 // direct pointers to input {Nodes}. | |
| 238 // | |
| 239 // inline case: | |
| 240 // |Use #N |Use #N-1|...|Use #1 |Use #0 |Node xxxx |I#0|I#1|...|I#N-1|I#N| | |
| 241 // ^ ^ ^ | |
| 242 // + Use + Node + Input | |
| 243 // | |
| 244 // Since every {Use} instance records its {input_index}, pointer arithmetic | |
| 245 // can compute the {Node}. | |
| 246 // | |
| 247 // out-of-line case: | |
| 248 // |Node xxxx | | |
| 249 // ^ + outline ------------------+ | |
| 250 // +----------------------------------------+ | |
| 251 // | | | |
| 252 // v | node | |
| 253 // |Use #N |Use #N-1|...|Use #1 |Use #0 |OOL xxxxx |I#0|I#1|...|I#N-1|I#N| | |
| 254 // ^ ^ | |
| 255 // + Use + Input | |
| 256 // | |
| 257 // Out-of-line storage of input lists is needed if appending an input to | |
| 258 // a node exceeds the maximum inline capacity. | |
| 172 | 259 |
| 173 void Update(Node* new_to); | 260 Node(NodeId id, const Operator* op, int inline_count, int inline_capacity); |
| 174 }; | |
| 175 | 261 |
| 176 inline Node(NodeId id, const Operator* op, int input_count, | 262 Node* const* GetInputPtrConst(int input_index) const { |
| 177 int reserve_input_count); | 263 return has_inline_inputs() ? &(inputs_.inline_[input_index]) |
| 178 | 264 : &inputs_.outline_->inputs_[input_index]; |
| 179 inline void EnsureAppendableInputs(Zone* zone); | |
| 180 | |
| 181 Input* GetInputRecordPtr(int index) { | |
| 182 return has_appendable_inputs() ? &((*inputs_.appendable_)[index]) | |
| 183 : &inputs_.static_[index]; | |
| 184 } | 265 } |
| 185 const Input* GetInputRecordPtr(int index) const { | 266 Node** GetInputPtr(int input_index) { |
| 186 return has_appendable_inputs() ? &((*inputs_.appendable_)[index]) | 267 return has_inline_inputs() ? &(inputs_.inline_[input_index]) |
| 187 : &inputs_.static_[index]; | 268 : &inputs_.outline_->inputs_[input_index]; |
| 269 } | |
| 270 Use* GetUsePtr(int input_index) { | |
| 271 Use* ptr = has_inline_inputs() ? reinterpret_cast<Use*>(this) | |
| 272 : reinterpret_cast<Use*>(inputs_.outline_); | |
| 273 return &ptr[-1 - input_index]; | |
| 188 } | 274 } |
| 189 | 275 |
| 190 inline void AppendUse(Use* const use); | 276 void AppendUse(Use* use); |
| 191 inline void RemoveUse(Use* const use); | 277 void RemoveUse(Use* use); |
| 192 | 278 |
| 193 void* operator new(size_t, void* location) { return location; } | 279 void* operator new(size_t, void* location) { return location; } |
| 194 | 280 |
| 195 typedef ZoneDeque<Input> InputDeque; | |
| 196 | |
| 197 // Only NodeProperties should manipulate the bounds. | 281 // Only NodeProperties should manipulate the bounds. |
| 198 Bounds bounds() { return bounds_; } | 282 Bounds bounds() { return bounds_; } |
| 199 void set_bounds(Bounds b) { bounds_ = b; } | 283 void set_bounds(Bounds b) { bounds_ = b; } |
| 200 | 284 |
| 201 // Only NodeMarkers should manipulate the marks on nodes. | 285 // Only NodeMarkers should manipulate the marks on nodes. |
| 202 Mark mark() { return mark_; } | 286 Mark mark() { return mark_; } |
| 203 void set_mark(Mark mark) { mark_ = mark; } | 287 void set_mark(Mark mark) { mark_ = mark; } |
| 204 | 288 |
| 205 int input_count() const { return InputCountField::decode(bit_field_); } | 289 inline bool has_inline_inputs() const { |
| 206 void set_input_count(int input_count) { | 290 return InlineCountField::decode(bit_field_) != kOutlineMarker; |
| 207 DCHECK_LE(0, input_count); | |
| 208 bit_field_ = InputCountField::update(bit_field_, input_count); | |
| 209 } | 291 } |
| 210 | 292 |
| 211 int reserved_input_count() const { | 293 void ClearInputs(int start, int count); |
| 212 return ReservedInputCountField::decode(bit_field_); | |
| 213 } | |
| 214 void set_reserved_input_count(int reserved_input_count) { | |
| 215 DCHECK_LE(0, reserved_input_count); | |
| 216 bit_field_ = | |
| 217 ReservedInputCountField::update(bit_field_, reserved_input_count); | |
| 218 } | |
| 219 | 294 |
| 220 bool has_appendable_inputs() const { | 295 typedef BitField<NodeId, 0, 24> IdField; |
| 221 return HasAppendableInputsField::decode(bit_field_); | 296 typedef BitField<unsigned, 25, 4> InlineCountField; |
| 222 } | 297 typedef BitField<unsigned, 29, 4> InlineCapacityField; |
|
Michael Starzinger
2015/05/21 14:14:02
Looks like this is exceeding 32-bit here?
titzer
2015/05/21 15:11:19
Finger math is best math!
| |
| 223 void set_has_appendable_inputs(bool has_appendable_inputs) { | 298 static const int kOutlineMarker = InlineCountField::kMax; |
| 224 bit_field_ = | 299 static const int kMaxInlineCount = InlineCountField::kMax - 1; |
| 225 HasAppendableInputsField::update(bit_field_, has_appendable_inputs); | 300 static const int kMaxInlineCapacity = InlineCapacityField::kMax - 1; |
| 226 } | |
| 227 | |
| 228 typedef BitField<unsigned, 0, 29> InputCountField; | |
| 229 typedef BitField<unsigned, 29, 2> ReservedInputCountField; | |
| 230 typedef BitField<unsigned, 31, 1> HasAppendableInputsField; | |
| 231 static const int kDefaultReservedInputs = ReservedInputCountField::kMax; | |
| 232 | 301 |
| 233 const Operator* op_; | 302 const Operator* op_; |
| 234 Bounds bounds_; | 303 Bounds bounds_; |
| 235 Mark mark_; | 304 Mark mark_; |
| 236 NodeId const id_; | 305 uint32_t bit_field_; |
| 237 unsigned bit_field_; | |
| 238 Use* first_use_; | 306 Use* first_use_; |
| 239 union { | 307 union { |
| 240 // When a node is initially allocated, it uses a static buffer to hold its | 308 // Inline storage for inputs or out-of-line storage. |
| 241 // inputs under the assumption that the number of outputs will not increase. | 309 Node* inline_[1]; |
| 242 // When the first input is appended, the static buffer is converted into a | 310 OutOfLineInputs* outline_; |
| 243 // deque to allow for space-efficient growing. | |
| 244 Input static_[1]; | |
| 245 InputDeque* appendable_; | |
| 246 } inputs_; | 311 } inputs_; |
| 247 | 312 |
| 248 friend class Edge; | 313 friend class Edge; |
| 249 friend class NodeMarkerBase; | 314 friend class NodeMarkerBase; |
| 250 friend class NodeProperties; | 315 friend class NodeProperties; |
| 251 | 316 |
| 317 #if DEBUG | |
| 318 static Node* Verify(Node* node); | |
| 319 #define VERIFY(node) Verify(node) | |
|
Michael Starzinger
2015/05/21 14:14:02
This macro probably cannot be undef'ed, because it
titzer
2015/05/21 15:11:19
Fixed this to be a regular function in debug mode,
| |
| 320 #else | |
| 321 #define VERIFY(node) \ | |
| 322 do { \ | |
| 323 } while (false) | |
| 324 #endif | |
| 325 | |
| 252 DISALLOW_COPY_AND_ASSIGN(Node); | 326 DISALLOW_COPY_AND_ASSIGN(Node); |
| 253 }; | 327 }; |
| 254 | 328 |
| 255 | 329 |
| 256 std::ostream& operator<<(std::ostream& os, const Node& n); | 330 std::ostream& operator<<(std::ostream& os, const Node& n); |
| 257 | 331 |
| 258 | 332 |
| 259 // Typedefs to shorten commonly used Node containers. | 333 // Typedefs to shorten commonly used Node containers. |
| 260 typedef ZoneDeque<Node*> NodeDeque; | 334 typedef ZoneDeque<Node*> NodeDeque; |
| 261 typedef ZoneSet<Node*> NodeSet; | 335 typedef ZoneSet<Node*> NodeSet; |
| 262 typedef ZoneVector<Node*> NodeVector; | 336 typedef ZoneVector<Node*> NodeVector; |
| 263 typedef ZoneVector<NodeVector> NodeVectorVector; | 337 typedef ZoneVector<NodeVector> NodeVectorVector; |
| 264 | 338 |
| 265 | 339 |
| 266 // Helper to extract parameters from Operator1<*> nodes. | 340 // Helper to extract parameters from Operator1<*> nodes. |
| 267 template <typename T> | 341 template <typename T> |
| 268 static inline const T& OpParameter(const Node* node) { | 342 static inline const T& OpParameter(const Node* node) { |
| 269 return OpParameter<T>(node->op()); | 343 return OpParameter<T>(node->op()); |
| 270 } | 344 } |
| 271 | 345 |
| 272 | 346 |
| 273 // An encapsulation for information associated with a single use of node as a | 347 // An encapsulation for information associated with a single use of node as a |
| 274 // input from another node, allowing access to both the defining node and | 348 // input from another node, allowing access to both the defining node and |
| 275 // the node having the input. | 349 // the node having the input. |
| 276 class Edge final { | 350 class Edge final { |
| 277 public: | 351 public: |
| 278 Node* from() const { return input_->use->from; } | 352 Node* from() const { return use_->from(); } |
| 279 Node* to() const { return input_->to; } | 353 Node* to() const { return *input_ptr_; } |
| 280 int index() const { | 354 int index() const { |
| 281 int const index = input_->use->input_index; | 355 int const index = use_->input_index(); |
| 282 DCHECK_LT(index, input_->use->from->input_count()); | 356 DCHECK_LT(index, use_->from()->InputCount()); |
| 283 return index; | 357 return index; |
| 284 } | 358 } |
| 285 | 359 |
| 286 bool operator==(const Edge& other) { return input_ == other.input_; } | 360 bool operator==(const Edge& other) { return input_ptr_ == other.input_ptr_; } |
| 287 bool operator!=(const Edge& other) { return !(*this == other); } | 361 bool operator!=(const Edge& other) { return !(*this == other); } |
| 288 | 362 |
| 289 void UpdateTo(Node* new_to) { input_->Update(new_to); } | 363 void UpdateTo(Node* new_to) { |
| 364 Node* old_to = *input_ptr_; | |
| 365 if (old_to != new_to) { | |
| 366 if (old_to) old_to->RemoveUse(use_); | |
| 367 *input_ptr_ = new_to; | |
| 368 if (new_to) new_to->AppendUse(use_); | |
| 369 } | |
| 370 } | |
| 290 | 371 |
| 291 private: | 372 private: |
| 292 friend class Node::UseEdges::iterator; | 373 friend class Node::UseEdges::iterator; |
| 293 friend class Node::InputEdges::iterator; | 374 friend class Node::InputEdges::iterator; |
| 294 | 375 |
| 295 explicit Edge(Node::Input* input) : input_(input) { DCHECK_NOT_NULL(input); } | 376 Edge(Node::Use* use, Node** input_ptr) : use_(use), input_ptr_(input_ptr) { |
| 377 DCHECK_NOT_NULL(use); | |
| 378 DCHECK_NOT_NULL(input_ptr); | |
| 379 DCHECK_EQ(input_ptr, use->input_ptr()); | |
| 380 } | |
| 296 | 381 |
| 297 Node::Input* input_; | 382 Node::Use* use_; |
| 383 Node** input_ptr_; | |
| 298 }; | 384 }; |
| 299 | 385 |
| 300 | 386 |
| 301 // A forward iterator to visit the edges for the input dependencies of a node. | 387 // A forward iterator to visit the edges for the input dependencies of a node. |
| 302 class Node::InputEdges::iterator final { | 388 class Node::InputEdges::iterator final { |
| 303 public: | 389 public: |
| 304 typedef std::forward_iterator_tag iterator_category; | 390 typedef std::forward_iterator_tag iterator_category; |
| 305 typedef int difference_type; | 391 typedef int difference_type; |
| 306 typedef Edge value_type; | 392 typedef Edge value_type; |
| 307 typedef Edge* pointer; | 393 typedef Edge* pointer; |
| 308 typedef Edge& reference; | 394 typedef Edge& reference; |
| 309 | 395 |
| 310 iterator() : input_(nullptr) {} | 396 iterator() : use_(nullptr), input_ptr_(nullptr) {} |
| 311 iterator(const iterator& other) : input_(other.input_) {} | 397 iterator(const iterator& other) |
| 398 : use_(other.use_), input_ptr_(other.input_ptr_) {} | |
| 312 | 399 |
| 313 Edge operator*() const { return Edge(input_); } | 400 Edge operator*() const { return Edge(use_, input_ptr_); } |
| 314 bool operator==(const iterator& other) const { | 401 bool operator==(const iterator& other) const { |
| 315 return input_ == other.input_; | 402 return input_ptr_ == other.input_ptr_; |
| 316 } | 403 } |
| 317 bool operator!=(const iterator& other) const { return !(*this == other); } | 404 bool operator!=(const iterator& other) const { return !(*this == other); } |
| 318 iterator& operator++() { | 405 iterator& operator++() { |
| 319 SetInput(Edge(input_).from(), input_->use->input_index + 1); | 406 input_ptr_++; |
| 407 use_--; | |
| 320 return *this; | 408 return *this; |
| 321 } | 409 } |
| 322 iterator operator++(int); | 410 iterator operator++(int); |
| 323 | 411 |
| 324 private: | 412 private: |
| 325 friend class Node; | 413 friend class Node; |
| 326 | 414 |
| 327 explicit iterator(Node* from, int index = 0) : input_(nullptr) { | 415 explicit iterator(Node* from, int index = 0) |
| 328 SetInput(from, index); | 416 : use_(from->GetUsePtr(index)), input_ptr_(from->GetInputPtr(index)) {} |
| 329 } | |
| 330 | 417 |
| 331 void SetInput(Node* from, int index) { | 418 Use* use_; |
| 332 DCHECK(index >= 0 && index <= from->InputCount()); | 419 Node** input_ptr_; |
| 333 if (index < from->InputCount()) { | |
| 334 input_ = from->GetInputRecordPtr(index); | |
| 335 } else { | |
| 336 input_ = nullptr; | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 Input* input_; | |
| 341 }; | 420 }; |
| 342 | 421 |
| 343 | 422 |
| 344 Node::InputEdges::iterator Node::InputEdges::begin() const { | 423 Node::InputEdges::iterator Node::InputEdges::begin() const { |
| 345 return Node::InputEdges::iterator(this->node_, 0); | 424 return Node::InputEdges::iterator(this->node_, 0); |
| 346 } | 425 } |
| 347 | 426 |
| 348 | 427 |
| 349 Node::InputEdges::iterator Node::InputEdges::end() const { | 428 Node::InputEdges::iterator Node::InputEdges::end() const { |
| 350 return Node::InputEdges::iterator(this->node_, this->node_->InputCount()); | 429 return Node::InputEdges::iterator(this->node_, this->node_->InputCount()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 return const_iterator(this->node_, this->node_->InputCount()); | 472 return const_iterator(this->node_, this->node_->InputCount()); |
| 394 } | 473 } |
| 395 | 474 |
| 396 | 475 |
| 397 // A forward iterator to visit the uses edges of a node. | 476 // A forward iterator to visit the uses edges of a node. |
| 398 class Node::UseEdges::iterator final { | 477 class Node::UseEdges::iterator final { |
| 399 public: | 478 public: |
| 400 iterator(const iterator& other) | 479 iterator(const iterator& other) |
| 401 : current_(other.current_), next_(other.next_) {} | 480 : current_(other.current_), next_(other.next_) {} |
| 402 | 481 |
| 403 Edge operator*() const { | 482 Edge operator*() const { return Edge(current_, current_->input_ptr()); } |
| 404 return Edge(current_->from->GetInputRecordPtr(current_->input_index)); | |
| 405 } | |
| 406 | |
| 407 bool operator==(const iterator& other) const { | 483 bool operator==(const iterator& other) const { |
| 408 return current_ == other.current_; | 484 return current_ == other.current_; |
| 409 } | 485 } |
| 410 bool operator!=(const iterator& other) const { return !(*this == other); } | 486 bool operator!=(const iterator& other) const { return !(*this == other); } |
| 411 iterator& operator++() { | 487 iterator& operator++() { |
| 412 DCHECK_NOT_NULL(current_); | 488 DCHECK_NOT_NULL(current_); |
| 413 current_ = next_; | 489 current_ = next_; |
| 414 next_ = current_ ? current_->next : nullptr; | 490 next_ = current_ ? current_->next : nullptr; |
| 415 return *this; | 491 return *this; |
| 416 } | 492 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 443 class Node::Uses::const_iterator final { | 519 class Node::Uses::const_iterator final { |
| 444 public: | 520 public: |
| 445 typedef std::forward_iterator_tag iterator_category; | 521 typedef std::forward_iterator_tag iterator_category; |
| 446 typedef int difference_type; | 522 typedef int difference_type; |
| 447 typedef Node* value_type; | 523 typedef Node* value_type; |
| 448 typedef Node** pointer; | 524 typedef Node** pointer; |
| 449 typedef Node*& reference; | 525 typedef Node*& reference; |
| 450 | 526 |
| 451 const_iterator(const const_iterator& other) : current_(other.current_) {} | 527 const_iterator(const const_iterator& other) : current_(other.current_) {} |
| 452 | 528 |
| 453 Node* operator*() const { return current_->from; } | 529 Node* operator*() const { return current_->from(); } |
| 454 bool operator==(const const_iterator& other) const { | 530 bool operator==(const const_iterator& other) const { |
| 455 return other.current_ == current_; | 531 return other.current_ == current_; |
| 456 } | 532 } |
| 457 bool operator!=(const const_iterator& other) const { | 533 bool operator!=(const const_iterator& other) const { |
| 458 return other.current_ != current_; | 534 return other.current_ != current_; |
| 459 } | 535 } |
| 460 const_iterator& operator++() { | 536 const_iterator& operator++() { |
| 461 DCHECK_NOT_NULL(current_); | 537 DCHECK_NOT_NULL(current_); |
| 462 current_ = current_->next; | 538 current_ = current_->next; |
| 463 return *this; | 539 return *this; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 474 }; | 550 }; |
| 475 | 551 |
| 476 | 552 |
| 477 Node::Uses::const_iterator Node::Uses::begin() const { | 553 Node::Uses::const_iterator Node::Uses::begin() const { |
| 478 return const_iterator(this->node_); | 554 return const_iterator(this->node_); |
| 479 } | 555 } |
| 480 | 556 |
| 481 | 557 |
| 482 Node::Uses::const_iterator Node::Uses::end() const { return const_iterator(); } | 558 Node::Uses::const_iterator Node::Uses::end() const { return const_iterator(); } |
| 483 | 559 |
| 484 | |
| 485 void Node::ReplaceInput(int index, Node* new_to) { | |
| 486 GetInputRecordPtr(index)->Update(new_to); | |
| 487 } | |
| 488 | |
| 489 } // namespace compiler | 560 } // namespace compiler |
| 490 } // namespace internal | 561 } // namespace internal |
| 491 } // namespace v8 | 562 } // namespace v8 |
| 492 | 563 |
| 493 #endif // V8_COMPILER_NODE_H_ | 564 #endif // V8_COMPILER_NODE_H_ |
| OLD | NEW |