Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: src/compiler/node.h

Issue 780503002: [turbofan] Initial work on cleaning up the Node class. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/compiler/node.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <deque> 8 #include <deque>
9 #include <set> 9 #include <set>
10 #include <vector> 10 #include <vector>
11 11
12 #include "src/v8.h" 12 #include "src/v8.h"
13 13
14 #include "src/compiler/opcodes.h" 14 #include "src/compiler/opcodes.h"
15 #include "src/compiler/operator.h" 15 #include "src/compiler/operator.h"
16 #include "src/types.h" 16 #include "src/types.h"
17 #include "src/zone.h" 17 #include "src/zone.h"
18 #include "src/zone-allocator.h" 18 #include "src/zone-allocator.h"
19 #include "src/zone-containers.h" 19 #include "src/zone-containers.h"
20 20
21 namespace v8 { 21 namespace v8 {
22 namespace internal { 22 namespace internal {
23 namespace compiler { 23 namespace compiler {
24 24
25 // Forward declarations.
25 class Edge; 26 class Edge;
26 class Graph; 27 class Graph;
27 28
29
28 // Marks are used during traversal of the graph to distinguish states of nodes. 30 // Marks are used during traversal of the graph to distinguish states of nodes.
29 // Each node has a mark which is a monotonically increasing integer, and a 31 // Each node has a mark which is a monotonically increasing integer, and a
30 // {NodeMarker} has a range of values that indicate states of a node. 32 // {NodeMarker} has a range of values that indicate states of a node.
31 typedef uint32_t Mark; 33 typedef uint32_t Mark;
32 34
33 // NodeIds are identifying numbers for nodes that can be used to index auxiliary 35 // NodeIds are identifying numbers for nodes that can be used to index auxiliary
34 // out-of-line data associated with each node. 36 // out-of-line data associated with each node.
35 typedef int NodeId; 37 typedef int NodeId;
36 38
37 // A Node is the basic primitive of graphs. Nodes are chained together by 39 // A Node is the basic primitive of graphs. Nodes are chained together by
(...skipping 21 matching lines...) Expand all
59 const Operator* op() const { return op_; } 61 const Operator* op() const { return op_; }
60 void set_op(const Operator* op) { op_ = op; } 62 void set_op(const Operator* op) { op_ = op; }
61 63
62 IrOpcode::Value opcode() const { 64 IrOpcode::Value opcode() const {
63 DCHECK(op_->opcode() <= IrOpcode::kLast); 65 DCHECK(op_->opcode() <= IrOpcode::kLast);
64 return static_cast<IrOpcode::Value>(op_->opcode()); 66 return static_cast<IrOpcode::Value>(op_->opcode());
65 } 67 }
66 68
67 NodeId id() const { return id_; } 69 NodeId id() const { return id_; }
68 70
69 int InputCount() const { return input_count_; } 71 int InputCount() const { return input_count(); }
70 Node* InputAt(int index) const { return GetInputRecordPtr(index)->to; } 72 Node* InputAt(int index) const { return GetInputRecordPtr(index)->to; }
71 inline void ReplaceInput(int index, Node* new_input); 73 inline void ReplaceInput(int index, Node* new_input);
72 inline void AppendInput(Zone* zone, Node* new_input); 74 inline void AppendInput(Zone* zone, Node* new_input);
73 inline void InsertInput(Zone* zone, int index, Node* new_input); 75 inline void InsertInput(Zone* zone, int index, Node* new_input);
74 inline void RemoveInput(int index); 76 inline void RemoveInput(int index);
75 77
76 int UseCount() { return use_count_; } 78 int UseCount() const;
77 Node* UseAt(int index) { 79 Node* UseAt(int index) const;
78 DCHECK(index < use_count_);
79 Use* current = first_use_;
80 while (index-- != 0) {
81 current = current->next;
82 }
83 return current->from;
84 }
85 inline void ReplaceUses(Node* replace_to); 80 inline void ReplaceUses(Node* replace_to);
86 template <class UnaryPredicate> 81 template <class UnaryPredicate>
87 inline void ReplaceUsesIf(UnaryPredicate pred, Node* replace_to); 82 inline void ReplaceUsesIf(UnaryPredicate pred, Node* replace_to);
88 inline void RemoveAllInputs(); 83 inline void RemoveAllInputs();
89 84
90 inline void TrimInputCount(int input_count); 85 inline void TrimInputCount(int input_count);
91 86
92 class InputEdges { 87 class InputEdges {
93 public: 88 public:
94 class iterator; 89 class iterator;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 public: 163 public:
169 Node* to; 164 Node* to;
170 Use* use; 165 Use* use;
171 166
172 void Update(Node* new_to); 167 void Update(Node* new_to);
173 }; 168 };
174 169
175 void EnsureAppendableInputs(Zone* zone); 170 void EnsureAppendableInputs(Zone* zone);
176 171
177 Input* GetInputRecordPtr(int index) const { 172 Input* GetInputRecordPtr(int index) const {
178 if (has_appendable_inputs_) { 173 if (has_appendable_inputs()) {
179 return &((*inputs_.appendable_)[index]); 174 return &((*inputs_.appendable_)[index]);
180 } else { 175 } else {
181 return inputs_.static_ + index; 176 return &inputs_.static_[index];
182 } 177 }
183 } 178 }
184 179
185 inline void AppendUse(Use* use); 180 inline void AppendUse(Use* use);
186 inline void RemoveUse(Use* use); 181 inline void RemoveUse(Use* use);
187 182
188 void* operator new(size_t, void* location) { return location; } 183 void* operator new(size_t, void* location) { return location; }
189 184
190 private: 185 private:
191 Node(Graph* graph, int input_count, int reserve_input_count); 186 inline Node(NodeId id, int input_count, int reserve_input_count);
192 187
193 typedef ZoneDeque<Input> InputDeque; 188 typedef ZoneDeque<Input> InputDeque;
194 189
195 friend class NodeProperties; 190 friend class NodeProperties;
196 template <typename State> 191 template <typename State>
197 friend class NodeMarker; 192 friend class NodeMarker;
198 193
199 // Only NodeProperties should manipulate the bounds. 194 // Only NodeProperties should manipulate the bounds.
200 Bounds bounds() { return bounds_; } 195 Bounds bounds() { return bounds_; }
201 void set_bounds(Bounds b) { bounds_ = b; } 196 void set_bounds(Bounds b) { bounds_ = b; }
202 197
203 // Only NodeMarkers should manipulate the marks on nodes. 198 // Only NodeMarkers should manipulate the marks on nodes.
204 Mark mark() { return mark_; } 199 Mark mark() { return mark_; }
205 void set_mark(Mark mark) { mark_ = mark; } 200 void set_mark(Mark mark) { mark_ = mark; }
206 201
207 static const int kReservedInputCountBits = 2; 202 int input_count() const { return InputCountField::decode(bit_field_); }
208 static const int kMaxReservedInputs = (1 << kReservedInputCountBits) - 1; 203 void set_input_count(int input_count) {
209 static const int kDefaultReservedInputs = kMaxReservedInputs; 204 DCHECK_LE(0, input_count);
205 bit_field_ = InputCountField::update(bit_field_, input_count);
206 }
207
208 int reserved_input_count() const {
209 return ReservedInputCountField::decode(bit_field_);
210 }
211 void set_reserved_input_count(int reserved_input_count) {
212 DCHECK_LE(0, reserved_input_count);
213 bit_field_ =
214 ReservedInputCountField::update(bit_field_, reserved_input_count);
215 }
216
217 bool has_appendable_inputs() const {
218 return HasAppendableInputsField::decode(bit_field_);
219 }
220 void set_has_appendable_inputs(bool has_appendable_inputs) {
221 bit_field_ =
222 HasAppendableInputsField::update(bit_field_, has_appendable_inputs);
223 }
224
225 typedef BitField<unsigned, 0, 29> InputCountField;
226 typedef BitField<unsigned, 29, 2> ReservedInputCountField;
227 typedef BitField<unsigned, 31, 1> HasAppendableInputsField;
228 static const int kDefaultReservedInputs = ReservedInputCountField::kMax;
210 229
211 const Operator* op_; 230 const Operator* op_;
212 Bounds bounds_; 231 Bounds bounds_;
213 Mark mark_; 232 Mark mark_;
214 NodeId id_; 233 NodeId id_;
215 int input_count_ : 29; 234 unsigned bit_field_;
216 unsigned int reserve_input_count_ : kReservedInputCountBits;
217 bool has_appendable_inputs_ : 1;
218 union { 235 union {
219 // When a node is initially allocated, it uses a static buffer to hold its 236 // When a node is initially allocated, it uses a static buffer to hold its
220 // inputs under the assumption that the number of outputs will not increase. 237 // inputs under the assumption that the number of outputs will not increase.
221 // When the first input is appended, the static buffer is converted into a 238 // When the first input is appended, the static buffer is converted into a
222 // deque to allow for space-efficient growing. 239 // deque to allow for space-efficient growing.
223 Input* static_; 240 Input* static_;
224 InputDeque* appendable_; 241 InputDeque* appendable_;
225 } inputs_; 242 } inputs_;
226 int use_count_;
227 Use* first_use_; 243 Use* first_use_;
228 Use* last_use_; 244 Use* last_use_;
229 245
230 DISALLOW_COPY_AND_ASSIGN(Node); 246 DISALLOW_COPY_AND_ASSIGN(Node);
231 }; 247 };
232 248
233 249
234 // An encapsulation for information associated with a single use of node as a 250 // An encapsulation for information associated with a single use of node as a
235 // input from another node, allowing access to both the defining node and 251 // input from another node, allowing access to both the defining node and
236 // the node having the input. 252 // the node having the input.
237 class Edge { 253 class Edge {
238 public: 254 public:
239 Node* from() const { return input_->use->from; } 255 Node* from() const { return input_->use->from; }
240 Node* to() const { return input_->to; } 256 Node* to() const { return input_->to; }
241 int index() const { 257 int index() const {
242 int index = input_->use->input_index; 258 int index = input_->use->input_index;
243 DCHECK(index < input_->use->from->input_count_); 259 DCHECK(index < input_->use->from->input_count());
244 return index; 260 return index;
245 } 261 }
246 262
247 bool operator==(const Edge& other) { return input_ == other.input_; } 263 bool operator==(const Edge& other) { return input_ == other.input_; }
248 bool operator!=(const Edge& other) { return !(*this == other); } 264 bool operator!=(const Edge& other) { return !(*this == other); }
249 265
250 void UpdateTo(Node* new_to) { input_->Update(new_to); } 266 void UpdateTo(Node* new_to) { input_->Update(new_to); }
251 267
252 private: 268 private:
253 friend class Node::Uses::iterator; 269 friend class Node::Uses::iterator;
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 if (replace_to->last_use_ == NULL) { 509 if (replace_to->last_use_ == NULL) {
494 DCHECK_EQ(NULL, replace_to->first_use_); 510 DCHECK_EQ(NULL, replace_to->first_use_);
495 replace_to->first_use_ = first_use_; 511 replace_to->first_use_ = first_use_;
496 replace_to->last_use_ = last_use_; 512 replace_to->last_use_ = last_use_;
497 } else if (first_use_ != NULL) { 513 } else if (first_use_ != NULL) {
498 DCHECK_NE(NULL, replace_to->first_use_); 514 DCHECK_NE(NULL, replace_to->first_use_);
499 replace_to->last_use_->next = first_use_; 515 replace_to->last_use_->next = first_use_;
500 first_use_->prev = replace_to->last_use_; 516 first_use_->prev = replace_to->last_use_;
501 replace_to->last_use_ = last_use_; 517 replace_to->last_use_ = last_use_;
502 } 518 }
503 replace_to->use_count_ += use_count_;
504 use_count_ = 0;
505 first_use_ = NULL; 519 first_use_ = NULL;
506 last_use_ = NULL; 520 last_use_ = NULL;
507 } 521 }
508 522
509 template <class UnaryPredicate> 523 template <class UnaryPredicate>
510 inline void Node::ReplaceUsesIf(UnaryPredicate pred, Node* replace_to) { 524 inline void Node::ReplaceUsesIf(UnaryPredicate pred, Node* replace_to) {
511 for (Use* use = first_use_; use != NULL;) { 525 for (Use* use = first_use_; use != NULL;) {
512 Use* next = use->next; 526 Use* next = use->next;
513 if (pred(use->from)) { 527 if (pred(use->from)) {
514 RemoveUse(use); 528 RemoveUse(use);
515 replace_to->AppendUse(use); 529 replace_to->AppendUse(use);
516 use->from->GetInputRecordPtr(use->input_index)->to = replace_to; 530 use->from->GetInputRecordPtr(use->input_index)->to = replace_to;
517 } 531 }
518 use = next; 532 use = next;
519 } 533 }
520 } 534 }
521 535
522 inline void Node::RemoveAllInputs() { 536 inline void Node::RemoveAllInputs() {
523 for (Edge edge : input_edges()) { 537 for (Edge edge : input_edges()) {
524 edge.UpdateTo(NULL); 538 edge.UpdateTo(NULL);
525 } 539 }
526 } 540 }
527 541
528 inline void Node::TrimInputCount(int new_input_count) { 542 inline void Node::TrimInputCount(int new_input_count) {
529 if (new_input_count == input_count_) return; // Nothing to do. 543 if (new_input_count == input_count()) return; // Nothing to do.
530 544
531 DCHECK(new_input_count < input_count_); 545 DCHECK(new_input_count < input_count());
532 546
533 // Update inline inputs. 547 // Update inline inputs.
534 for (int i = new_input_count; i < input_count_; i++) { 548 for (int i = new_input_count; i < input_count(); i++) {
535 Node::Input* input = GetInputRecordPtr(i); 549 Node::Input* input = GetInputRecordPtr(i);
536 input->Update(NULL); 550 input->Update(NULL);
537 } 551 }
538 input_count_ = new_input_count; 552 set_input_count(new_input_count);
539 } 553 }
540 554
541 inline void Node::ReplaceInput(int index, Node* new_to) { 555 inline void Node::ReplaceInput(int index, Node* new_to) {
542 Input* input = GetInputRecordPtr(index); 556 Input* input = GetInputRecordPtr(index);
543 input->Update(new_to); 557 input->Update(new_to);
544 } 558 }
545 559
546 inline void Node::Input::Update(Node* new_to) { 560 inline void Node::Input::Update(Node* new_to) {
547 Node* old_to = this->to; 561 Node* old_to = this->to;
548 if (new_to == old_to) return; // Nothing to do. 562 if (new_to == old_to) return; // Nothing to do.
549 // Snip out the use from where it used to be 563 // Snip out the use from where it used to be
550 if (old_to != NULL) { 564 if (old_to != NULL) {
551 old_to->RemoveUse(use); 565 old_to->RemoveUse(use);
552 } 566 }
553 to = new_to; 567 to = new_to;
554 // And put it into the new node's use list. 568 // And put it into the new node's use list.
555 if (new_to != NULL) { 569 if (new_to != NULL) {
556 new_to->AppendUse(use); 570 new_to->AppendUse(use);
557 } else { 571 } else {
558 use->next = NULL; 572 use->next = NULL;
559 use->prev = NULL; 573 use->prev = NULL;
560 } 574 }
561 } 575 }
562 576
563 inline void Node::EnsureAppendableInputs(Zone* zone) { 577 inline void Node::EnsureAppendableInputs(Zone* zone) {
564 if (!has_appendable_inputs_) { 578 if (!has_appendable_inputs()) {
565 void* deque_buffer = zone->New(sizeof(InputDeque)); 579 void* deque_buffer = zone->New(sizeof(InputDeque));
566 InputDeque* deque = new (deque_buffer) InputDeque(zone); 580 InputDeque* deque = new (deque_buffer) InputDeque(zone);
567 for (int i = 0; i < input_count_; ++i) { 581 for (int i = 0; i < input_count(); ++i) {
568 deque->push_back(inputs_.static_[i]); 582 deque->push_back(inputs_.static_[i]);
569 } 583 }
570 inputs_.appendable_ = deque; 584 inputs_.appendable_ = deque;
571 has_appendable_inputs_ = true; 585 set_has_appendable_inputs(true);
572 } 586 }
573 } 587 }
574 588
575 inline void Node::AppendInput(Zone* zone, Node* to_append) { 589 inline void Node::AppendInput(Zone* zone, Node* to_append) {
576 Use* new_use = new (zone) Use; 590 Use* new_use = new (zone) Use;
577 Input new_input; 591 Input new_input;
578 new_input.to = to_append; 592 new_input.to = to_append;
579 new_input.use = new_use; 593 new_input.use = new_use;
580 if (reserve_input_count_ > 0) { 594 if (reserved_input_count() > 0) {
581 DCHECK(!has_appendable_inputs_); 595 DCHECK(!has_appendable_inputs());
582 reserve_input_count_--; 596 set_reserved_input_count(reserved_input_count() - 1);
583 inputs_.static_[input_count_] = new_input; 597 inputs_.static_[input_count()] = new_input;
584 } else { 598 } else {
585 EnsureAppendableInputs(zone); 599 EnsureAppendableInputs(zone);
586 inputs_.appendable_->push_back(new_input); 600 inputs_.appendable_->push_back(new_input);
587 } 601 }
588 new_use->input_index = input_count_; 602 new_use->input_index = input_count();
589 new_use->from = this; 603 new_use->from = this;
590 to_append->AppendUse(new_use); 604 to_append->AppendUse(new_use);
591 input_count_++; 605 set_input_count(input_count() + 1);
592 } 606 }
593 607
594 inline void Node::InsertInput(Zone* zone, int index, Node* to_insert) { 608 inline void Node::InsertInput(Zone* zone, int index, Node* to_insert) {
595 DCHECK(index >= 0 && index < InputCount()); 609 DCHECK(index >= 0 && index < InputCount());
596 // TODO(turbofan): Optimize this implementation! 610 // TODO(turbofan): Optimize this implementation!
597 AppendInput(zone, InputAt(InputCount() - 1)); 611 AppendInput(zone, InputAt(InputCount() - 1));
598 for (int i = InputCount() - 1; i > index; --i) { 612 for (int i = InputCount() - 1; i > index; --i) {
599 ReplaceInput(i, InputAt(i - 1)); 613 ReplaceInput(i, InputAt(i - 1));
600 } 614 }
601 ReplaceInput(index, to_insert); 615 ReplaceInput(index, to_insert);
(...skipping 10 matching lines...) Expand all
612 626
613 inline void Node::AppendUse(Use* use) { 627 inline void Node::AppendUse(Use* use) {
614 use->next = NULL; 628 use->next = NULL;
615 use->prev = last_use_; 629 use->prev = last_use_;
616 if (last_use_ == NULL) { 630 if (last_use_ == NULL) {
617 first_use_ = use; 631 first_use_ = use;
618 } else { 632 } else {
619 last_use_->next = use; 633 last_use_->next = use;
620 } 634 }
621 last_use_ = use; 635 last_use_ = use;
622 ++use_count_;
623 } 636 }
624 637
625 inline void Node::RemoveUse(Use* use) { 638 inline void Node::RemoveUse(Use* use) {
626 if (last_use_ == use) { 639 if (last_use_ == use) {
627 last_use_ = use->prev; 640 last_use_ = use->prev;
628 } 641 }
629 if (use->prev != NULL) { 642 if (use->prev != NULL) {
630 use->prev->next = use->next; 643 use->prev->next = use->next;
631 } else { 644 } else {
632 first_use_ = use->next; 645 first_use_ = use->next;
633 } 646 }
634 if (use->next != NULL) { 647 if (use->next != NULL) {
635 use->next->prev = use->prev; 648 use->next->prev = use->prev;
636 } 649 }
637 --use_count_;
638 } 650 }
639 651
640 inline bool Node::OwnedBy(Node* owner) const { 652 inline bool Node::OwnedBy(Node* owner) const {
641 return first_use_ != NULL && first_use_->from == owner && 653 return first_use_ != NULL && first_use_->from == owner &&
642 first_use_->next == NULL; 654 first_use_->next == NULL;
643 } 655 }
644 656
645 } // namespace compiler 657 } // namespace compiler
646 } // namespace internal 658 } // namespace internal
647 } // namespace v8 659 } // namespace v8
648 660
649 #endif // V8_COMPILER_NODE_H_ 661 #endif // V8_COMPILER_NODE_H_
OLDNEW
« no previous file with comments | « no previous file | src/compiler/node.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698