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/compiler/types.h" | 10 #include "src/compiler/types.h" |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 39 // In addition Nodes only contain a mutable Operator that may change during | 39 // In addition Nodes only contain a mutable Operator that may change during |
| 40 // compilation, e.g. during lowering passes. Other information that needs to be | 40 // compilation, e.g. during lowering passes. Other information that needs to be |
| 41 // associated with Nodes during compilation must be stored out-of-line indexed | 41 // associated with Nodes during compilation must be stored out-of-line indexed |
| 42 // by the Node's id. | 42 // by the Node's id. |
| 43 class V8_EXPORT_PRIVATE Node final { | 43 class V8_EXPORT_PRIVATE Node final { |
| 44 public: | 44 public: |
| 45 static Node* New(Zone* zone, NodeId id, const Operator* op, int input_count, | 45 static Node* New(Zone* zone, NodeId id, const Operator* op, int input_count, |
| 46 Node* const* inputs, bool has_extensible_inputs); | 46 Node* const* inputs, bool has_extensible_inputs); |
| 47 static Node* Clone(Zone* zone, NodeId id, const Node* node); | 47 static Node* Clone(Zone* zone, NodeId id, const Node* node); |
| 48 | 48 |
| 49 bool IsDead() const { return InputCount() > 0 && !InputAt(0); } | 49 inline bool IsDead() const; |
| 50 void Kill(); | 50 void Kill(); |
| 51 | 51 |
| 52 const Operator* op() const { return op_; } | 52 const Operator* op() const { return op_; } |
| 53 | 53 |
| 54 IrOpcode::Value opcode() const { | 54 IrOpcode::Value opcode() const { |
| 55 DCHECK(op_->opcode() <= IrOpcode::kLast); | 55 DCHECK(op_->opcode() <= IrOpcode::kLast); |
| 56 return static_cast<IrOpcode::Value>(op_->opcode()); | 56 return static_cast<IrOpcode::Value>(op_->opcode()); |
| 57 } | 57 } |
| 58 | 58 |
| 59 NodeId id() const { return IdField::decode(bit_field_); } | 59 NodeId id() const { return IdField::decode(bit_field_); } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 void AppendInput(Zone* zone, Node* new_to); | 102 void AppendInput(Zone* zone, Node* new_to); |
| 103 void InsertInput(Zone* zone, int index, Node* new_to); | 103 void InsertInput(Zone* zone, int index, Node* new_to); |
| 104 void InsertInputs(Zone* zone, int index, int count); | 104 void InsertInputs(Zone* zone, int index, int count); |
| 105 void RemoveInput(int index); | 105 void RemoveInput(int index); |
| 106 void NullAllInputs(); | 106 void NullAllInputs(); |
| 107 void TrimInputCount(int new_input_count); | 107 void TrimInputCount(int new_input_count); |
| 108 | 108 |
| 109 int UseCount() const; | 109 int UseCount() const; |
| 110 void ReplaceUses(Node* replace_to); | 110 void ReplaceUses(Node* replace_to); |
| 111 | 111 |
| 112 class InputEdges final { | 112 class InputEdges; |
| 113 public: | 113 inline InputEdges input_edges(); |
| 114 typedef Edge value_type; | |
| 115 | 114 |
| 116 class iterator; | 115 class Inputs; |
| 117 inline iterator begin() const; | 116 inline Inputs inputs() const; |
| 118 inline iterator end() const; | |
| 119 | |
| 120 bool empty() const; | |
| 121 | |
| 122 explicit InputEdges(Node* node) : node_(node) {} | |
| 123 | |
| 124 private: | |
| 125 Node* node_; | |
| 126 }; | |
| 127 | |
| 128 InputEdges input_edges() { return InputEdges(this); } | |
| 129 | |
| 130 class V8_EXPORT_PRIVATE Inputs final { | |
| 131 public: | |
| 132 typedef Node* value_type; | |
| 133 | |
| 134 class const_iterator; | |
| 135 inline const_iterator begin() const; | |
| 136 inline const_iterator end() const; | |
| 137 | |
| 138 bool empty() const; | |
| 139 | |
| 140 explicit Inputs(Node* node) : node_(node) {} | |
| 141 | |
| 142 private: | |
| 143 Node* node_; | |
| 144 }; | |
| 145 | |
| 146 Inputs inputs() { return Inputs(this); } | |
| 147 | 117 |
| 148 class UseEdges final { | 118 class UseEdges final { |
| 149 public: | 119 public: |
| 150 typedef Edge value_type; | 120 typedef Edge value_type; |
| 151 | 121 |
| 152 class iterator; | 122 class iterator; |
| 153 inline iterator begin() const; | 123 inline iterator begin() const; |
| 154 inline iterator end() const; | 124 inline iterator end() const; |
| 155 | 125 |
| 156 bool empty() const; | 126 bool empty() const; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 typedef ZoneVector<Node*> NodeVector; | 308 typedef ZoneVector<Node*> NodeVector; |
| 339 typedef ZoneVector<NodeVector> NodeVectorVector; | 309 typedef ZoneVector<NodeVector> NodeVectorVector; |
| 340 | 310 |
| 341 | 311 |
| 342 // Helper to extract parameters from Operator1<*> nodes. | 312 // Helper to extract parameters from Operator1<*> nodes. |
| 343 template <typename T> | 313 template <typename T> |
| 344 static inline const T& OpParameter(const Node* node) { | 314 static inline const T& OpParameter(const Node* node) { |
| 345 return OpParameter<T>(node->op()); | 315 return OpParameter<T>(node->op()); |
| 346 } | 316 } |
| 347 | 317 |
| 318 class Node::InputEdges final { | |
| 319 public: | |
| 320 typedef Edge value_type; | |
| 321 | |
| 322 class iterator; | |
| 323 inline iterator begin() const; | |
| 324 inline iterator end() const; | |
| 325 | |
| 326 bool empty() const { return count_ == 0; } | |
| 327 int count() const { return count_; } | |
| 328 | |
| 329 inline value_type operator[](int index) const; | |
| 330 | |
| 331 InputEdges(Node** input_root, Use* use_root, int count) | |
| 332 : input_root_(input_root), use_root_(use_root), count_(count) {} | |
| 333 | |
| 334 private: | |
| 335 Node** input_root_; | |
| 336 Use* use_root_; | |
| 337 int count_; | |
| 338 }; | |
| 339 | |
| 340 class V8_EXPORT_PRIVATE Node::Inputs final { | |
| 341 public: | |
| 342 typedef Node* value_type; | |
| 343 | |
| 344 class const_iterator; | |
| 345 inline const_iterator begin() const; | |
| 346 inline const_iterator end() const; | |
| 347 | |
| 348 bool empty() const { return count_ == 0; } | |
| 349 int count() const { return count_; } | |
| 350 | |
| 351 inline value_type operator[](int index) const; | |
| 352 | |
| 353 explicit Inputs(Node* const* input_root, int count) | |
| 354 : input_root_(input_root), count_(count) {} | |
| 355 | |
| 356 private: | |
| 357 Node* const* input_root_; | |
| 358 int count_; | |
| 359 }; | |
| 348 | 360 |
| 349 // An encapsulation for information associated with a single use of node as a | 361 // An encapsulation for information associated with a single use of node as a |
| 350 // input from another node, allowing access to both the defining node and | 362 // input from another node, allowing access to both the defining node and |
| 351 // the node having the input. | 363 // the node having the input. |
| 352 class Edge final { | 364 class Edge final { |
| 353 public: | 365 public: |
| 354 Node* from() const { return use_->from(); } | 366 Node* from() const { return use_->from(); } |
| 355 Node* to() const { return *input_ptr_; } | 367 Node* to() const { return *input_ptr_; } |
| 356 int index() const { | 368 int index() const { |
| 357 int const index = use_->input_index(); | 369 int const index = use_->input_index(); |
| 358 DCHECK_LT(index, use_->from()->InputCount()); | 370 DCHECK_LT(index, use_->from()->InputCount()); |
| 359 return index; | 371 return index; |
| 360 } | 372 } |
| 361 | 373 |
| 362 bool operator==(const Edge& other) { return input_ptr_ == other.input_ptr_; } | 374 bool operator==(const Edge& other) { return input_ptr_ == other.input_ptr_; } |
| 363 bool operator!=(const Edge& other) { return !(*this == other); } | 375 bool operator!=(const Edge& other) { return !(*this == other); } |
| 364 | 376 |
| 365 void UpdateTo(Node* new_to) { | 377 void UpdateTo(Node* new_to) { |
| 366 Node* old_to = *input_ptr_; | 378 Node* old_to = *input_ptr_; |
| 367 if (old_to != new_to) { | 379 if (old_to != new_to) { |
| 368 if (old_to) old_to->RemoveUse(use_); | 380 if (old_to) old_to->RemoveUse(use_); |
| 369 *input_ptr_ = new_to; | 381 *input_ptr_ = new_to; |
| 370 if (new_to) new_to->AppendUse(use_); | 382 if (new_to) new_to->AppendUse(use_); |
| 371 } | 383 } |
| 372 } | 384 } |
| 373 | 385 |
| 374 private: | 386 private: |
| 375 friend class Node::UseEdges::iterator; | 387 friend class Node::UseEdges::iterator; |
| 388 friend class Node::InputEdges; | |
| 376 friend class Node::InputEdges::iterator; | 389 friend class Node::InputEdges::iterator; |
| 377 | 390 |
| 378 Edge(Node::Use* use, Node** input_ptr) : use_(use), input_ptr_(input_ptr) { | 391 Edge(Node::Use* use, Node** input_ptr) : use_(use), input_ptr_(input_ptr) { |
| 379 DCHECK_NOT_NULL(use); | 392 DCHECK_NOT_NULL(use); |
| 380 DCHECK_NOT_NULL(input_ptr); | 393 DCHECK_NOT_NULL(input_ptr); |
| 381 DCHECK_EQ(input_ptr, use->input_ptr()); | 394 DCHECK_EQ(input_ptr, use->input_ptr()); |
| 382 } | 395 } |
| 383 | 396 |
| 384 Node::Use* use_; | 397 Node::Use* use_; |
| 385 Node** input_ptr_; | 398 Node** input_ptr_; |
| 386 }; | 399 }; |
| 387 | 400 |
| 401 bool Node::IsDead() const { | |
| 402 Node::Inputs inputs = this->inputs(); | |
| 403 return inputs.count() > 0 && inputs[0] == nullptr; | |
|
Jarin
2017/01/10 10:53:39
I actually think the original function will genera
Leszek Swirski
2017/01/10 12:03:38
You'd be surprised! I checked the disassembled ver
| |
| 404 } | |
| 405 | |
| 406 Node::InputEdges Node::input_edges() { | |
| 407 int inline_count = InlineCountField::decode(bit_field_); | |
| 408 if (inline_count != kOutlineMarker) { | |
| 409 return InputEdges(inputs_.inline_, reinterpret_cast<Use*>(this) - 1, | |
| 410 inline_count); | |
| 411 } else { | |
| 412 return InputEdges(inputs_.outline_->inputs_, | |
| 413 reinterpret_cast<Use*>(inputs_.outline_) - 1, | |
| 414 inputs_.outline_->count_); | |
| 415 } | |
| 416 } | |
| 417 | |
| 418 Node::Inputs Node::inputs() const { | |
| 419 int inline_count = InlineCountField::decode(bit_field_); | |
| 420 if (inline_count != kOutlineMarker) { | |
| 421 return Inputs(inputs_.inline_, inline_count); | |
| 422 } else { | |
| 423 return Inputs(inputs_.outline_->inputs_, inputs_.outline_->count_); | |
| 424 } | |
| 425 } | |
| 388 | 426 |
| 389 // A forward iterator to visit the edges for the input dependencies of a node. | 427 // A forward iterator to visit the edges for the input dependencies of a node. |
| 390 class Node::InputEdges::iterator final { | 428 class Node::InputEdges::iterator final { |
| 391 public: | 429 public: |
| 392 typedef std::forward_iterator_tag iterator_category; | 430 typedef std::forward_iterator_tag iterator_category; |
| 393 typedef int difference_type; | 431 typedef std::ptrdiff_t difference_type; |
| 394 typedef Edge value_type; | 432 typedef Edge value_type; |
| 395 typedef Edge* pointer; | 433 typedef Edge* pointer; |
| 396 typedef Edge& reference; | 434 typedef Edge& reference; |
| 397 | 435 |
| 398 iterator() : use_(nullptr), input_ptr_(nullptr) {} | 436 iterator() : use_(nullptr), input_ptr_(nullptr) {} |
| 399 iterator(const iterator& other) | 437 iterator(const iterator& other) |
| 400 : use_(other.use_), input_ptr_(other.input_ptr_) {} | 438 : use_(other.use_), input_ptr_(other.input_ptr_) {} |
| 401 | 439 |
| 402 Edge operator*() const { return Edge(use_, input_ptr_); } | 440 Edge operator*() const { return Edge(use_, input_ptr_); } |
| 403 bool operator==(const iterator& other) const { | 441 bool operator==(const iterator& other) const { |
| 404 return input_ptr_ == other.input_ptr_; | 442 return input_ptr_ == other.input_ptr_; |
| 405 } | 443 } |
| 406 bool operator!=(const iterator& other) const { return !(*this == other); } | 444 bool operator!=(const iterator& other) const { return !(*this == other); } |
| 407 iterator& operator++() { | 445 iterator& operator++() { |
| 408 input_ptr_++; | 446 input_ptr_++; |
| 409 use_--; | 447 use_--; |
| 410 return *this; | 448 return *this; |
| 411 } | 449 } |
| 412 iterator operator++(int); | 450 iterator operator++(int); |
| 413 iterator& operator+=(difference_type offset) { | 451 iterator& operator+=(difference_type offset) { |
| 414 input_ptr_ += offset; | 452 input_ptr_ += offset; |
| 415 use_ -= offset; | 453 use_ -= offset; |
| 416 return *this; | 454 return *this; |
| 417 } | 455 } |
| 418 iterator operator+(difference_type offset) const { | 456 iterator operator+(difference_type offset) const { |
| 419 return iterator(use_ - offset, input_ptr_ + offset); | 457 return iterator(use_ - offset, input_ptr_ + offset); |
| 420 } | 458 } |
| 421 difference_type operator-(const iterator& other) const { | 459 difference_type operator-(const iterator& other) const { |
| 422 return static_cast<difference_type>(input_ptr_ - other.input_ptr_); | 460 return input_ptr_ - other.input_ptr_; |
| 423 } | 461 } |
| 424 | 462 |
| 425 private: | 463 private: |
| 426 friend class Node; | 464 friend class Node; |
| 427 | 465 |
| 428 explicit iterator(Node* from, int index = 0) | |
| 429 : use_(from->GetUsePtr(index)), input_ptr_(from->GetInputPtr(index)) {} | |
| 430 | |
| 431 explicit iterator(Use* use, Node** input_ptr) | 466 explicit iterator(Use* use, Node** input_ptr) |
| 432 : use_(use), input_ptr_(input_ptr) {} | 467 : use_(use), input_ptr_(input_ptr) {} |
| 433 | 468 |
| 434 Use* use_; | 469 Use* use_; |
| 435 Node** input_ptr_; | 470 Node** input_ptr_; |
| 436 }; | 471 }; |
| 437 | 472 |
| 438 | 473 |
| 439 Node::InputEdges::iterator Node::InputEdges::begin() const { | 474 Node::InputEdges::iterator Node::InputEdges::begin() const { |
| 440 return Node::InputEdges::iterator(this->node_, 0); | 475 return Node::InputEdges::iterator(use_root_, input_root_); |
| 441 } | 476 } |
| 442 | 477 |
| 443 | 478 |
| 444 Node::InputEdges::iterator Node::InputEdges::end() const { | 479 Node::InputEdges::iterator Node::InputEdges::end() const { |
| 445 return Node::InputEdges::iterator(this->node_, this->node_->InputCount()); | 480 return Node::InputEdges::iterator(use_root_ - count_, input_root_ + count_); |
| 446 } | 481 } |
| 447 | 482 |
| 483 Edge Node::InputEdges::operator[](int index) const { | |
| 484 return Edge(use_root_ + index, input_root_ + index); | |
| 485 } | |
| 448 | 486 |
| 449 // A forward iterator to visit the inputs of a node. | 487 // A forward iterator to visit the inputs of a node. |
| 450 class Node::Inputs::const_iterator final { | 488 class Node::Inputs::const_iterator final { |
| 451 public: | 489 public: |
| 452 typedef std::forward_iterator_tag iterator_category; | 490 typedef std::forward_iterator_tag iterator_category; |
| 453 typedef int difference_type; | 491 typedef std::ptrdiff_t difference_type; |
| 454 typedef Node* value_type; | 492 typedef Node* value_type; |
| 455 typedef Node** pointer; | 493 typedef const value_type* pointer; |
| 456 typedef Node*& reference; | 494 typedef value_type& reference; |
| 457 | 495 |
| 458 const_iterator(const const_iterator& other) : iter_(other.iter_) {} | 496 const_iterator(const const_iterator& other) : input_ptr_(other.input_ptr_) {} |
| 459 | 497 |
| 460 Node* operator*() const { return (*iter_).to(); } | 498 Node* operator*() const { return *input_ptr_; } |
| 461 bool operator==(const const_iterator& other) const { | 499 bool operator==(const const_iterator& other) const { |
| 462 return iter_ == other.iter_; | 500 return input_ptr_ == other.input_ptr_; |
| 463 } | 501 } |
| 464 bool operator!=(const const_iterator& other) const { | 502 bool operator!=(const const_iterator& other) const { |
| 465 return !(*this == other); | 503 return !(*this == other); |
| 466 } | 504 } |
| 467 const_iterator& operator++() { | 505 const_iterator& operator++() { |
| 468 ++iter_; | 506 ++input_ptr_; |
| 469 return *this; | 507 return *this; |
| 470 } | 508 } |
| 471 const_iterator operator++(int); | 509 const_iterator operator++(int); |
| 472 const_iterator& operator+=(difference_type offset) { | 510 const_iterator& operator+=(difference_type offset) { |
| 473 iter_ += offset; | 511 input_ptr_ += offset; |
| 474 return *this; | 512 return *this; |
| 475 } | 513 } |
| 476 const_iterator operator+(difference_type offset) const { | 514 const_iterator operator+(difference_type offset) const { |
| 477 return const_iterator(iter_ + offset); | 515 return const_iterator(input_ptr_ + offset); |
| 478 } | 516 } |
| 479 difference_type operator-(const const_iterator& other) const { | 517 difference_type operator-(const const_iterator& other) const { |
| 480 return iter_ - other.iter_; | 518 return input_ptr_ - other.input_ptr_; |
| 481 } | 519 } |
| 482 | 520 |
| 483 private: | 521 private: |
| 484 friend class Node::Inputs; | 522 friend class Node::Inputs; |
| 485 | 523 |
| 486 const_iterator(Node* node, int index) : iter_(node, index) {} | 524 explicit const_iterator(Node* const* input_ptr) : input_ptr_(input_ptr) {} |
| 487 | 525 |
| 488 explicit const_iterator(Node::InputEdges::iterator iter) : iter_(iter) {} | 526 Node* const* input_ptr_; |
| 489 | |
| 490 Node::InputEdges::iterator iter_; | |
| 491 }; | 527 }; |
| 492 | 528 |
| 493 | 529 |
| 494 Node::Inputs::const_iterator Node::Inputs::begin() const { | 530 Node::Inputs::const_iterator Node::Inputs::begin() const { |
| 495 return const_iterator(this->node_, 0); | 531 return const_iterator(input_root_); |
| 496 } | 532 } |
| 497 | 533 |
| 498 | 534 |
| 499 Node::Inputs::const_iterator Node::Inputs::end() const { | 535 Node::Inputs::const_iterator Node::Inputs::end() const { |
| 500 return const_iterator(this->node_, this->node_->InputCount()); | 536 return const_iterator(input_root_ + count_); |
| 501 } | 537 } |
| 502 | 538 |
| 539 Node* Node::Inputs::operator[](int index) const { return input_root_[index]; } | |
| 503 | 540 |
| 504 // A forward iterator to visit the uses edges of a node. | 541 // A forward iterator to visit the uses edges of a node. |
| 505 class Node::UseEdges::iterator final { | 542 class Node::UseEdges::iterator final { |
| 506 public: | 543 public: |
| 507 iterator(const iterator& other) | 544 iterator(const iterator& other) |
| 508 : current_(other.current_), next_(other.next_) {} | 545 : current_(other.current_), next_(other.next_) {} |
| 509 | 546 |
| 510 Edge operator*() const { return Edge(current_, current_->input_ptr()); } | 547 Edge operator*() const { return Edge(current_, current_->input_ptr()); } |
| 511 bool operator==(const iterator& other) const { | 548 bool operator==(const iterator& other) const { |
| 512 return current_ == other.current_; | 549 return current_ == other.current_; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 583 } | 620 } |
| 584 | 621 |
| 585 | 622 |
| 586 Node::Uses::const_iterator Node::Uses::end() const { return const_iterator(); } | 623 Node::Uses::const_iterator Node::Uses::end() const { return const_iterator(); } |
| 587 | 624 |
| 588 } // namespace compiler | 625 } // namespace compiler |
| 589 } // namespace internal | 626 } // namespace internal |
| 590 } // namespace v8 | 627 } // namespace v8 |
| 591 | 628 |
| 592 #endif // V8_COMPILER_NODE_H_ | 629 #endif // V8_COMPILER_NODE_H_ |
| OLD | NEW |