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 |