5 #include "src/compiler/node.h" 11 Node::OutOfLineInputs* Node::OutOfLineInputs::New(Zone* zone,
int capacity) {
13 sizeof(OutOfLineInputs) + capacity * (
sizeof(Node*) +
sizeof(Use));
14 intptr_t raw_buffer =
reinterpret_cast<intptr_t
>(zone->New(size));
15 Node::OutOfLineInputs* outline =
16 reinterpret_cast<OutOfLineInputs*
>(raw_buffer + capacity *
sizeof(Use));
17 outline->capacity_ = capacity;
23 void Node::OutOfLineInputs::ExtractFrom(Use* old_use_ptr, Node** old_input_ptr,
27 Use* new_use_ptr =
reinterpret_cast<Use*
>(
this) - 1;
28 Node** new_input_ptr = inputs_;
29 for (
int current = 0; current < count; current++) {
30 new_use_ptr->bit_field_ =
31 Use::InputIndexField::encode(current) | Use::InlineField::encode(
false);
32 DCHECK_EQ(old_input_ptr, old_use_ptr->input_ptr());
33 DCHECK_EQ(new_input_ptr, new_use_ptr->input_ptr());
34 Node* old_to = *old_input_ptr;
36 *old_input_ptr =
nullptr;
37 old_to->RemoveUse(old_use_ptr);
38 *new_input_ptr = old_to;
39 old_to->AppendUse(new_use_ptr);
41 *new_input_ptr =
nullptr;
52 Node* Node::New(Zone* zone, NodeId
id,
const Operator* op,
int input_count,
53 Node*
const* inputs,
bool has_extensible_inputs) {
61 for (
int i = 0;
i < input_count;
i++) {
62 if (inputs[
i] ==
nullptr) {
63 FATAL(
"Node::New() Error: #%d:%s[%d] is nullptr", static_cast<int>(
id),
69 if (input_count > kMaxInlineCapacity) {
72 has_extensible_inputs ? input_count + kMaxInlineCapacity : input_count;
73 OutOfLineInputs* outline = OutOfLineInputs::New(zone, capacity);
76 void* node_buffer = zone->New(
sizeof(Node));
77 node =
new (node_buffer) Node(
id, op, kOutlineMarker, 0);
78 node->inputs_.outline_ = outline;
80 outline->node_ = node;
81 outline->count_ = input_count;
83 input_ptr = outline->inputs_;
84 use_ptr =
reinterpret_cast<Use*
>(outline);
88 int capacity = input_count;
89 if (has_extensible_inputs) {
90 const int max = kMaxInlineCapacity;
91 capacity = std::min(input_count + 3, max);
94 size_t size =
sizeof(Node) + capacity * (
sizeof(Node*) +
sizeof(Use));
95 intptr_t raw_buffer =
reinterpret_cast<intptr_t
>(zone->New(size));
97 reinterpret_cast<void*
>(raw_buffer + capacity *
sizeof(Use));
99 node =
new (node_buffer) Node(
id, op, input_count, capacity);
100 input_ptr = node->inputs_.inline_;
101 use_ptr =
reinterpret_cast<Use*
>(node);
106 for (
int current = 0; current < input_count; ++current) {
107 Node* to = *inputs++;
108 input_ptr[current] = to;
109 Use* use = use_ptr - 1 - current;
110 use->bit_field_ = Use::InputIndexField::encode(current) |
111 Use::InlineField::encode(is_inline);
119 Node* Node::Clone(Zone* zone, NodeId
id,
const Node* node) {
120 int const input_count = node->InputCount();
121 Node*
const*
const inputs = node->has_inline_inputs()
122 ? node->inputs_.inline_
123 : node->inputs_.outline_->inputs_;
124 Node*
const clone = New(zone,
id, node->op(), input_count, inputs,
false);
125 clone->set_type(node->type());
131 DCHECK_NOT_NULL(op());
133 DCHECK(uses().empty());
137 void Node::AppendInput(Zone* zone, Node* new_to) {
138 DCHECK_NOT_NULL(zone);
139 DCHECK_NOT_NULL(new_to);
141 int inline_count = InlineCountField::decode(bit_field_);
142 int inline_capacity = InlineCapacityField::decode(bit_field_);
143 if (inline_count < inline_capacity) {
145 bit_field_ = InlineCountField::update(bit_field_, inline_count + 1);
146 *GetInputPtr(inline_count) = new_to;
147 Use* use = GetUsePtr(inline_count);
148 use->bit_field_ = Use::InputIndexField::encode(inline_count) |
149 Use::InlineField::encode(
true);
150 new_to->AppendUse(use);
153 int input_count = InputCount();
154 OutOfLineInputs* outline =
nullptr;
155 if (inline_count != kOutlineMarker) {
157 outline = OutOfLineInputs::New(zone, input_count * 2 + 3);
158 outline->node_ =
this;
159 outline->ExtractFrom(GetUsePtr(0), GetInputPtr(0), input_count);
160 bit_field_ = InlineCountField::update(bit_field_, kOutlineMarker);
161 inputs_.outline_ = outline;
164 outline = inputs_.outline_;
165 if (input_count >= outline->capacity_) {
167 outline = OutOfLineInputs::New(zone, input_count * 2 + 3);
168 outline->node_ =
this;
169 outline->ExtractFrom(GetUsePtr(0), GetInputPtr(0), input_count);
170 inputs_.outline_ = outline;
174 *GetInputPtr(input_count) = new_to;
175 Use* use = GetUsePtr(input_count);
176 use->bit_field_ = Use::InputIndexField::encode(input_count) |
177 Use::InlineField::encode(
false);
178 new_to->AppendUse(use);
184 void Node::InsertInput(Zone* zone,
int index, Node* new_to) {
185 DCHECK_NOT_NULL(zone);
187 DCHECK_LT(index, InputCount());
188 AppendInput(zone, InputAt(InputCount() - 1));
189 for (
int i = InputCount() - 1;
i > index; --
i) {
190 ReplaceInput(
i, InputAt(
i - 1));
192 ReplaceInput(index, new_to);
196 void Node::InsertInputs(Zone* zone,
int index,
int count) {
197 DCHECK_NOT_NULL(zone);
200 DCHECK_LT(index, InputCount());
201 for (
int i = 0;
i < count;
i++) {
202 AppendInput(zone, InputAt(Max(InputCount() - count, 0)));
204 for (
int i = InputCount() - count - 1;
i >= Max(index, count); --
i) {
205 ReplaceInput(
i, InputAt(
i - count));
207 for (
int i = 0;
i < count;
i++) {
208 ReplaceInput(index +
i,
nullptr);
213 void Node::RemoveInput(
int index) {
215 DCHECK_LT(index, InputCount());
216 for (; index < InputCount() - 1; ++index) {
217 ReplaceInput(index, InputAt(index + 1));
219 TrimInputCount(InputCount() - 1);
224 void Node::ClearInputs(
int start,
int count) {
225 Node** input_ptr = GetInputPtr(start);
226 Use* use_ptr = GetUsePtr(start);
227 while (count-- > 0) {
228 DCHECK_EQ(input_ptr, use_ptr->input_ptr());
229 Node* input = *input_ptr;
230 *input_ptr =
nullptr;
231 if (input) input->RemoveUse(use_ptr);
239 void Node::NullAllInputs() { ClearInputs(0, InputCount()); }
242 void Node::TrimInputCount(
int new_input_count) {
243 int current_count = InputCount();
244 DCHECK_LE(new_input_count, current_count);
245 if (new_input_count == current_count)
return;
246 ClearInputs(new_input_count, current_count - new_input_count);
247 if (has_inline_inputs()) {
248 bit_field_ = InlineCountField::update(bit_field_, new_input_count);
250 inputs_.outline_->count_ = new_input_count;
255 int Node::UseCount()
const {
257 for (
const Use* use = first_use_; use; use = use->next) {
264 void Node::ReplaceUses(Node* that) {
265 DCHECK(this->first_use_ ==
nullptr || this->first_use_->prev ==
nullptr);
266 DCHECK(that->first_use_ ==
nullptr || that->first_use_->prev ==
nullptr);
269 Use* last_use =
nullptr;
270 for (Use* use = this->first_use_; use; use = use->next) {
271 *use->input_ptr() = that;
276 last_use->next = that->first_use_;
277 if (that->first_use_) that->first_use_->prev = last_use;
278 that->first_use_ = this->first_use_;
280 first_use_ =
nullptr;
284 bool Node::OwnedBy(Node
const* owner1, Node
const* owner2)
const {
286 for (Use* use = first_use_; use; use = use->next) {
287 Node* from = use->from();
288 if (from == owner1) {
290 }
else if (from == owner2) {
299 void Node::Print()
const {
301 os << *
this << std::endl;
302 for (Node* input : this->inputs()) {
303 os <<
" " << *input << std::endl;
307 std::ostream& operator<<(std::ostream& os,
const Node& n) {
308 os << n.id() <<
": " << *n.op();
309 if (n.InputCount() > 0) {
311 for (
int i = 0;
i < n.InputCount(); ++
i) {
312 if (
i != 0) os <<
", ";
314 os << n.InputAt(
i)->id();
324 Node::Node(NodeId
id,
const Operator* op,
int inline_count,
int inline_capacity)
327 bit_field_(IdField::encode(id) | InlineCountField::encode(inline_count) |
328 InlineCapacityField::encode(inline_capacity)),
329 first_use_(nullptr) {
331 DCHECK_GE(kMaxInlineCapacity, inline_capacity);
332 DCHECK(inline_count == kOutlineMarker || inline_count <= inline_capacity);
336 void Node::AppendUse(Use* use) {
337 DCHECK(first_use_ ==
nullptr || first_use_->prev ==
nullptr);
338 DCHECK_EQ(
this, *use->input_ptr());
339 use->next = first_use_;
341 if (first_use_) first_use_->prev = use;
346 void Node::RemoveUse(Use* use) {
347 DCHECK(first_use_ ==
nullptr || first_use_->prev ==
nullptr);
349 DCHECK_NE(first_use_, use);
350 use->prev->next = use->next;
352 DCHECK_EQ(first_use_, use);
353 first_use_ = use->next;
356 use->next->prev = use->prev;
362 void Node::Verify() {
365 int count = this->InputCount();
368 if (count > 200 && count % 100)
return;
370 for (
int i = 0;
i < count;
i++) {
371 DCHECK_EQ(
i, this->GetUsePtr(
i)->input_index());
372 DCHECK_EQ(this->GetInputPtr(
i), this->GetUsePtr(
i)->input_ptr());
373 DCHECK_EQ(count, this->InputCount());
377 for (Node* input : this->inputs()) {
378 DCHECK_EQ(this->InputAt(index), input);
381 DCHECK_EQ(count, index);
382 DCHECK_EQ(this->InputCount(), index);
386 for (Edge edge : this->input_edges()) {
387 DCHECK_EQ(edge.from(),
this);
388 DCHECK_EQ(index, edge.index());
389 DCHECK_EQ(this->InputAt(index), edge.to());
392 DCHECK_EQ(count, index);
393 DCHECK_EQ(this->InputCount(), index);
398 Node::InputEdges::iterator Node::InputEdges::iterator::operator++(
int n) {
399 iterator result(*
this);
405 Node::Inputs::const_iterator Node::Inputs::const_iterator::operator++(
int n) {
406 const_iterator result(*
this);
412 Node::UseEdges::iterator Node::UseEdges::iterator::operator++(
int n) {
413 iterator result(*
this);
419 bool Node::UseEdges::empty()
const {
return begin() == end(); }
422 Node::Uses::const_iterator Node::Uses::const_iterator::operator++(
int n) {
423 const_iterator result(*
this);
429 bool Node::Uses::empty()
const {
return begin() == end(); }