LCOV - code coverage report
Current view: top level - src/compiler - load-elimination.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 437 499 87.6 %
Date: 2017-04-26 Functions: 40 55 72.7 %

          Line data    Source code
       1             : // Copyright 2016 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/load-elimination.h"
       6             : 
       7             : #include "src/compiler/common-operator.h"
       8             : #include "src/compiler/js-graph.h"
       9             : #include "src/compiler/node-properties.h"
      10             : #include "src/compiler/simplified-operator.h"
      11             : #include "src/factory.h"
      12             : #include "src/objects-inl.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : namespace compiler {
      17             : 
      18             : namespace {
      19             : 
      20             : enum Aliasing { kNoAlias, kMayAlias, kMustAlias };
      21             : 
      22     7794442 : Aliasing QueryAlias(Node* a, Node* b) {
      23     5725178 :   if (a == b) return kMustAlias;
      24     2713360 :   if (!NodeProperties::GetType(a)->Maybe(NodeProperties::GetType(b))) {
      25             :     return kNoAlias;
      26             :   }
      27     1008923 :   switch (b->opcode()) {
      28             :     case IrOpcode::kAllocate: {
      29      653549 :       switch (a->opcode()) {
      30             :         case IrOpcode::kAllocate:
      31             :         case IrOpcode::kHeapConstant:
      32             :         case IrOpcode::kParameter:
      33             :           return kNoAlias;
      34             :         default:
      35             :           break;
      36             :       }
      37             :       break;
      38             :     }
      39             :     case IrOpcode::kFinishRegion:
      40             :     case IrOpcode::kTypeGuard:
      41       38153 :       return QueryAlias(a, b->InputAt(0));
      42             :     default:
      43             :       break;
      44             :   }
      45      717142 :   switch (a->opcode()) {
      46             :     case IrOpcode::kAllocate: {
      47       40629 :       switch (b->opcode()) {
      48             :         case IrOpcode::kHeapConstant:
      49             :         case IrOpcode::kParameter:
      50             :           return kNoAlias;
      51             :         default:
      52             :           break;
      53             :       }
      54             :       break;
      55             :     }
      56             :     case IrOpcode::kFinishRegion:
      57             :     case IrOpcode::kTypeGuard:
      58      272197 :       return QueryAlias(a->InputAt(0), b);
      59             :     default:
      60             :       break;
      61             :   }
      62      425295 :   return kMayAlias;
      63             : }
      64             : 
      65     2296273 : bool MayAlias(Node* a, Node* b) { return QueryAlias(a, b) != kNoAlias; }
      66             : 
      67     3118555 : bool MustAlias(Node* a, Node* b) { return QueryAlias(a, b) == kMustAlias; }
      68             : 
      69             : }  // namespace
      70             : 
      71    70936298 : Reduction LoadElimination::Reduce(Node* node) {
      72    35468149 :   if (FLAG_trace_turbo_load_elimination) {
      73           0 :     if (node->op()->EffectInputCount() > 0) {
      74           0 :       PrintF(" visit #%d:%s", node->id(), node->op()->mnemonic());
      75           0 :       if (node->op()->ValueInputCount() > 0) {
      76           0 :         PrintF("(");
      77           0 :         for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
      78           0 :           if (i > 0) PrintF(", ");
      79           0 :           Node* const value = NodeProperties::GetValueInput(node, i);
      80           0 :           PrintF("#%d:%s", value->id(), value->op()->mnemonic());
      81             :         }
      82           0 :         PrintF(")");
      83             :       }
      84           0 :       PrintF("\n");
      85           0 :       for (int i = 0; i < node->op()->EffectInputCount(); ++i) {
      86           0 :         Node* const effect = NodeProperties::GetEffectInput(node, i);
      87           0 :         if (AbstractState const* const state = node_states_.Get(effect)) {
      88             :           PrintF("  state[%i]: #%d:%s\n", i, effect->id(),
      89           0 :                  effect->op()->mnemonic());
      90           0 :           state->Print();
      91             :         } else {
      92             :           PrintF("  no state[%i]: #%d:%s\n", i, effect->id(),
      93           0 :                  effect->op()->mnemonic());
      94             :         }
      95             :       }
      96             :     }
      97             :   }
      98    35468149 :   switch (node->opcode()) {
      99             :     case IrOpcode::kArrayBufferWasNeutered:
     100         636 :       return ReduceArrayBufferWasNeutered(node);
     101             :     case IrOpcode::kCheckMaps:
     102      138591 :       return ReduceCheckMaps(node);
     103             :     case IrOpcode::kEnsureWritableFastElements:
     104         212 :       return ReduceEnsureWritableFastElements(node);
     105             :     case IrOpcode::kMaybeGrowFastElements:
     106        3217 :       return ReduceMaybeGrowFastElements(node);
     107             :     case IrOpcode::kTransitionElementsKind:
     108         667 :       return ReduceTransitionElementsKind(node);
     109             :     case IrOpcode::kLoadField:
     110     1427468 :       return ReduceLoadField(node);
     111             :     case IrOpcode::kStoreField:
     112     1344908 :       return ReduceStoreField(node);
     113             :     case IrOpcode::kLoadElement:
     114       56448 :       return ReduceLoadElement(node);
     115             :     case IrOpcode::kStoreElement:
     116      180680 :       return ReduceStoreElement(node);
     117             :     case IrOpcode::kStoreTypedElement:
     118        4921 :       return ReduceStoreTypedElement(node);
     119             :     case IrOpcode::kEffectPhi:
     120      956620 :       return ReduceEffectPhi(node);
     121             :     case IrOpcode::kDead:
     122             :       break;
     123             :     case IrOpcode::kStart:
     124             :       return ReduceStart(node);
     125             :     default:
     126    30955400 :       return ReduceOtherNode(node);
     127             :   }
     128             :   return NoChange();
     129             : }
     130             : 
     131             : namespace {
     132             : 
     133          41 : bool IsCompatibleCheck(Node const* a, Node const* b) {
     134          41 :   if (a->op() != b->op()) return false;
     135         140 :   for (int i = a->op()->ValueInputCount(); --i >= 0;) {
     136          41 :     if (!MustAlias(a->InputAt(i), b->InputAt(i))) return false;
     137             :   }
     138             :   return true;
     139             : }
     140             : 
     141             : }  // namespace
     142             : 
     143         149 : Node* LoadElimination::AbstractChecks::Lookup(Node* node) const {
     144        1205 :   for (Node* const check : nodes_) {
     145        1073 :     if (check && IsCompatibleCheck(check, node)) {
     146             :       return check;
     147             :     }
     148             :   }
     149             :   return nullptr;
     150             : }
     151             : 
     152         627 : bool LoadElimination::AbstractChecks::Equals(AbstractChecks const* that) const {
     153         627 :   if (this == that) return true;
     154        1248 :   for (size_t i = 0; i < arraysize(nodes_); ++i) {
     155        1449 :     if (Node* this_node = this->nodes_[i]) {
     156        1615 :       for (size_t j = 0;; ++j) {
     157        1937 :         if (j == arraysize(nodes_)) return false;
     158        1736 :         if (that->nodes_[j] == this_node) break;
     159        1615 :       }
     160             :     }
     161             :   }
     162        1150 :   for (size_t i = 0; i < arraysize(nodes_); ++i) {
     163        1164 :     if (Node* that_node = that->nodes_[i]) {
     164         119 :       for (size_t j = 0;; ++j) {
     165         254 :         if (j == arraysize(nodes_)) return false;
     166         240 :         if (this->nodes_[j] == that_node) break;
     167         119 :       }
     168             :     }
     169             :   }
     170             :   return true;
     171             : }
     172             : 
     173         263 : LoadElimination::AbstractChecks const* LoadElimination::AbstractChecks::Merge(
     174             :     AbstractChecks const* that, Zone* zone) const {
     175         263 :   if (this->Equals(that)) return this;
     176             :   AbstractChecks* copy = new (zone) AbstractChecks(zone);
     177        1935 :   for (Node* const this_node : this->nodes_) {
     178        1720 :     if (this_node == nullptr) continue;
     179        1823 :     for (Node* const that_node : that->nodes_) {
     180        1622 :       if (this_node == that_node) {
     181          14 :         copy->nodes_[copy->next_index_++] = this_node;
     182          14 :         break;
     183             :       }
     184             :     }
     185             :   }
     186         215 :   copy->next_index_ %= arraysize(nodes_);
     187         215 :   return copy;
     188             : }
     189             : 
     190           0 : void LoadElimination::AbstractChecks::Print() const {
     191           0 :   for (Node* const node : nodes_) {
     192           0 :     if (node != nullptr) {
     193           0 :       PrintF("    #%d:%s\n", node->id(), node->op()->mnemonic());
     194             :     }
     195             :   }
     196           0 : }
     197             : 
     198      165637 : Node* LoadElimination::AbstractElements::Lookup(Node* object,
     199             :                                                 Node* index) const {
     200     1478216 :   for (Element const element : elements_) {
     201     1314253 :     if (element.object == nullptr) continue;
     202             :     DCHECK_NOT_NULL(element.index);
     203             :     DCHECK_NOT_NULL(element.value);
     204     2317669 :     if (MustAlias(object, element.object) && MustAlias(index, element.index)) {
     205             :       return element.value;
     206             :     }
     207             :   }
     208             :   return nullptr;
     209             : }
     210             : 
     211             : LoadElimination::AbstractElements const*
     212      159590 : LoadElimination::AbstractElements::Kill(Node* object, Node* index,
     213             :                                         Zone* zone) const {
     214      183427 :   for (Element const element : this->elements_) {
     215      180611 :     if (element.object == nullptr) continue;
     216      158939 :     if (MayAlias(object, element.object)) {
     217             :       AbstractElements* that = new (zone) AbstractElements(zone);
     218     2508384 :       for (Element const element : this->elements_) {
     219     1254192 :         if (element.object == nullptr) continue;
     220             :         DCHECK_NOT_NULL(element.index);
     221             :         DCHECK_NOT_NULL(element.value);
     222     2297841 :         if (!MayAlias(object, element.object) ||
     223             :             !NodeProperties::GetType(index)->Maybe(
     224     1147932 :                 NodeProperties::GetType(element.index))) {
     225     1137898 :           that->elements_[that->next_index_++] = element;
     226             :         }
     227             :       }
     228      156774 :       that->next_index_ %= arraysize(elements_);
     229             :       return that;
     230             :     }
     231             :   }
     232        2816 :   return this;
     233             : }
     234             : 
     235       23000 : bool LoadElimination::AbstractElements::Equals(
     236             :     AbstractElements const* that) const {
     237       23000 :   if (this == that) return true;
     238       87014 :   for (size_t i = 0; i < arraysize(elements_); ++i) {
     239       92821 :     Element this_element = this->elements_[i];
     240       92821 :     if (this_element.object == nullptr) continue;
     241       53016 :     for (size_t j = 0;; ++j) {
     242       72412 :       if (j == arraysize(elements_)) return false;
     243       66605 :       Element that_element = that->elements_[j];
     244       66605 :       if (this_element.object == that_element.object &&
     245       13891 :           this_element.index == that_element.index &&
     246             :           this_element.value == that_element.value) {
     247             :         break;
     248             :       }
     249       53016 :     }
     250             :   }
     251       84344 :   for (size_t i = 0; i < arraysize(elements_); ++i) {
     252       84683 :     Element that_element = that->elements_[i];
     253       84683 :     if (that_element.object == nullptr) continue;
     254        9038 :     for (size_t j = 0;; ++j) {
     255       22414 :       if (j == arraysize(elements_)) return false;
     256       22075 :       Element this_element = this->elements_[j];
     257       22075 :       if (that_element.object == this_element.object &&
     258       13037 :           that_element.index == this_element.index &&
     259             :           that_element.value == this_element.value) {
     260             :         break;
     261             :       }
     262        9038 :     }
     263             :   }
     264             :   return true;
     265             : }
     266             : 
     267             : LoadElimination::AbstractElements const*
     268       10037 : LoadElimination::AbstractElements::Merge(AbstractElements const* that,
     269             :                                          Zone* zone) const {
     270       10037 :   if (this->Equals(that)) return this;
     271             :   AbstractElements* copy = new (zone) AbstractElements(zone);
     272       53037 :   for (Element const this_element : this->elements_) {
     273       47144 :     if (this_element.object == nullptr) continue;
     274       57438 :     for (Element const that_element : that->elements_) {
     275       51230 :       if (this_element.object == that_element.object &&
     276        1220 :           this_element.index == that_element.index &&
     277             :           this_element.value == that_element.value) {
     278         918 :         copy->elements_[copy->next_index_++] = this_element;
     279         918 :         break;
     280             :       }
     281             :     }
     282             :   }
     283        5893 :   copy->next_index_ %= arraysize(elements_);
     284        5893 :   return copy;
     285             : }
     286             : 
     287           0 : void LoadElimination::AbstractElements::Print() const {
     288           0 :   for (Element const& element : elements_) {
     289           0 :     if (element.object) {
     290             :       PrintF("    #%d:%s @ #%d:%s -> #%d:%s\n", element.object->id(),
     291             :              element.object->op()->mnemonic(), element.index->id(),
     292             :              element.index->op()->mnemonic(), element.value->id(),
     293           0 :              element.value->op()->mnemonic());
     294             :     }
     295             :   }
     296           0 : }
     297             : 
     298      616978 : Node* LoadElimination::AbstractField::Lookup(Node* object) const {
     299     1703745 :   for (auto pair : info_for_node_) {
     300      713689 :     if (MustAlias(object, pair.first)) return pair.second;
     301             :   }
     302             :   return nullptr;
     303             : }
     304             : 
     305     1081140 : LoadElimination::AbstractField const* LoadElimination::AbstractField::Kill(
     306             :     Node* object, Zone* zone) const {
     307     2450425 :   for (auto pair : this->info_for_node_) {
     308      541688 :     if (MayAlias(object, pair.first)) {
     309             :       AbstractField* that = new (zone) AbstractField(zone);
     310      874339 :       for (auto pair : this->info_for_node_) {
     311      734506 :         if (!MayAlias(object, pair.first)) that->info_for_node_.insert(pair);
     312             :       }
     313             :       return that;
     314             :     }
     315             :   }
     316             :   return this;
     317             : }
     318             : 
     319           0 : void LoadElimination::AbstractField::Print() const {
     320           0 :   for (auto pair : info_for_node_) {
     321             :     PrintF("    #%d:%s -> #%d:%s\n", pair.first->id(),
     322             :            pair.first->op()->mnemonic(), pair.second->id(),
     323           0 :            pair.second->op()->mnemonic());
     324             :   }
     325           0 : }
     326             : 
     327       58580 : bool LoadElimination::AbstractMaps::Lookup(
     328             :     Node* object, ZoneHandleSet<Map>* object_maps) const {
     329      166504 :   for (auto pair : info_for_node_) {
     330       87156 :     if (MustAlias(object, pair.first)) {
     331       37812 :       *object_maps = pair.second;
     332             :       return true;
     333             :     }
     334             :   }
     335             :   return false;
     336             : }
     337             : 
     338       54411 : LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Kill(
     339             :     Node* object, Zone* zone) const {
     340      169122 :   for (auto pair : this->info_for_node_) {
     341       67475 :     if (MayAlias(object, pair.first)) {
     342             :       AbstractMaps* that = new (zone) AbstractMaps(zone);
     343       25359 :       for (auto pair : this->info_for_node_) {
     344       22018 :         if (!MayAlias(object, pair.first)) that->info_for_node_.insert(pair);
     345             :       }
     346             :       return that;
     347             :     }
     348             :   }
     349             :   return this;
     350             : }
     351             : 
     352           0 : void LoadElimination::AbstractMaps::Print() const {
     353           0 :   for (auto pair : info_for_node_) {
     354           0 :     PrintF("    #%d:%s\n", pair.first->id(), pair.first->op()->mnemonic());
     355           0 :     OFStream os(stdout);
     356             :     ZoneHandleSet<Map> const& maps = pair.second;
     357           0 :     for (size_t i = 0; i < maps.size(); ++i) {
     358           0 :       os << "     - " << Brief(*maps[i]) << "\n";
     359             :     }
     360           0 :   }
     361           0 : }
     362             : 
     363      205591 : bool LoadElimination::AbstractState::Equals(AbstractState const* that) const {
     364      205591 :   if (this->checks_) {
     365         364 :     if (!that->checks_ || !that->checks_->Equals(this->checks_)) {
     366             :       return false;
     367             :     }
     368      205227 :   } else if (that->checks_) {
     369             :     return false;
     370             :   }
     371      205591 :   if (this->elements_) {
     372       12963 :     if (!that->elements_ || !that->elements_->Equals(this->elements_)) {
     373             :       return false;
     374             :     }
     375      192628 :   } else if (that->elements_) {
     376             :     return false;
     377             :   }
     378     6567599 :   for (size_t i = 0u; i < arraysize(fields_); ++i) {
     379     6567692 :     AbstractField const* this_field = this->fields_[i];
     380     6567692 :     AbstractField const* that_field = that->fields_[i];
     381     6567692 :     if (this_field) {
     382      757795 :       if (!that_field || !that_field->Equals(this_field)) return false;
     383     6188800 :     } else if (that_field) {
     384             :       return false;
     385             :     }
     386             :   }
     387      205235 :   if (this->maps_) {
     388      172816 :     if (!that->maps_ || !that->maps_->Equals(this->maps_)) {
     389             :       return false;
     390             :     }
     391      118827 :   } else if (that->maps_) {
     392             :     return false;
     393             :   }
     394             :   return true;
     395             : }
     396             : 
     397     1285986 : void LoadElimination::AbstractState::Merge(AbstractState const* that,
     398             :                                            Zone* zone) {
     399             :   // Merge the information we have about the checks.
     400     1285986 :   if (this->checks_) {
     401             :     this->checks_ =
     402         270 :         that->checks_ ? that->checks_->Merge(this->checks_, zone) : nullptr;
     403             :   }
     404             : 
     405             :   // Merge the information we have about the elements.
     406     1285986 :   if (this->elements_) {
     407             :     this->elements_ = that->elements_
     408             :                           ? that->elements_->Merge(this->elements_, zone)
     409       20609 :                           : nullptr;
     410             :   }
     411             : 
     412             :   // Merge the information we have about the fields.
     413    41151579 :   for (size_t i = 0; i < arraysize(fields_); ++i) {
     414    41151577 :     if (this->fields_[i]) {
     415      548285 :       if (that->fields_[i]) {
     416      197571 :         this->fields_[i] = this->fields_[i]->Merge(that->fields_[i], zone);
     417             :       } else {
     418      350714 :         this->fields_[i] = nullptr;
     419             :       }
     420             :     }
     421             :   }
     422             : 
     423             :   // Merge the information we have about the maps.
     424     1285988 :   if (this->maps_) {
     425       54857 :     this->maps_ = that->maps_ ? that->maps_->Merge(this->maps_, zone) : nullptr;
     426             :   }
     427     1285988 : }
     428             : 
     429           0 : Node* LoadElimination::AbstractState::LookupCheck(Node* node) const {
     430         444 :   return this->checks_ ? this->checks_->Lookup(node) : nullptr;
     431             : }
     432             : 
     433         427 : LoadElimination::AbstractState const* LoadElimination::AbstractState::AddCheck(
     434             :     Node* node, Zone* zone) const {
     435         427 :   AbstractState* that = new (zone) AbstractState(*this);
     436         427 :   if (that->checks_) {
     437         132 :     that->checks_ = that->checks_->Extend(node, zone);
     438             :   } else {
     439         295 :     that->checks_ = new (zone) AbstractChecks(node, zone);
     440             :   }
     441         427 :   return that;
     442             : }
     443             : 
     444           0 : bool LoadElimination::AbstractState::LookupMaps(
     445             :     Node* object, ZoneHandleSet<Map>* object_map) const {
     446      104162 :   return this->maps_ && this->maps_->Lookup(object, object_map);
     447             : }
     448             : 
     449      196648 : LoadElimination::AbstractState const* LoadElimination::AbstractState::AddMaps(
     450             :     Node* object, ZoneHandleSet<Map> maps, Zone* zone) const {
     451      196648 :   AbstractState* that = new (zone) AbstractState(*this);
     452      196648 :   if (that->maps_) {
     453       74989 :     that->maps_ = that->maps_->Extend(object, maps, zone);
     454             :   } else {
     455      243318 :     that->maps_ = new (zone) AbstractMaps(object, maps, zone);
     456             :   }
     457      196649 :   return that;
     458             : }
     459             : 
     460      136487 : LoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps(
     461             :     Node* object, Zone* zone) const {
     462      136487 :   if (this->maps_) {
     463       54411 :     AbstractMaps const* that_maps = this->maps_->Kill(object, zone);
     464       54411 :     if (this->maps_ != that_maps) {
     465        7175 :       AbstractState* that = new (zone) AbstractState(*this);
     466        7175 :       that->maps_ = that_maps;
     467        7175 :       return that;
     468             :     }
     469             :   }
     470      129312 :   return this;
     471             : }
     472             : 
     473           0 : Node* LoadElimination::AbstractState::LookupElement(Node* object,
     474             :                                                     Node* index) const {
     475      201346 :   if (this->elements_) {
     476      165637 :     return this->elements_->Lookup(object, index);
     477             :   }
     478             :   return nullptr;
     479             : }
     480             : 
     481             : LoadElimination::AbstractState const*
     482      200419 : LoadElimination::AbstractState::AddElement(Node* object, Node* index,
     483             :                                            Node* value, Zone* zone) const {
     484      200419 :   AbstractState* that = new (zone) AbstractState(*this);
     485      200419 :   if (that->elements_) {
     486      164960 :     that->elements_ = that->elements_->Extend(object, index, value, zone);
     487             :   } else {
     488       35459 :     that->elements_ = new (zone) AbstractElements(object, index, value, zone);
     489             :   }
     490      200419 :   return that;
     491             : }
     492             : 
     493             : LoadElimination::AbstractState const*
     494      171495 : LoadElimination::AbstractState::KillElement(Node* object, Node* index,
     495             :                                             Zone* zone) const {
     496      171495 :   if (this->elements_) {
     497             :     AbstractElements const* that_elements =
     498      159590 :         this->elements_->Kill(object, index, zone);
     499      159590 :     if (this->elements_ != that_elements) {
     500      156774 :       AbstractState* that = new (zone) AbstractState(*this);
     501      156774 :       that->elements_ = that_elements;
     502      156774 :       return that;
     503             :     }
     504             :   }
     505       14721 :   return this;
     506             : }
     507             : 
     508     1829372 : LoadElimination::AbstractState const* LoadElimination::AbstractState::AddField(
     509             :     Node* object, size_t index, Node* value, Zone* zone) const {
     510     1829373 :   AbstractState* that = new (zone) AbstractState(*this);
     511     1829373 :   if (that->fields_[index]) {
     512      488719 :     that->fields_[index] = that->fields_[index]->Extend(object, value, zone);
     513             :   } else {
     514     1340654 :     that->fields_[index] = new (zone) AbstractField(object, value, zone);
     515             :   }
     516     1829372 :   return that;
     517             : }
     518             : 
     519      913348 : LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
     520             :     Node* object, size_t index, Zone* zone) const {
     521      913348 :   if (AbstractField const* this_field = this->fields_[index]) {
     522      337385 :     this_field = this_field->Kill(object, zone);
     523      337385 :     if (this->fields_[index] != this_field) {
     524      194080 :       AbstractState* that = new (zone) AbstractState(*this);
     525      194080 :       that->fields_[index] = this_field;
     526      194080 :       return that;
     527             :     }
     528             :   }
     529      719268 :   return this;
     530             : }
     531             : 
     532             : LoadElimination::AbstractState const*
     533       92021 : LoadElimination::AbstractState::KillFields(Node* object, Zone* zone) const {
     534     2025998 :   for (size_t i = 0;; ++i) {
     535     2118019 :     if (i == arraysize(fields_)) return this;
     536     2055163 :     if (AbstractField const* this_field = this->fields_[i]) {
     537      617705 :       AbstractField const* that_field = this_field->Kill(object, zone);
     538      617705 :       if (that_field != this_field) {
     539       29165 :         AbstractState* that = new (zone) AbstractState(*this);
     540       29165 :         that->fields_[i] = that_field;
     541      947807 :         while (++i < arraysize(fields_)) {
     542      889477 :           if (this->fields_[i] != nullptr) {
     543      126050 :             that->fields_[i] = this->fields_[i]->Kill(object, zone);
     544             :           }
     545             :         }
     546             :         return that;
     547             :       }
     548             :     }
     549     2025998 :   }
     550             : }
     551             : 
     552           0 : Node* LoadElimination::AbstractState::LookupField(Node* object,
     553             :                                                   size_t index) const {
     554     1957632 :   if (AbstractField const* this_field = this->fields_[index]) {
     555      616978 :     return this_field->Lookup(object);
     556             :   }
     557             :   return nullptr;
     558             : }
     559             : 
     560           0 : void LoadElimination::AbstractState::Print() const {
     561           0 :   if (checks_) {
     562           0 :     PrintF("   checks:\n");
     563           0 :     checks_->Print();
     564             :   }
     565           0 :   if (maps_) {
     566           0 :     PrintF("   maps:\n");
     567           0 :     maps_->Print();
     568             :   }
     569           0 :   if (elements_) {
     570           0 :     PrintF("   elements:\n");
     571           0 :     elements_->Print();
     572             :   }
     573           0 :   for (size_t i = 0; i < arraysize(fields_); ++i) {
     574           0 :     if (AbstractField const* const field = fields_[i]) {
     575           0 :       PrintF("   field %zu:\n", i);
     576           0 :       field->Print();
     577             :     }
     578             :   }
     579           0 : }
     580             : 
     581             : LoadElimination::AbstractState const*
     582    26654038 : LoadElimination::AbstractStateForEffectNodes::Get(Node* node) const {
     583    26654038 :   size_t const id = node->id();
     584    74680846 :   if (id < info_for_node_.size()) return info_for_node_[id];
     585             :   return nullptr;
     586             : }
     587             : 
     588     9231190 : void LoadElimination::AbstractStateForEffectNodes::Set(
     589     9231190 :     Node* node, AbstractState const* state) {
     590     9231190 :   size_t const id = node->id();
     591    18462380 :   if (id >= info_for_node_.size()) info_for_node_.resize(id + 1, nullptr);
     592     9231186 :   info_for_node_[id] = state;
     593     9231186 : }
     594             : 
     595         636 : Reduction LoadElimination::ReduceArrayBufferWasNeutered(Node* node) {
     596         636 :   Node* const effect = NodeProperties::GetEffectInput(node);
     597             :   AbstractState const* state = node_states_.Get(effect);
     598         636 :   if (state == nullptr) return NoChange();
     599         444 :   if (Node* const check = state->LookupCheck(node)) {
     600          17 :     ReplaceWithValue(node, check, effect);
     601             :     return Replace(check);
     602             :   }
     603         427 :   state = state->AddCheck(node, zone());
     604         427 :   return UpdateState(node, state);
     605             : }
     606             : 
     607      138591 : Reduction LoadElimination::ReduceCheckMaps(Node* node) {
     608      138591 :   ZoneHandleSet<Map> const maps = CheckMapsParametersOf(node->op()).maps();
     609      138591 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     610      138591 :   Node* const effect = NodeProperties::GetEffectInput(node);
     611             :   AbstractState const* state = node_states_.Get(effect);
     612      138591 :   if (state == nullptr) return NoChange();
     613             :   ZoneHandleSet<Map> object_maps;
     614       89089 :   if (state->LookupMaps(object, &object_maps)) {
     615       36782 :     if (maps.contains(object_maps)) return Replace(effect);
     616         679 :     state = state->KillMaps(object, zone());
     617             :     // TODO(turbofan): Compute the intersection.
     618             :   }
     619       52986 :   state = state->AddMaps(object, maps, zone());
     620       52986 :   return UpdateState(node, state);
     621             : }
     622             : 
     623         212 : Reduction LoadElimination::ReduceEnsureWritableFastElements(Node* node) {
     624         212 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     625         212 :   Node* const elements = NodeProperties::GetValueInput(node, 1);
     626         212 :   Node* const effect = NodeProperties::GetEffectInput(node);
     627             :   AbstractState const* state = node_states_.Get(effect);
     628         212 :   if (state == nullptr) return NoChange();
     629             :     // Check if the {elements} already have the fixed array map.
     630             :   ZoneHandleSet<Map> elements_maps;
     631             :   ZoneHandleSet<Map> fixed_array_maps(factory()->fixed_array_map());
     632         196 :   if (state->LookupMaps(elements, &elements_maps) &&
     633           4 :       fixed_array_maps.contains(elements_maps)) {
     634           4 :     ReplaceWithValue(node, elements, effect);
     635             :     return Replace(elements);
     636             :   }
     637             :   // We know that the resulting elements have the fixed array map.
     638         188 :   state = state->AddMaps(node, fixed_array_maps, zone());
     639             :   // Kill the previous elements on {object}.
     640             :   state =
     641         188 :       state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone());
     642             :   // Add the new elements on {object}.
     643             :   state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node,
     644         188 :                           zone());
     645         188 :   return UpdateState(node, state);
     646             : }
     647             : 
     648        3217 : Reduction LoadElimination::ReduceMaybeGrowFastElements(Node* node) {
     649        3217 :   GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op());
     650        3217 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     651        3217 :   Node* const effect = NodeProperties::GetEffectInput(node);
     652             :   AbstractState const* state = node_states_.Get(effect);
     653        3217 :   if (state == nullptr) return NoChange();
     654        2213 :   if (flags & GrowFastElementsFlag::kDoubleElements) {
     655             :     // We know that the resulting elements have the fixed double array map.
     656             :     state = state->AddMaps(
     657         193 :         node, ZoneHandleSet<Map>(factory()->fixed_double_array_map()), zone());
     658             :   } else {
     659             :     // We know that the resulting elements have the fixed array map.
     660             :     state = state->AddMaps(
     661        2020 :         node, ZoneHandleSet<Map>(factory()->fixed_array_map()), zone());
     662             :   }
     663        2213 :   if (flags & GrowFastElementsFlag::kArrayObject) {
     664             :     // Kill the previous Array::length on {object}.
     665             :     state =
     666        2200 :         state->KillField(object, FieldIndexOf(JSArray::kLengthOffset), zone());
     667             :   }
     668             :   // Kill the previous elements on {object}.
     669             :   state =
     670        2213 :       state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone());
     671             :   // Add the new elements on {object}.
     672             :   state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node,
     673        2213 :                           zone());
     674        2213 :   return UpdateState(node, state);
     675             : }
     676             : 
     677         667 : Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) {
     678         667 :   ElementsTransition transition = ElementsTransitionOf(node->op());
     679         667 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     680             :   Handle<Map> source_map(transition.source());
     681             :   Handle<Map> target_map(transition.target());
     682         667 :   Node* const effect = NodeProperties::GetEffectInput(node);
     683             :   AbstractState const* state = node_states_.Get(effect);
     684         667 :   if (state == nullptr) return NoChange();
     685             :   ZoneHandleSet<Map> object_maps;
     686         571 :   if (state->LookupMaps(object, &object_maps)) {
     687         125 :     if (ZoneHandleSet<Map>(target_map).contains(object_maps)) {
     688             :       // The {object} already has the {target_map}, so this TransitionElements
     689             :       // {node} is fully redundant (independent of what {source_map} is).
     690             :       return Replace(effect);
     691             :     }
     692          62 :     if (object_maps.contains(ZoneHandleSet<Map>(source_map))) {
     693          62 :       object_maps.remove(source_map, zone());
     694          62 :       object_maps.insert(target_map, zone());
     695          62 :       state = state->KillMaps(object, zone());
     696          62 :       state = state->AddMaps(object, object_maps, zone());
     697             :     }
     698             :   } else {
     699         446 :     state = state->KillMaps(object, zone());
     700             :   }
     701         508 :   switch (transition.mode()) {
     702             :     case ElementsTransition::kFastTransition:
     703             :       break;
     704             :     case ElementsTransition::kSlowTransition:
     705             :       // Kill the elements as well.
     706             :       state = state->KillField(object, FieldIndexOf(JSObject::kElementsOffset),
     707         281 :                                zone());
     708         281 :       break;
     709             :   }
     710         508 :   return UpdateState(node, state);
     711             : }
     712             : 
     713     1427802 : Reduction LoadElimination::ReduceLoadField(Node* node) {
     714     1427468 :   FieldAccess const& access = FieldAccessOf(node->op());
     715     1427468 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     716     1427468 :   Node* const effect = NodeProperties::GetEffectInput(node);
     717     1427467 :   Node* const control = NodeProperties::GetControlInput(node);
     718             :   AbstractState const* state = node_states_.Get(effect);
     719     1427469 :   if (state == nullptr) return NoChange();
     720     1144900 :   if (access.offset == HeapObject::kMapOffset &&
     721             :       access.base_is_tagged == kTaggedBase) {
     722             :     DCHECK(IsAnyTagged(access.machine_type.representation()));
     723             :     ZoneHandleSet<Map> object_maps;
     724       15009 :     if (state->LookupMaps(object, &object_maps) && object_maps.size() == 1) {
     725         334 :       Node* value = jsgraph()->HeapConstant(object_maps[0]);
     726             :       NodeProperties::SetType(value, Type::OtherInternal());
     727      130686 :       ReplaceWithValue(node, value, effect);
     728         334 :       return Replace(value);
     729             :     }
     730             :   } else {
     731     1130747 :     int field_index = FieldIndexOf(access);
     732     1130748 :     if (field_index >= 0) {
     733     2148984 :       if (Node* replacement = state->LookupField(object, field_index)) {
     734             :         // Make sure we don't resurrect dead {replacement} nodes.
     735      130352 :         if (!replacement->IsDead()) {
     736             :           // We might need to guard the {replacement} if the type of the
     737             :           // {node} is more precise than the type of the {replacement}.
     738             :           Type* const node_type = NodeProperties::GetType(node);
     739      130352 :           if (!NodeProperties::GetType(replacement)->Is(node_type)) {
     740             :             replacement = graph()->NewNode(common()->TypeGuard(node_type),
     741         910 :                                            replacement, control);
     742             :             NodeProperties::SetType(replacement, node_type);
     743             :           }
     744             :           ReplaceWithValue(node, replacement, effect);
     745             :           return Replace(replacement);
     746             :         }
     747             :       }
     748      944140 :       state = state->AddField(object, field_index, node, zone());
     749             :     }
     750             :   }
     751             :   Handle<Map> field_map;
     752     1014214 :   if (access.map.ToHandle(&field_map)) {
     753       11232 :     state = state->AddMaps(node, ZoneHandleSet<Map>(field_map), zone());
     754             :   }
     755     1014215 :   return UpdateState(node, state);
     756             : }
     757             : 
     758     1344908 : Reduction LoadElimination::ReduceStoreField(Node* node) {
     759     1344908 :   FieldAccess const& access = FieldAccessOf(node->op());
     760     1344908 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     761     1344908 :   Node* const new_value = NodeProperties::GetValueInput(node, 1);
     762     1344908 :   Node* const effect = NodeProperties::GetEffectInput(node);
     763             :   AbstractState const* state = node_states_.Get(effect);
     764     1344908 :   if (state == nullptr) return NoChange();
     765     1105138 :   if (access.offset == HeapObject::kMapOffset &&
     766             :       access.base_is_tagged == kTaggedBase) {
     767             :     DCHECK(IsAnyTagged(access.machine_type.representation()));
     768             :     // Kill all potential knowledge about the {object}s map.
     769      129988 :     state = state->KillMaps(object, zone());
     770             :     Type* const new_value_type = NodeProperties::GetType(new_value);
     771      129988 :     if (new_value_type->IsHeapConstant()) {
     772             :       // Record the new {object} map information.
     773             :       ZoneHandleSet<Map> object_maps(
     774             :           Handle<Map>::cast(new_value_type->AsHeapConstant()->Value()));
     775      129967 :       state = state->AddMaps(object, object_maps, zone());
     776             :     }
     777             :   } else {
     778      975150 :     int field_index = FieldIndexOf(access);
     779      975150 :     if (field_index >= 0) {
     780      883140 :       Node* const old_value = state->LookupField(object, field_index);
     781      883140 :       if (old_value == new_value) {
     782             :         // This store is fully redundant.
     783             :         return Replace(effect);
     784             :       }
     785             :       // Kill all potentially aliasing fields and record the new value.
     786      882832 :       state = state->KillField(object, field_index, zone());
     787      882832 :       state = state->AddField(object, field_index, new_value, zone());
     788             :     } else {
     789             :       // Unsupported StoreField operator.
     790       92010 :       state = state->KillFields(object, zone());
     791             :     }
     792             :   }
     793     1104829 :   return UpdateState(node, state);
     794             : }
     795             : 
     796       91657 : Reduction LoadElimination::ReduceLoadElement(Node* node) {
     797       56448 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     798       56448 :   Node* const index = NodeProperties::GetValueInput(node, 1);
     799       56448 :   Node* const effect = NodeProperties::GetEffectInput(node);
     800       56448 :   Node* const control = NodeProperties::GetControlInput(node);
     801             :   AbstractState const* state = node_states_.Get(effect);
     802       56448 :   if (state == nullptr) return NoChange();
     803             : 
     804             :   // Only handle loads that do not require truncations.
     805       35209 :   ElementAccess const& access = ElementAccessOf(node->op());
     806       35209 :   switch (access.machine_type.representation()) {
     807             :     case MachineRepresentation::kNone:
     808             :     case MachineRepresentation::kSimd1x4:
     809             :     case MachineRepresentation::kSimd1x8:
     810             :     case MachineRepresentation::kSimd1x16:
     811             :     case MachineRepresentation::kBit:
     812           0 :       UNREACHABLE();
     813             :       break;
     814             :     case MachineRepresentation::kWord8:
     815             :     case MachineRepresentation::kWord16:
     816             :     case MachineRepresentation::kWord32:
     817             :     case MachineRepresentation::kWord64:
     818             :     case MachineRepresentation::kFloat32:
     819             :       // TODO(turbofan): Add support for doing the truncations.
     820             :       break;
     821             :     case MachineRepresentation::kFloat64:
     822             :     case MachineRepresentation::kSimd128:
     823             :     case MachineRepresentation::kTaggedSigned:
     824             :     case MachineRepresentation::kTaggedPointer:
     825             :     case MachineRepresentation::kTagged:
     826       34902 :       if (Node* replacement = state->LookupElement(object, index)) {
     827             :         // Make sure we don't resurrect dead {replacement} nodes.
     828         655 :         if (!replacement->IsDead()) {
     829             :           // We might need to guard the {replacement} if the type of the
     830             :           // {node} is more precise than the type of the {replacement}.
     831             :           Type* const node_type = NodeProperties::GetType(node);
     832         655 :           if (!NodeProperties::GetType(replacement)->Is(node_type)) {
     833             :             replacement = graph()->NewNode(common()->TypeGuard(node_type),
     834           8 :                                            replacement, control);
     835             :             NodeProperties::SetType(replacement, node_type);
     836             :           }
     837         655 :           ReplaceWithValue(node, replacement, effect);
     838             :           return Replace(replacement);
     839             :         }
     840             :       }
     841       34247 :       state = state->AddElement(object, index, node, zone());
     842       34247 :       return UpdateState(node, state);
     843             :   }
     844             :   return NoChange();
     845             : }
     846             : 
     847      180680 : Reduction LoadElimination::ReduceStoreElement(Node* node) {
     848      180680 :   ElementAccess const& access = ElementAccessOf(node->op());
     849      180680 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     850      180680 :   Node* const index = NodeProperties::GetValueInput(node, 1);
     851      180680 :   Node* const new_value = NodeProperties::GetValueInput(node, 2);
     852      180680 :   Node* const effect = NodeProperties::GetEffectInput(node);
     853             :   AbstractState const* state = node_states_.Get(effect);
     854      180680 :   if (state == nullptr) return NoChange();
     855             :   Node* const old_value = state->LookupElement(object, index);
     856      166444 :   if (old_value == new_value) {
     857             :     // This store is fully redundant.
     858             :     return Replace(effect);
     859             :   }
     860             :   // Kill all potentially aliasing elements.
     861      166422 :   state = state->KillElement(object, index, zone());
     862             :   // Only record the new value if the store doesn't have an implicit truncation.
     863      166422 :   switch (access.machine_type.representation()) {
     864             :     case MachineRepresentation::kNone:
     865             :     case MachineRepresentation::kSimd1x4:
     866             :     case MachineRepresentation::kSimd1x8:
     867             :     case MachineRepresentation::kSimd1x16:
     868             :     case MachineRepresentation::kBit:
     869           0 :       UNREACHABLE();
     870             :       break;
     871             :     case MachineRepresentation::kWord8:
     872             :     case MachineRepresentation::kWord16:
     873             :     case MachineRepresentation::kWord32:
     874             :     case MachineRepresentation::kWord64:
     875             :     case MachineRepresentation::kFloat32:
     876             :       // TODO(turbofan): Add support for doing the truncations.
     877             :       break;
     878             :     case MachineRepresentation::kFloat64:
     879             :     case MachineRepresentation::kSimd128:
     880             :     case MachineRepresentation::kTaggedSigned:
     881             :     case MachineRepresentation::kTaggedPointer:
     882             :     case MachineRepresentation::kTagged:
     883      166172 :       state = state->AddElement(object, index, new_value, zone());
     884      166172 :       break;
     885             :   }
     886      166422 :   return UpdateState(node, state);
     887             : }
     888             : 
     889        4921 : Reduction LoadElimination::ReduceStoreTypedElement(Node* node) {
     890        4921 :   Node* const effect = NodeProperties::GetEffectInput(node);
     891             :   AbstractState const* state = node_states_.Get(effect);
     892        4921 :   if (state == nullptr) return NoChange();
     893        3673 :   return UpdateState(node, state);
     894             : }
     895             : 
     896     1614726 : Reduction LoadElimination::ReduceEffectPhi(Node* node) {
     897      956620 :   Node* const effect0 = NodeProperties::GetEffectInput(node, 0);
     898     1710676 :   Node* const control = NodeProperties::GetControlInput(node);
     899             :   AbstractState const* state0 = node_states_.Get(effect0);
     900      956619 :   if (state0 == nullptr) return NoChange();
     901      754056 :   if (control->opcode() == IrOpcode::kLoop) {
     902             :     // Here we rely on having only reducible loops:
     903             :     // The loop entry edge always dominates the header, so we can just take
     904             :     // the state from the first input, and compute the loop state based on it.
     905       95950 :     AbstractState const* state = ComputeLoopState(node, state0);
     906       95950 :     return UpdateState(node, state);
     907             :   }
     908             :   DCHECK_EQ(IrOpcode::kMerge, control->opcode());
     909             : 
     910             :   // Shortcut for the case when we do not know anything about some input.
     911      658106 :   int const input_count = node->op()->EffectInputCount();
     912     3673974 :   for (int i = 1; i < input_count; ++i) {
     913     3148171 :     Node* const effect = NodeProperties::GetEffectInput(node, i);
     914     3148171 :     if (node_states_.Get(effect) == nullptr) return NoChange();
     915             :   }
     916             : 
     917             :   // Make a copy of the first input's state and merge with the state
     918             :   // from other inputs.
     919      525805 :   AbstractState* state = new (zone()) AbstractState(*state0);
     920     1811793 :   for (int i = 1; i < input_count; ++i) {
     921     1285988 :     Node* const input = NodeProperties::GetEffectInput(node, i);
     922     1285988 :     state->Merge(node_states_.Get(input), zone());
     923             :   }
     924      525805 :   return UpdateState(node, state);
     925             : }
     926             : 
     927           0 : Reduction LoadElimination::ReduceStart(Node* node) {
     928      393189 :   return UpdateState(node, empty_state());
     929             : }
     930             : 
     931    37515535 : Reduction LoadElimination::ReduceOtherNode(Node* node) {
     932    30955956 :   if (node->op()->EffectInputCount() == 1) {
     933     8851681 :     if (node->op()->EffectOutputCount() == 1) {
     934     8151283 :       Node* const effect = NodeProperties::GetEffectInput(node);
     935             :       AbstractState const* state = node_states_.Get(effect);
     936             :       // If we do not know anything about the predecessor, do not propagate
     937             :       // just yet because we will have to recompute anyway once we compute
     938             :       // the predecessor.
     939     8151294 :       if (state == nullptr) return NoChange();
     940             :       // Check if this {node} has some uncontrolled side effects.
     941     6559579 :       if (!node->op()->HasProperty(Operator::kNoWrite)) {
     942     2312573 :         state = empty_state();
     943             :       }
     944     6559579 :       return UpdateState(node, state);
     945             :     } else {
     946             :       // Effect terminators should be handled specially.
     947             :       return NoChange();
     948             :     }
     949             :   }
     950             :   DCHECK_EQ(0, node->op()->EffectInputCount());
     951             :   DCHECK_EQ(0, node->op()->EffectOutputCount());
     952             :   return NoChange();
     953             : }
     954             : 
     955     9954217 : Reduction LoadElimination::UpdateState(Node* node, AbstractState const* state) {
     956             :   AbstractState const* original = node_states_.Get(node);
     957             :   // Only signal that the {node} has Changed, if the information about {state}
     958             :   // has changed wrt. the {original}.
     959     9954217 :   if (state != original) {
     960     9436065 :     if (original == nullptr || !state->Equals(original)) {
     961     9231189 :       node_states_.Set(node, state);
     962             :       return Changed(node);
     963             :     }
     964             :   }
     965             :   return NoChange();
     966             : }
     967             : 
     968       95950 : LoadElimination::AbstractState const* LoadElimination::ComputeLoopState(
     969             :     Node* node, AbstractState const* state) const {
     970       95950 :   Node* const control = NodeProperties::GetControlInput(node);
     971       95950 :   ZoneQueue<Node*> queue(zone());
     972             :   ZoneSet<Node*> visited(zone());
     973             :   visited.insert(node);
     974      383800 :   for (int i = 1; i < control->InputCount(); ++i) {
     975      287850 :     queue.push(node->InputAt(i));
     976             :   }
     977      804109 :   while (!queue.empty()) {
     978      783663 :     Node* const current = queue.front();
     979             :     queue.pop();
     980      783639 :     if (visited.find(current) == visited.end()) {
     981             :       visited.insert(current);
     982     2850268 :       if (!current->op()->HasProperty(Operator::kNoWrite)) {
     983      112055 :         switch (current->opcode()) {
     984             :           case IrOpcode::kEnsureWritableFastElements: {
     985          33 :             Node* const object = NodeProperties::GetValueInput(current, 0);
     986             :             state = state->KillField(
     987          33 :                 object, FieldIndexOf(JSObject::kElementsOffset), zone());
     988          33 :             break;
     989             :           }
     990             :           case IrOpcode::kMaybeGrowFastElements: {
     991             :             GrowFastElementsFlags flags =
     992        1234 :                 GrowFastElementsFlagsOf(current->op());
     993        1234 :             Node* const object = NodeProperties::GetValueInput(current, 0);
     994             :             state = state->KillField(
     995        1234 :                 object, FieldIndexOf(JSObject::kElementsOffset), zone());
     996        1234 :             if (flags & GrowFastElementsFlag::kArrayObject) {
     997             :               state = state->KillField(
     998        1234 :                   object, FieldIndexOf(JSArray::kLengthOffset), zone());
     999             :             }
    1000             :             break;
    1001             :           }
    1002             :           case IrOpcode::kTransitionElementsKind: {
    1003         157 :             ElementsTransition transition = ElementsTransitionOf(current->op());
    1004         157 :             Node* const object = NodeProperties::GetValueInput(current, 0);
    1005             :             ZoneHandleSet<Map> object_maps;
    1006         471 :             if (!state->LookupMaps(object, &object_maps) ||
    1007             :                 !ZoneHandleSet<Map>(transition.target())
    1008         247 :                      .contains(object_maps)) {
    1009         112 :               state = state->KillMaps(object, zone());
    1010         112 :               switch (transition.mode()) {
    1011             :                 case ElementsTransition::kFastTransition:
    1012             :                   break;
    1013             :                 case ElementsTransition::kSlowTransition:
    1014             :                   // Kill the elements as well.
    1015             :                   state = state->KillField(
    1016          53 :                       object, FieldIndexOf(JSObject::kElementsOffset), zone());
    1017          53 :                   break;
    1018             :               }
    1019             :             }
    1020             :             break;
    1021             :           }
    1022             :           case IrOpcode::kStoreField: {
    1023       28291 :             FieldAccess const& access = FieldAccessOf(current->op());
    1024       28291 :             Node* const object = NodeProperties::GetValueInput(current, 0);
    1025       28291 :             if (access.offset == HeapObject::kMapOffset) {
    1026             :               // Invalidate what we know about the {object}s map.
    1027        5200 :               state = state->KillMaps(object, zone());
    1028             :             } else {
    1029       23091 :               int field_index = FieldIndexOf(access);
    1030       23091 :               if (field_index < 0) {
    1031          11 :                 state = state->KillFields(object, zone());
    1032             :               } else {
    1033       23080 :                 state = state->KillField(object, field_index, zone());
    1034             :               }
    1035             :             }
    1036             :             break;
    1037             :           }
    1038             :           case IrOpcode::kStoreElement: {
    1039        5073 :             Node* const object = NodeProperties::GetValueInput(current, 0);
    1040        5073 :             Node* const index = NodeProperties::GetValueInput(current, 1);
    1041        5073 :             state = state->KillElement(object, index, zone());
    1042        5073 :             break;
    1043             :           }
    1044             :           case IrOpcode::kStoreBuffer:
    1045             :           case IrOpcode::kStoreTypedElement: {
    1046             :             // Doesn't affect anything we track with the state currently.
    1047             :             break;
    1048             :           }
    1049             :           default:
    1050       75495 :             return empty_state();
    1051             :         }
    1052             :       }
    1053     4197450 :       for (int i = 0; i < current->op()->EffectInputCount(); ++i) {
    1054     1498202 :         queue.push(NodeProperties::GetEffectInput(current, i));
    1055             :       }
    1056             :     }
    1057             :   }
    1058             :   return state;
    1059             : }
    1060             : 
    1061             : // static
    1062           0 : int LoadElimination::FieldIndexOf(int offset) {
    1063             :   DCHECK_EQ(0, offset % kPointerSize);
    1064     2024927 :   int field_index = offset / kPointerSize;
    1065     2024927 :   if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1;
    1066             :   DCHECK_LT(0, field_index);
    1067     1980711 :   return field_index - 1;
    1068             : }
    1069             : 
    1070             : // static
    1071     2128988 : int LoadElimination::FieldIndexOf(FieldAccess const& access) {
    1072     2128988 :   MachineRepresentation rep = access.machine_type.representation();
    1073             :   switch (rep) {
    1074             :     case MachineRepresentation::kNone:
    1075             :     case MachineRepresentation::kBit:
    1076             :     case MachineRepresentation::kSimd128:
    1077             :     case MachineRepresentation::kSimd1x4:
    1078             :     case MachineRepresentation::kSimd1x8:
    1079             :     case MachineRepresentation::kSimd1x16:
    1080           0 :       UNREACHABLE();
    1081             :       break;
    1082             :     case MachineRepresentation::kWord32:
    1083             :     case MachineRepresentation::kWord64:
    1084        8600 :       if (rep != MachineType::PointerRepresentation()) {
    1085             :         return -1;  // We currently only track pointer size fields.
    1086             :       }
    1087             :       break;
    1088             :     case MachineRepresentation::kWord8:
    1089             :     case MachineRepresentation::kWord16:
    1090             :     case MachineRepresentation::kFloat32:
    1091             :       return -1;  // Currently untracked.
    1092             :     case MachineRepresentation::kFloat64:
    1093             :       if (kDoubleSize != kPointerSize) {
    1094             :         return -1;  // We currently only track pointer size fields.
    1095             :       }
    1096             :     // Fall through.
    1097             :     case MachineRepresentation::kTaggedSigned:
    1098             :     case MachineRepresentation::kTaggedPointer:
    1099             :     case MachineRepresentation::kTagged:
    1100             :       // TODO(bmeurer): Check that we never do overlapping load/stores of
    1101             :       // individual parts of Float64 values.
    1102             :       break;
    1103             :   }
    1104     2121403 :   if (access.base_is_tagged != kTaggedBase) {
    1105             :     return -1;  // We currently only track tagged objects.
    1106             :   }
    1107     4049854 :   return FieldIndexOf(access.offset);
    1108             : }
    1109             : 
    1110         918 : CommonOperatorBuilder* LoadElimination::common() const {
    1111         918 :   return jsgraph()->common();
    1112             : }
    1113             : 
    1114         918 : Graph* LoadElimination::graph() const { return jsgraph()->graph(); }
    1115             : 
    1116        2405 : Factory* LoadElimination::factory() const { return jsgraph()->factory(); }
    1117             : 
    1118             : }  // namespace compiler
    1119             : }  // namespace internal
    1120             : }  // namespace v8

Generated by: LCOV version 1.10