LCOV - code coverage report
Current view: top level - src/compiler - node.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 163 185 88.1 %
Date: 2019-01-20 Functions: 23 29 79.3 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/node.h"
       6             : 
       7             : namespace v8 {
       8             : namespace internal {
       9             : namespace compiler {
      10             : 
      11    11757732 : Node::OutOfLineInputs* Node::OutOfLineInputs::New(Zone* zone, int capacity) {
      12             :   size_t size =
      13    11757732 :       sizeof(OutOfLineInputs) + capacity * (sizeof(Node*) + sizeof(Use));
      14    11757732 :   intptr_t raw_buffer = reinterpret_cast<intptr_t>(zone->New(size));
      15             :   Node::OutOfLineInputs* outline =
      16    11757753 :       reinterpret_cast<OutOfLineInputs*>(raw_buffer + capacity * sizeof(Use));
      17    11757753 :   outline->capacity_ = capacity;
      18    11757753 :   outline->count_ = 0;
      19    11757753 :   return outline;
      20             : }
      21             : 
      22             : 
      23    11721383 : void Node::OutOfLineInputs::ExtractFrom(Use* old_use_ptr, Node** old_input_ptr,
      24             :                                         int count) {
      25             :   // Extract the inputs from the old use and input pointers and copy them
      26             :   // to this out-of-line-storage.
      27    11721383 :   Use* new_use_ptr = reinterpret_cast<Use*>(this) - 1;
      28    11721383 :   Node** new_input_ptr = inputs_;
      29    49143105 :   for (int current = 0; current < count; current++) {
      30             :     new_use_ptr->bit_field_ =
      31    74843444 :         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    37421722 :     Node* old_to = *old_input_ptr;
      35    37421722 :     if (old_to) {
      36    37421722 :       *old_input_ptr = nullptr;
      37             :       old_to->RemoveUse(old_use_ptr);
      38    37421722 :       *new_input_ptr = old_to;
      39             :       old_to->AppendUse(new_use_ptr);
      40             :     } else {
      41           0 :       *new_input_ptr = nullptr;
      42             :     }
      43    37421722 :     old_input_ptr++;
      44    37421722 :     new_input_ptr++;
      45    37421722 :     old_use_ptr--;
      46    37421722 :     new_use_ptr--;
      47             :   }
      48    11721383 :   this->count_ = count;
      49    11721383 : }
      50             : 
      51             : 
      52   150035723 : Node* Node::New(Zone* zone, NodeId id, const Operator* op, int input_count,
      53             :                 Node* const* inputs, bool has_extensible_inputs) {
      54             :   Node** input_ptr;
      55             :   Use* use_ptr;
      56             :   Node* node;
      57             :   bool is_inline;
      58             : 
      59             : #if DEBUG
      60             :   // Verify that none of the inputs are {nullptr}.
      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),
      64             :             op->mnemonic(), i);
      65             :     }
      66             :   }
      67             : #endif
      68             : 
      69   150035723 :   if (input_count > kMaxInlineCapacity) {
      70             :     // Allocate out-of-line inputs.
      71             :     int capacity =
      72       36359 :         has_extensible_inputs ? input_count + kMaxInlineCapacity : input_count;
      73       36359 :     OutOfLineInputs* outline = OutOfLineInputs::New(zone, capacity);
      74             : 
      75             :     // Allocate node.
      76       36359 :     void* node_buffer = zone->New(sizeof(Node));
      77             :     node = new (node_buffer) Node(id, op, kOutlineMarker, 0);
      78       44754 :     node->inputs_.outline_ = outline;
      79             : 
      80       44754 :     outline->node_ = node;
      81       44754 :     outline->count_ = input_count;
      82             : 
      83       44754 :     input_ptr = outline->inputs_;
      84             :     use_ptr = reinterpret_cast<Use*>(outline);
      85             :     is_inline = false;
      86             :   } else {
      87             :     // Allocate node with inline inputs.
      88             :     int capacity = input_count;
      89   149999364 :     if (has_extensible_inputs) {
      90     1232665 :       const int max = kMaxInlineCapacity;
      91     2465330 :       capacity = std::min(input_count + 3, max);
      92             :     }
      93             : 
      94   149999364 :     size_t size = sizeof(Node) + capacity * (sizeof(Node*) + sizeof(Use));
      95   149999364 :     intptr_t raw_buffer = reinterpret_cast<intptr_t>(zone->New(size));
      96             :     void* node_buffer =
      97   149994662 :         reinterpret_cast<void*>(raw_buffer + capacity * sizeof(Use));
      98             : 
      99             :     node = new (node_buffer) Node(id, op, input_count, capacity);
     100   149994662 :     input_ptr = node->inputs_.inline_;
     101             :     use_ptr = reinterpret_cast<Use*>(node);
     102             :     is_inline = true;
     103             :   }
     104             : 
     105             :   // Initialize the input pointers and the uses.
     106   416436004 :   for (int current = 0; current < input_count; ++current) {
     107   266396588 :     Node* to = *inputs++;
     108   266396588 :     input_ptr[current] = to;
     109   266396588 :     Use* use = use_ptr - 1 - current;
     110   532793176 :     use->bit_field_ = Use::InputIndexField::encode(current) |
     111   266396588 :                       Use::InlineField::encode(is_inline);
     112             :     to->AppendUse(use);
     113             :   }
     114             :   node->Verify();
     115   150039416 :   return node;
     116             : }
     117             : 
     118             : 
     119     4746998 : 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     2373499 :                                   : node->inputs_.outline_->inputs_;
     124     2373499 :   Node* const clone = New(zone, id, node->op(), input_count, inputs, false);
     125             :   clone->set_type(node->type());
     126     2373496 :   return clone;
     127             : }
     128             : 
     129             : 
     130    12817964 : void Node::Kill() {
     131             :   DCHECK_NOT_NULL(op());
     132    12817964 :   NullAllInputs();
     133             :   DCHECK(uses().empty());
     134    12818182 : }
     135             : 
     136             : 
     137    24361189 : void Node::AppendInput(Zone* zone, Node* new_to) {
     138             :   DCHECK_NOT_NULL(zone);
     139             :   DCHECK_NOT_NULL(new_to);
     140             : 
     141    48722378 :   int inline_count = InlineCountField::decode(bit_field_);
     142    24361189 :   int inline_capacity = InlineCapacityField::decode(bit_field_);
     143    24361189 :   if (inline_count < inline_capacity) {
     144             :     // Append inline input.
     145     2236014 :     bit_field_ = InlineCountField::update(bit_field_, inline_count + 1);
     146     1118007 :     *GetInputPtr(inline_count) = new_to;
     147             :     Use* use = GetUsePtr(inline_count);
     148     1118007 :     use->bit_field_ = Use::InputIndexField::encode(inline_count) |
     149     1118007 :                       Use::InlineField::encode(true);
     150             :     new_to->AppendUse(use);
     151             :   } else {
     152             :     // Append out-of-line input.
     153             :     int input_count = InputCount();
     154             :     OutOfLineInputs* outline = nullptr;
     155    23243182 :     if (inline_count != kOutlineMarker) {
     156             :       // switch to out of line inputs.
     157    11573441 :       outline = OutOfLineInputs::New(zone, input_count * 2 + 3);
     158    11573443 :       outline->node_ = this;
     159    11573443 :       outline->ExtractFrom(GetUsePtr(0), GetInputPtr(0), input_count);
     160    23146906 :       bit_field_ = InlineCountField::update(bit_field_, kOutlineMarker);
     161    11573453 :       inputs_.outline_ = outline;
     162             :     } else {
     163             :       // use current out of line inputs.
     164    11669741 :       outline = inputs_.outline_;
     165    11669741 :       if (input_count >= outline->capacity_) {
     166             :         // out of space in out-of-line inputs.
     167      147931 :         outline = OutOfLineInputs::New(zone, input_count * 2 + 3);
     168      147931 :         outline->node_ = this;
     169      147931 :         outline->ExtractFrom(GetUsePtr(0), GetInputPtr(0), input_count);
     170      147931 :         inputs_.outline_ = outline;
     171             :       }
     172             :     }
     173    23243194 :     outline->count_++;
     174    23243194 :     *GetInputPtr(input_count) = new_to;
     175             :     Use* use = GetUsePtr(input_count);
     176    23243194 :     use->bit_field_ = Use::InputIndexField::encode(input_count) |
     177    23243194 :                       Use::InlineField::encode(false);
     178             :     new_to->AppendUse(use);
     179             :   }
     180             :   Verify();
     181    24361201 : }
     182             : 
     183             : 
     184    12960046 : void Node::InsertInput(Zone* zone, int index, Node* new_to) {
     185             :   DCHECK_NOT_NULL(zone);
     186             :   DCHECK_LE(0, index);
     187             :   DCHECK_LT(index, InputCount());
     188    25920092 :   AppendInput(zone, InputAt(InputCount() - 1));
     189    76447561 :   for (int i = InputCount() - 1; i > index; --i) {
     190   101054962 :     ReplaceInput(i, InputAt(i - 1));
     191             :   }
     192    12960060 :   ReplaceInput(index, new_to);
     193             :   Verify();
     194    12960064 : }
     195             : 
     196         496 : void Node::InsertInputs(Zone* zone, int index, int count) {
     197             :   DCHECK_NOT_NULL(zone);
     198             :   DCHECK_LE(0, index);
     199             :   DCHECK_LT(0, count);
     200             :   DCHECK_LT(index, InputCount());
     201        1493 :   for (int i = 0; i < count; i++) {
     202        1994 :     AppendInput(zone, InputAt(Max(InputCount() - count, 0)));
     203             :   }
     204        4660 :   for (int i = InputCount() - count - 1; i >= Max(index, count); --i) {
     205        3668 :     ReplaceInput(i, InputAt(i - count));
     206             :   }
     207         997 :   for (int i = 0; i < count; i++) {
     208         997 :     ReplaceInput(index + i, nullptr);
     209             :   }
     210             :   Verify();
     211         496 : }
     212             : 
     213      581434 : void Node::RemoveInput(int index) {
     214             :   DCHECK_LE(0, index);
     215             :   DCHECK_LT(index, InputCount());
     216     1442593 :   for (; index < InputCount() - 1; ++index) {
     217      559442 :     ReplaceInput(index, InputAt(index + 1));
     218             :   }
     219      581438 :   TrimInputCount(InputCount() - 1);
     220             :   Verify();
     221      581438 : }
     222             : 
     223             : 
     224    15947573 : void Node::ClearInputs(int start, int count) {
     225             :   Node** input_ptr = GetInputPtr(start);
     226             :   Use* use_ptr = GetUsePtr(start);
     227    64452399 :   while (count-- > 0) {
     228             :     DCHECK_EQ(input_ptr, use_ptr->input_ptr());
     229    32557253 :     Node* input = *input_ptr;
     230    32557253 :     *input_ptr = nullptr;
     231    32557253 :     if (input) input->RemoveUse(use_ptr);
     232    32557253 :     input_ptr++;
     233    32557253 :     use_ptr--;
     234             :   }
     235             :   Verify();
     236    15947573 : }
     237             : 
     238             : 
     239    28503054 : void Node::NullAllInputs() { ClearInputs(0, InputCount()); }
     240             : 
     241             : 
     242     3481602 : void Node::TrimInputCount(int new_input_count) {
     243             :   int current_count = InputCount();
     244             :   DCHECK_LE(new_input_count, current_count);
     245     3570974 :   if (new_input_count == current_count) return;  // Nothing to do.
     246     1696109 :   ClearInputs(new_input_count, current_count - new_input_count);
     247     1696121 :   if (has_inline_inputs()) {
     248     1996110 :     bit_field_ = InlineCountField::update(bit_field_, new_input_count);
     249             :   } else {
     250      698066 :     inputs_.outline_->count_ = new_input_count;
     251             :   }
     252             : }
     253             : 
     254             : 
     255       87142 : int Node::UseCount() const {
     256             :   int use_count = 0;
     257       96253 :   for (const Use* use = first_use_; use; use = use->next) {
     258        9111 :     ++use_count;
     259             :   }
     260       87142 :   return use_count;
     261             : }
     262             : 
     263             : 
     264     6254687 : 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);
     267             : 
     268             :   // Update the pointers to {this} to point to {that}.
     269             :   Use* last_use = nullptr;
     270    15078260 :   for (Use* use = this->first_use_; use; use = use->next) {
     271     8823573 :     *use->input_ptr() = that;
     272             :     last_use = use;
     273             :   }
     274     6254687 :   if (last_use) {
     275             :     // Concat the use list of {this} and {that}.
     276     4695281 :     last_use->next = that->first_use_;
     277     4695281 :     if (that->first_use_) that->first_use_->prev = last_use;
     278     4695281 :     that->first_use_ = this->first_use_;
     279             :   }
     280     6254687 :   first_use_ = nullptr;
     281     6254687 : }
     282             : 
     283             : 
     284       82489 : bool Node::OwnedBy(Node const* owner1, Node const* owner2) const {
     285             :   unsigned mask = 0;
     286      241356 :   for (Use* use = first_use_; use; use = use->next) {
     287             :     Node* from = use->from();
     288      226071 :     if (from == owner1) {
     289       80020 :       mask |= 1;
     290      146051 :     } else if (from == owner2) {
     291       78847 :       mask |= 2;
     292             :     } else {
     293             :       return false;
     294             :     }
     295             :   }
     296       15285 :   return mask == 3;
     297             : }
     298             : 
     299           0 : void Node::Print() const {
     300           0 :   StdoutStream os;
     301           0 :   Print(os);
     302           0 : }
     303             : 
     304           0 : void Node::Print(std::ostream& os) const {
     305           0 :   os << *this << std::endl;
     306           0 :   for (Node* input : this->inputs()) {
     307           0 :     os << "  " << *input << std::endl;
     308             :   }
     309           0 : }
     310             : 
     311         394 : std::ostream& operator<<(std::ostream& os, const Node& n) {
     312         394 :   os << n.id() << ": " << *n.op();
     313         394 :   if (n.InputCount() > 0) {
     314         296 :     os << "(";
     315        1926 :     for (int i = 0; i < n.InputCount(); ++i) {
     316         667 :       if (i != 0) os << ", ";
     317         667 :       if (n.InputAt(i)) {
     318         667 :         os << n.InputAt(i)->id();
     319             :       } else {
     320           0 :         os << "null";
     321             :       }
     322             :     }
     323         296 :     os << ")";
     324             :   }
     325         394 :   return os;
     326             : }
     327             : 
     328           0 : Node::Node(NodeId id, const Operator* op, int inline_count, int inline_capacity)
     329             :     : op_(op),
     330             :       mark_(0),
     331   450028740 :       bit_field_(IdField::encode(id) | InlineCountField::encode(inline_count) |
     332   149994662 :                  InlineCapacityField::encode(inline_capacity)),
     333   450118248 :       first_use_(nullptr) {
     334             :   // Inputs must either be out of line or within the inline capacity.
     335             :   DCHECK_GE(kMaxInlineCapacity, inline_capacity);
     336             :   DCHECK(inline_count == kOutlineMarker || inline_count <= inline_capacity);
     337           0 : }
     338             : 
     339             : 
     340    78900793 : void Node::AppendUse(Use* use) {
     341             :   DCHECK(first_use_ == nullptr || first_use_->prev == nullptr);
     342             :   DCHECK_EQ(this, *use->input_ptr());
     343   456693183 :   use->next = first_use_;
     344   456693183 :   use->prev = nullptr;
     345   456693183 :   if (first_use_) first_use_->prev = use;
     346   456693183 :   first_use_ = use;
     347    78900793 : }
     348             : 
     349             : 
     350   124538734 : void Node::RemoveUse(Use* use) {
     351             :   DCHECK(first_use_ == nullptr || first_use_->prev == nullptr);
     352   243641814 :   if (use->prev) {
     353             :     DCHECK_NE(first_use_, use);
     354   155507031 :     use->prev->next = use->next;
     355             :   } else {
     356             :     DCHECK_EQ(first_use_, use);
     357    88134783 :     first_use_ = use->next;
     358             :   }
     359   243641814 :   if (use->next) {
     360   150526053 :     use->next->prev = use->prev;
     361             :   }
     362   124538734 : }
     363             : 
     364             : 
     365             : #if DEBUG
     366             : void Node::Verify() {
     367             :   // Check basic sanity of input data structures.
     368             :   fflush(stdout);
     369             :   int count = this->InputCount();
     370             :   // Avoid quadratic explosion for mega nodes; only verify if the input
     371             :   // count is less than 200 or is a round number of 100s.
     372             :   if (count > 200 && count % 100) return;
     373             : 
     374             :   for (int i = 0; i < count; i++) {
     375             :     DCHECK_EQ(i, this->GetUsePtr(i)->input_index());
     376             :     DCHECK_EQ(this->GetInputPtr(i), this->GetUsePtr(i)->input_ptr());
     377             :     DCHECK_EQ(count, this->InputCount());
     378             :   }
     379             :   {  // Direct input iteration.
     380             :     int index = 0;
     381             :     for (Node* input : this->inputs()) {
     382             :       DCHECK_EQ(this->InputAt(index), input);
     383             :       index++;
     384             :     }
     385             :     DCHECK_EQ(count, index);
     386             :     DCHECK_EQ(this->InputCount(), index);
     387             :   }
     388             :   {  // Input edge iteration.
     389             :     int index = 0;
     390             :     for (Edge edge : this->input_edges()) {
     391             :       DCHECK_EQ(edge.from(), this);
     392             :       DCHECK_EQ(index, edge.index());
     393             :       DCHECK_EQ(this->InputAt(index), edge.to());
     394             :       index++;
     395             :     }
     396             :     DCHECK_EQ(count, index);
     397             :     DCHECK_EQ(this->InputCount(), index);
     398             :   }
     399             : }
     400             : #endif
     401             : 
     402           0 : Node::InputEdges::iterator Node::InputEdges::iterator::operator++(int n) {
     403           0 :   iterator result(*this);
     404             :   ++(*this);
     405           0 :   return result;
     406             : }
     407             : 
     408             : 
     409           0 : Node::Inputs::const_iterator Node::Inputs::const_iterator::operator++(int n) {
     410           0 :   const_iterator result(*this);
     411             :   ++(*this);
     412           0 :   return result;
     413             : }
     414             : 
     415             : 
     416           0 : Node::UseEdges::iterator Node::UseEdges::iterator::operator++(int n) {
     417           0 :   iterator result(*this);
     418             :   ++(*this);
     419           0 :   return result;
     420             : }
     421             : 
     422             : 
     423       37576 : bool Node::UseEdges::empty() const { return begin() == end(); }
     424             : 
     425             : 
     426      177399 : Node::Uses::const_iterator Node::Uses::const_iterator::operator++(int n) {
     427      177399 :   const_iterator result(*this);
     428             :   ++(*this);
     429      177399 :   return result;
     430             : }
     431             : 
     432             : 
     433     2915856 : bool Node::Uses::empty() const { return begin() == end(); }
     434             : 
     435             : }  // namespace compiler
     436             : }  // namespace internal
     437      183867 : }  // namespace v8

Generated by: LCOV version 1.10