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 <deque> | 8 #include <deque> |
9 #include <set> | 9 #include <set> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "src/compiler/generic-algorithm.h" | 12 #include "src/compiler/generic-algorithm.h" |
13 #include "src/compiler/generic-node.h" | |
14 #include "src/compiler/opcodes.h" | 13 #include "src/compiler/opcodes.h" |
15 #include "src/compiler/operator.h" | 14 #include "src/compiler/operator.h" |
16 #include "src/types.h" | 15 #include "src/types.h" |
17 #include "src/zone.h" | 16 #include "src/zone.h" |
18 #include "src/zone-allocator.h" | 17 #include "src/zone-allocator.h" |
| 18 #include "src/zone-containers.h" |
19 | 19 |
20 namespace v8 { | 20 namespace v8 { |
21 namespace internal { | 21 namespace internal { |
22 namespace compiler { | 22 namespace compiler { |
23 | 23 |
24 class NodeData { | 24 // A Node is the basic primitive of an IR graph. In addition to the graph |
| 25 // book-keeping Nodes only contain a mutable Operator that may change |
| 26 // during compilation, e.g. during lowering passes. Other information that |
| 27 // needs to be associated with Nodes during compilation must be stored |
| 28 // out-of-line indexed by the Node's id. |
| 29 class Node FINAL { |
25 public: | 30 public: |
| 31 Node(GenericGraphBase* graph, int input_count, int reserve_input_count); |
| 32 |
| 33 void Initialize(const Operator* op) { set_op(op); } |
| 34 |
| 35 bool IsDead() const { return InputCount() > 0 && InputAt(0) == NULL; } |
| 36 void Kill(); |
| 37 |
| 38 void CollectProjections(ZoneVector<Node*>* projections); |
| 39 Node* FindProjection(size_t projection_index); |
| 40 |
26 const Operator* op() const { return op_; } | 41 const Operator* op() const { return op_; } |
27 void set_op(const Operator* op) { op_ = op; } | 42 void set_op(const Operator* op) { op_ = op; } |
28 | 43 |
29 IrOpcode::Value opcode() const { | 44 IrOpcode::Value opcode() const { |
30 DCHECK(op_->opcode() <= IrOpcode::kLast); | 45 DCHECK(op_->opcode() <= IrOpcode::kLast); |
31 return static_cast<IrOpcode::Value>(op_->opcode()); | 46 return static_cast<IrOpcode::Value>(op_->opcode()); |
32 } | 47 } |
33 | 48 |
34 protected: | 49 inline NodeId id() const { return id_; } |
| 50 |
| 51 int InputCount() const { return input_count_; } |
| 52 Node* InputAt(int index) const { |
| 53 return static_cast<Node*>(GetInputRecordPtr(index)->to); |
| 54 } |
| 55 |
| 56 void ReplaceInput(int index, Node* new_input); |
| 57 void AppendInput(Zone* zone, Node* new_input); |
| 58 void InsertInput(Zone* zone, int index, Node* new_input); |
| 59 void RemoveInput(int index); |
| 60 |
| 61 int UseCount() { return use_count_; } |
| 62 Node* UseAt(int index) { |
| 63 DCHECK(index < use_count_); |
| 64 Use* current = first_use_; |
| 65 while (index-- != 0) { |
| 66 current = current->next; |
| 67 } |
| 68 return current->from; |
| 69 } |
| 70 void ReplaceUses(Node* replace_to); |
| 71 template <class UnaryPredicate> |
| 72 inline void ReplaceUsesIf(UnaryPredicate pred, Node* replace_to); |
| 73 void RemoveAllInputs(); |
| 74 |
| 75 void TrimInputCount(int input_count); |
| 76 |
| 77 class Inputs { |
| 78 public: |
| 79 class iterator; |
| 80 iterator begin(); |
| 81 iterator end(); |
| 82 |
| 83 explicit Inputs(Node* node) : node_(node) {} |
| 84 |
| 85 private: |
| 86 Node* node_; |
| 87 }; |
| 88 |
| 89 Inputs inputs() { return Inputs(this); } |
| 90 |
| 91 class Uses { |
| 92 public: |
| 93 class iterator; |
| 94 iterator begin(); |
| 95 iterator end(); |
| 96 bool empty(); // { return begin() == end(); } |
| 97 |
| 98 explicit Uses(Node* node) : node_(node) {} |
| 99 |
| 100 private: |
| 101 Node* node_; |
| 102 }; |
| 103 |
| 104 Uses uses() { return Uses(this); } |
| 105 |
| 106 class Edge; |
| 107 |
| 108 bool OwnedBy(Node* owner) const; |
| 109 |
| 110 static Node* New(GenericGraphBase* graph, int input_count, Node** inputs, |
| 111 bool has_extensible_inputs); |
| 112 |
| 113 |
| 114 private: |
35 const Operator* op_; | 115 const Operator* op_; |
36 Bounds bounds_; | 116 Bounds bounds_; |
37 explicit NodeData(Zone* zone) {} | |
38 | 117 |
39 friend class NodeProperties; | 118 friend class NodeProperties; |
40 Bounds bounds() { return bounds_; } | 119 Bounds bounds() { return bounds_; } |
41 void set_bounds(Bounds b) { bounds_ = b; } | 120 void set_bounds(Bounds b) { bounds_ = b; } |
42 }; | 121 |
43 | 122 friend class GenericGraphBase; |
44 // A Node is the basic primitive of an IR graph. In addition to the members | 123 |
45 // inherited from Vector, Nodes only contain a mutable Operator that may change | 124 class Use : public ZoneObject { |
46 // during compilation, e.g. during lowering passes. Other information that | 125 public: |
47 // needs to be associated with Nodes during compilation must be stored | 126 Node* from; |
48 // out-of-line indexed by the Node's id. | 127 Use* next; |
49 class Node FINAL : public GenericNode<NodeData, Node> { | 128 Use* prev; |
| 129 int input_index; |
| 130 }; |
| 131 |
| 132 class Input { |
| 133 public: |
| 134 Node* to; |
| 135 Use* use; |
| 136 |
| 137 void Update(Node* new_to); |
| 138 }; |
| 139 |
| 140 void EnsureAppendableInputs(Zone* zone); |
| 141 |
| 142 Input* GetInputRecordPtr(int index) const { |
| 143 if (has_appendable_inputs_) { |
| 144 return &((*inputs_.appendable_)[index]); |
| 145 } else { |
| 146 return inputs_.static_ + index; |
| 147 } |
| 148 } |
| 149 |
| 150 void AppendUse(Use* use); |
| 151 void RemoveUse(Use* use); |
| 152 |
| 153 void* operator new(size_t, void* location) { return location; } |
| 154 |
| 155 void AssignUniqueID(GenericGraphBase* graph); |
| 156 |
| 157 typedef ZoneDeque<Input> InputDeque; |
| 158 |
| 159 static const int kReservedInputCountBits = 2; |
| 160 static const int kMaxReservedInputs = (1 << kReservedInputCountBits) - 1; |
| 161 static const int kDefaultReservedInputs = kMaxReservedInputs; |
| 162 |
| 163 NodeId id_; |
| 164 int input_count_ : 29; |
| 165 unsigned int reserve_input_count_ : kReservedInputCountBits; |
| 166 bool has_appendable_inputs_ : 1; |
| 167 union { |
| 168 // When a node is initially allocated, it uses a static buffer to hold its |
| 169 // inputs under the assumption that the number of outputs will not increase. |
| 170 // When the first input is appended, the static buffer is converted into a |
| 171 // deque to allow for space-efficient growing. |
| 172 Input* static_; |
| 173 InputDeque* appendable_; |
| 174 } inputs_; |
| 175 int use_count_; |
| 176 Use* first_use_; |
| 177 Use* last_use_; |
| 178 |
| 179 DISALLOW_COPY_AND_ASSIGN(Node); |
| 180 }; |
| 181 |
| 182 class Node::Edge { |
50 public: | 183 public: |
51 Node(GenericGraphBase* graph, int input_count, int reserve_input_count) | 184 Node* from() const { return input_->use->from; } |
52 : GenericNode<NodeData, Node>(graph, input_count, reserve_input_count) {} | 185 Node* to() const { return input_->to; } |
53 | 186 int index() const { |
54 void Initialize(const Operator* op) { set_op(op); } | 187 int index = input_->use->input_index; |
55 | 188 DCHECK(index < input_->use->from->input_count_); |
56 bool IsDead() const { return InputCount() > 0 && InputAt(0) == NULL; } | 189 return index; |
57 void Kill(); | 190 } |
58 | 191 |
59 void CollectProjections(ZoneVector<Node*>* projections); | 192 private: |
60 Node* FindProjection(size_t projection_index); | 193 friend class Node::Uses::iterator; |
61 }; | 194 friend class Node::Inputs::iterator; |
| 195 |
| 196 explicit Edge(Node::Input* input) : input_(input) {} |
| 197 |
| 198 Node::Input* input_; |
| 199 }; |
| 200 |
| 201 |
| 202 // A forward iterator to visit the nodes which are depended upon by a node |
| 203 // in the order of input. |
| 204 class Node::Inputs::iterator { |
| 205 public: |
| 206 iterator(const Node::Inputs::iterator& other) // NOLINT |
| 207 : node_(other.node_), |
| 208 index_(other.index_) {} |
| 209 |
| 210 Node* operator*() { return GetInput()->to; } |
| 211 Node::Edge edge() { return Node::Edge(GetInput()); } |
| 212 bool operator==(const iterator& other) const { |
| 213 return other.index_ == index_ && other.node_ == node_; |
| 214 } |
| 215 bool operator!=(const iterator& other) const { return !(other == *this); } |
| 216 iterator& operator++() { |
| 217 DCHECK(node_ != NULL); |
| 218 DCHECK(index_ < node_->input_count_); |
| 219 ++index_; |
| 220 return *this; |
| 221 } |
| 222 iterator& UpdateToAndIncrement(Node* new_to) { |
| 223 Node::Input* input = GetInput(); |
| 224 input->Update(new_to); |
| 225 index_++; |
| 226 return *this; |
| 227 } |
| 228 int index() { return index_; } |
| 229 |
| 230 private: |
| 231 friend class Node; |
| 232 |
| 233 explicit iterator(Node* node, int index) : node_(node), index_(index) {} |
| 234 |
| 235 Input* GetInput() const { return node_->GetInputRecordPtr(index_); } |
| 236 |
| 237 Node* node_; |
| 238 int index_; |
| 239 }; |
| 240 |
| 241 // A forward iterator to visit the uses of a node. The uses are returned in |
| 242 // the order in which they were added as inputs. |
| 243 class Node::Uses::iterator { |
| 244 public: |
| 245 iterator(const Node::Uses::iterator& other) // NOLINT |
| 246 : current_(other.current_), |
| 247 index_(other.index_) {} |
| 248 |
| 249 Node* operator*() { return current_->from; } |
| 250 Node::Edge edge() { return Node::Edge(CurrentInput()); } |
| 251 |
| 252 bool operator==(const iterator& other) { return other.current_ == current_; } |
| 253 bool operator!=(const iterator& other) { return other.current_ != current_; } |
| 254 iterator& operator++() { |
| 255 DCHECK(current_ != NULL); |
| 256 index_++; |
| 257 current_ = current_->next; |
| 258 return *this; |
| 259 } |
| 260 iterator& UpdateToAndIncrement(Node* new_to) { |
| 261 DCHECK(current_ != NULL); |
| 262 index_++; |
| 263 Node::Input* input = CurrentInput(); |
| 264 current_ = current_->next; |
| 265 input->Update(new_to); |
| 266 return *this; |
| 267 } |
| 268 int index() const { return index_; } |
| 269 |
| 270 private: |
| 271 friend class Node::Uses; |
| 272 |
| 273 iterator() : current_(NULL), index_(0) {} |
| 274 explicit iterator(Node* node) : current_(node->first_use_), index_(0) {} |
| 275 |
| 276 Input* CurrentInput() const { |
| 277 return current_->from->GetInputRecordPtr(current_->input_index); |
| 278 } |
| 279 |
| 280 Node::Use* current_; |
| 281 int index_; |
| 282 }; |
| 283 |
| 284 |
| 285 template <class UnaryPredicate> |
| 286 inline void Node::ReplaceUsesIf(UnaryPredicate pred, Node* replace_to) { |
| 287 for (Use* use = first_use_; use != NULL;) { |
| 288 Use* next = use->next; |
| 289 if (pred(use->from)) { |
| 290 RemoveUse(use); |
| 291 replace_to->AppendUse(use); |
| 292 use->from->GetInputRecordPtr(use->input_index)->to = replace_to; |
| 293 } |
| 294 use = next; |
| 295 } |
| 296 } |
62 | 297 |
63 std::ostream& operator<<(std::ostream& os, const Node& n); | 298 std::ostream& operator<<(std::ostream& os, const Node& n); |
64 | 299 |
65 typedef GenericGraphVisit::NullNodeVisitor<NodeData, Node> NullNodeVisitor; | 300 typedef GenericGraphVisit::NullNodeVisitor<Node> NullNodeVisitor; |
66 | 301 |
67 typedef std::set<Node*, std::less<Node*>, zone_allocator<Node*> > NodeSet; | 302 typedef std::set<Node*, std::less<Node*>, zone_allocator<Node*> > NodeSet; |
68 typedef NodeSet::iterator NodeSetIter; | 303 typedef NodeSet::iterator NodeSetIter; |
69 typedef NodeSet::reverse_iterator NodeSetRIter; | 304 typedef NodeSet::reverse_iterator NodeSetRIter; |
70 | 305 |
71 typedef ZoneVector<Node*> NodeVector; | 306 typedef ZoneVector<Node*> NodeVector; |
72 typedef NodeVector::iterator NodeVectorIter; | 307 typedef NodeVector::iterator NodeVectorIter; |
73 typedef NodeVector::const_iterator NodeVectorConstIter; | 308 typedef NodeVector::const_iterator NodeVectorConstIter; |
74 typedef NodeVector::reverse_iterator NodeVectorRIter; | 309 typedef NodeVector::reverse_iterator NodeVectorRIter; |
75 | 310 |
76 typedef ZoneVector<NodeVector> NodeVectorVector; | 311 typedef ZoneVector<NodeVector> NodeVectorVector; |
77 typedef NodeVectorVector::iterator NodeVectorVectorIter; | 312 typedef NodeVectorVector::iterator NodeVectorVectorIter; |
78 typedef NodeVectorVector::reverse_iterator NodeVectorVectorRIter; | 313 typedef NodeVectorVector::reverse_iterator NodeVectorVectorRIter; |
79 | 314 |
80 typedef Node::Uses::iterator UseIter; | 315 typedef Node::Uses::iterator UseIter; |
81 typedef Node::Inputs::iterator InputIter; | 316 typedef Node::Inputs::iterator InputIter; |
82 | 317 |
83 // Helper to extract parameters from Operator1<*> nodes. | 318 // Helper to extract parameters from Operator1<*> nodes. |
84 template <typename T> | 319 template <typename T> |
85 static inline const T& OpParameter(const Node* node) { | 320 static inline const T& OpParameter(const Node* node) { |
86 return OpParameter<T>(node->op()); | 321 return OpParameter<T>(node->op()); |
87 } | 322 } |
88 | 323 |
89 } // namespace compiler | 324 } // namespace compiler |
90 } // namespace internal | 325 } // namespace internal |
91 } // namespace v8 | 326 } // namespace v8 |
92 | 327 |
93 #endif // V8_COMPILER_NODE_H_ | 328 #endif // V8_COMPILER_NODE_H_ |
OLD | NEW |