LCOV - code coverage report
Current view: top level - src/compiler - node-properties.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 206 218 94.5 %
Date: 2019-03-21 Functions: 42 45 93.3 %

          Line data    Source code
       1             : // Copyright 2015 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-properties.h"
       6             : #include "src/compiler/common-operator.h"
       7             : #include "src/compiler/graph.h"
       8             : #include "src/compiler/js-operator.h"
       9             : #include "src/compiler/linkage.h"
      10             : #include "src/compiler/node-matchers.h"
      11             : #include "src/compiler/operator-properties.h"
      12             : #include "src/compiler/simplified-operator.h"
      13             : #include "src/compiler/verifier.h"
      14             : #include "src/handles-inl.h"
      15             : #include "src/objects-inl.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : namespace compiler {
      20             : 
      21             : // static
      22       75577 : int NodeProperties::PastValueIndex(Node* node) {
      23       75577 :   return FirstValueIndex(node) + node->op()->ValueInputCount();
      24             : }
      25             : 
      26             : 
      27             : // static
      28         498 : int NodeProperties::PastContextIndex(Node* node) {
      29             :   return FirstContextIndex(node) +
      30  1231173481 :          OperatorProperties::GetContextInputCount(node->op());
      31             : }
      32             : 
      33             : 
      34             : // static
      35  1218281094 : int NodeProperties::PastFrameStateIndex(Node* node) {
      36             :   return FirstFrameStateIndex(node) +
      37  1218118997 :          OperatorProperties::GetFrameStateInputCount(node->op());
      38             : }
      39             : 
      40             : 
      41             : // static
      42    92242502 : int NodeProperties::PastEffectIndex(Node* node) {
      43   713317190 :   return FirstEffectIndex(node) + node->op()->EffectInputCount();
      44             : }
      45             : 
      46             : 
      47             : // static
      48    66802175 : int NodeProperties::PastControlIndex(Node* node) {
      49    66802930 :   return FirstControlIndex(node) + node->op()->ControlInputCount();
      50             : }
      51             : 
      52             : 
      53             : // static
      54   170857126 : Node* NodeProperties::GetValueInput(Node* node, int index) {
      55             :   DCHECK(0 <= index && index < node->op()->ValueInputCount());
      56   170857126 :   return node->InputAt(FirstValueIndex(node) + index);
      57             : }
      58             : 
      59             : 
      60             : // static
      61     6172256 : Node* NodeProperties::GetContextInput(Node* node) {
      62             :   DCHECK(OperatorProperties::HasContextInput(node->op()));
      63     6172256 :   return node->InputAt(FirstContextIndex(node));
      64             : }
      65             : 
      66             : 
      67             : // static
      68     5229505 : Node* NodeProperties::GetFrameStateInput(Node* node) {
      69             :   DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
      70     5229512 :   return node->InputAt(FirstFrameStateIndex(node));
      71             : }
      72             : 
      73             : 
      74             : // static
      75   254472461 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
      76             :   DCHECK(0 <= index && index < node->op()->EffectInputCount());
      77   508871924 :   return node->InputAt(FirstEffectIndex(node) + index);
      78             : }
      79             : 
      80             : 
      81             : // static
      82   336029863 : Node* NodeProperties::GetControlInput(Node* node, int index) {
      83             :   DCHECK(0 <= index && index < node->op()->ControlInputCount());
      84   671970940 :   return node->InputAt(FirstControlIndex(node) + index);
      85             : }
      86             : 
      87             : 
      88             : // static
      89     9580383 : bool NodeProperties::IsValueEdge(Edge edge) {
      90             :   Node* const node = edge.from();
      91             :   return IsInputRange(edge, FirstValueIndex(node),
      92     9580383 :                       node->op()->ValueInputCount());
      93             : }
      94             : 
      95             : 
      96             : // static
      97           0 : bool NodeProperties::IsContextEdge(Edge edge) {
      98             :   Node* const node = edge.from();
      99             :   return IsInputRange(edge, FirstContextIndex(node),
     100           0 :                       OperatorProperties::GetContextInputCount(node->op()));
     101             : }
     102             : 
     103             : 
     104             : // static
     105      517112 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
     106             :   Node* const node = edge.from();
     107             :   return IsInputRange(edge, FirstFrameStateIndex(node),
     108      517112 :                       OperatorProperties::GetFrameStateInputCount(node->op()));
     109             : }
     110             : 
     111             : 
     112             : // static
     113   228531800 : bool NodeProperties::IsEffectEdge(Edge edge) {
     114             :   Node* const node = edge.from();
     115             :   return IsInputRange(edge, FirstEffectIndex(node),
     116   228526018 :                       node->op()->EffectInputCount());
     117             : }
     118             : 
     119             : 
     120             : // static
     121   204776956 : bool NodeProperties::IsControlEdge(Edge edge) {
     122             :   Node* const node = edge.from();
     123             :   return IsInputRange(edge, FirstControlIndex(node),
     124   204772216 :                       node->op()->ControlInputCount());
     125             : }
     126             : 
     127             : 
     128             : // static
     129    13688542 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
     130    13688542 :   if (node->op()->HasProperty(Operator::kNoThrow)) return false;
     131   141764379 :   for (Edge const edge : node->use_edges()) {
     132    64446995 :     if (!NodeProperties::IsControlEdge(edge)) continue;
     133    21681569 :     if (edge.from()->opcode() == IrOpcode::kIfException) {
     134      828471 :       if (out_exception != nullptr) *out_exception = edge.from();
     135      818149 :       return true;
     136             :     }
     137             :   }
     138    12870389 :   return false;
     139             : }
     140             : 
     141             : // static
     142        1414 : Node* NodeProperties::FindSuccessfulControlProjection(Node* node) {
     143             :   DCHECK_GT(node->op()->ControlOutputCount(), 0);
     144        1414 :   if (node->op()->HasProperty(Operator::kNoThrow)) return node;
     145       40370 :   for (Edge const edge : node->use_edges()) {
     146       19575 :     if (!NodeProperties::IsControlEdge(edge)) continue;
     147        7801 :     if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
     148         194 :       return edge.from();
     149             :     }
     150             :   }
     151        1220 :   return node;
     152             : }
     153             : 
     154             : // static
     155     1355916 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
     156             :   DCHECK(index < node->op()->ValueInputCount());
     157     1355916 :   node->ReplaceInput(FirstValueIndex(node) + index, value);
     158     1355916 : }
     159             : 
     160             : 
     161             : // static
     162         686 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
     163             :   int value_input_count = node->op()->ValueInputCount();
     164             :   DCHECK_LE(1, value_input_count);
     165         686 :   node->ReplaceInput(0, value);
     166        2840 :   while (--value_input_count > 0) {
     167        1077 :     node->RemoveInput(value_input_count);
     168             :   }
     169         686 : }
     170             : 
     171             : 
     172             : // static
     173      266250 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
     174      266250 :   node->ReplaceInput(FirstContextIndex(node), context);
     175      266250 : }
     176             : 
     177             : 
     178             : // static
     179    13514173 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
     180             :   DCHECK(index < node->op()->ControlInputCount());
     181    13514167 :   node->ReplaceInput(FirstControlIndex(node) + index, control);
     182    13514159 : }
     183             : 
     184             : 
     185             : // static
     186     4762500 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
     187             :   DCHECK(index < node->op()->EffectInputCount());
     188     4762493 :   return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
     189             : }
     190             : 
     191             : 
     192             : // static
     193     7250850 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
     194             :   DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
     195     7250857 :   node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
     196     7250855 : }
     197             : 
     198             : 
     199             : // static
     200      104295 : void NodeProperties::RemoveNonValueInputs(Node* node) {
     201      104295 :   node->TrimInputCount(node->op()->ValueInputCount());
     202      104295 : }
     203             : 
     204             : 
     205             : // static
     206           0 : void NodeProperties::RemoveValueInputs(Node* node) {
     207             :   int value_input_count = node->op()->ValueInputCount();
     208           0 :   while (--value_input_count >= 0) {
     209           0 :     node->RemoveInput(value_input_count);
     210             :   }
     211           0 : }
     212             : 
     213             : 
     214      609992 : void NodeProperties::MergeControlToEnd(Graph* graph,
     215             :                                        CommonOperatorBuilder* common,
     216             :                                        Node* node) {
     217      609992 :   graph->end()->AppendInput(graph->zone(), node);
     218      609994 :   graph->end()->set_op(common->End(graph->end()->InputCount()));
     219      609996 : }
     220             : 
     221             : 
     222             : // static
     223     2136233 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
     224             :                                  Node* success, Node* exception) {
     225             :   // Requires distinguishing between value, effect and control edges.
     226    16571617 :   for (Edge edge : node->use_edges()) {
     227     7217689 :     if (IsControlEdge(edge)) {
     228     2155499 :       if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
     229             :         DCHECK_NOT_NULL(success);
     230       25659 :         edge.UpdateTo(success);
     231     2129840 :       } else if (edge.from()->opcode() == IrOpcode::kIfException) {
     232             :         DCHECK_NOT_NULL(exception);
     233        7281 :         edge.UpdateTo(exception);
     234             :       } else {
     235             :         DCHECK_NOT_NULL(success);
     236     2122559 :         edge.UpdateTo(success);
     237             :       }
     238     5062292 :     } else if (IsEffectEdge(edge)) {
     239             :       DCHECK_NOT_NULL(effect);
     240     1898479 :       edge.UpdateTo(effect);
     241             :     } else {
     242             :       DCHECK_NOT_NULL(value);
     243     3163845 :       edge.UpdateTo(value);
     244             :     }
     245             :   }
     246     2136239 : }
     247             : 
     248             : 
     249             : // static
     250    38403363 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
     251             :   node->set_op(new_op);
     252             :   Verifier::VerifyNode(node);
     253    38403363 : }
     254             : 
     255             : 
     256             : // static
     257       87194 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
     258       87194 :   Node* effect = NodeProperties::GetEffectInput(node);
     259      436650 :   while (effect->opcode() != IrOpcode::kCheckpoint) {
     260      174728 :     if (effect->opcode() == IrOpcode::kDead) return effect;
     261             :     DCHECK_EQ(1, effect->op()->EffectInputCount());
     262      174728 :     effect = NodeProperties::GetEffectInput(effect);
     263             :   }
     264       87194 :   Node* frame_state = GetFrameStateInput(effect);
     265       87194 :   return frame_state;
     266             : }
     267             : 
     268             : // static
     269      340740 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
     270      341075 :   for (auto use : node->uses()) {
     271      681498 :     if (use->opcode() == IrOpcode::kProjection &&
     272      340745 :         ProjectionIndexOf(use->op()) == projection_index) {
     273             :       return use;
     274             :     }
     275             :   }
     276             :   return nullptr;
     277             : }
     278             : 
     279             : 
     280             : // static
     281           0 : void NodeProperties::CollectValueProjections(Node* node, Node** projections,
     282             :                                              size_t projection_count) {
     283             : #ifdef DEBUG
     284             :   for (size_t index = 0; index < projection_count; ++index) {
     285             :     DCHECK_NULL(projections[index]);
     286             :   }
     287             : #endif
     288           0 :   for (Edge const edge : node->use_edges()) {
     289           0 :     if (!IsValueEdge(edge)) continue;
     290             :     Node* use = edge.from();
     291             :     DCHECK_EQ(IrOpcode::kProjection, use->opcode());
     292           0 :     projections[ProjectionIndexOf(use->op())] = use;
     293             :   }
     294           0 : }
     295             : 
     296             : 
     297             : // static
     298    11087762 : void NodeProperties::CollectControlProjections(Node* node, Node** projections,
     299             :                                                size_t projection_count) {
     300             : #ifdef DEBUG
     301             :   DCHECK_LE(static_cast<int>(projection_count), node->UseCount());
     302             :   std::memset(projections, 0, sizeof(*projections) * projection_count);
     303             : #endif
     304             :   size_t if_value_index = 0;
     305    63485248 :   for (Edge const edge : node->use_edges()) {
     306    26198705 :     if (!IsControlEdge(edge)) continue;
     307             :     Node* use = edge.from();
     308             :     size_t index;
     309    22771963 :     switch (use->opcode()) {
     310             :       case IrOpcode::kIfTrue:
     311             :         DCHECK_EQ(IrOpcode::kBranch, node->opcode());
     312             :         index = 0;
     313             :         break;
     314             :       case IrOpcode::kIfFalse:
     315             :         DCHECK_EQ(IrOpcode::kBranch, node->opcode());
     316             :         index = 1;
     317    10219041 :         break;
     318             :       case IrOpcode::kIfSuccess:
     319             :         DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
     320             :         index = 0;
     321             :         break;
     322             :       case IrOpcode::kIfException:
     323             :         DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
     324             :         index = 1;
     325      806229 :         break;
     326             :       case IrOpcode::kIfValue:
     327             :         DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
     328      659054 :         index = if_value_index++;
     329      659054 :         break;
     330             :       case IrOpcode::kIfDefault:
     331             :         DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
     332       62492 :         index = projection_count - 1;
     333       62492 :         break;
     334             :       default:
     335             :         continue;
     336             :     }
     337             :     DCHECK_LT(if_value_index, projection_count);
     338             :     DCHECK_LT(index, projection_count);
     339             :     DCHECK_NULL(projections[index]);
     340    22772035 :     projections[index] = use;
     341             :   }
     342             : #ifdef DEBUG
     343             :   for (size_t index = 0; index < projection_count; ++index) {
     344             :     DCHECK_NOT_NULL(projections[index]);
     345             :   }
     346             : #endif
     347    11087838 : }
     348             : 
     349             : // static
     350     4929577 : bool NodeProperties::IsSame(Node* a, Node* b) {
     351             :   for (;;) {
     352     4982813 :     if (a->opcode() == IrOpcode::kCheckHeapObject) {
     353             :       a = GetValueInput(a, 0);
     354        2159 :       continue;
     355             :     }
     356     4980654 :     if (b->opcode() == IrOpcode::kCheckHeapObject) {
     357             :       b = GetValueInput(b, 0);
     358       51077 :       continue;
     359             :     }
     360     4929577 :     return a == b;
     361             :   }
     362             : }
     363             : 
     364             : // static
     365       16301 : base::Optional<MapRef> NodeProperties::GetJSCreateMap(JSHeapBroker* broker,
     366             :                                                       Node* receiver) {
     367             :   DCHECK(receiver->opcode() == IrOpcode::kJSCreate ||
     368             :          receiver->opcode() == IrOpcode::kJSCreateArray);
     369             :   HeapObjectMatcher mtarget(GetValueInput(receiver, 0));
     370             :   HeapObjectMatcher mnewtarget(GetValueInput(receiver, 1));
     371       48903 :   if (mtarget.HasValue() && mnewtarget.HasValue() &&
     372       31785 :       mnewtarget.Ref(broker).IsJSFunction()) {
     373        7721 :     ObjectRef target = mtarget.Ref(broker);
     374        7721 :     JSFunctionRef newtarget = mnewtarget.Ref(broker).AsJSFunction();
     375        7721 :     if (newtarget.map().has_prototype_slot() && newtarget.has_initial_map()) {
     376        7686 :       if (broker->mode() == JSHeapBroker::kSerializing) newtarget.Serialize();
     377        7686 :       MapRef initial_map = newtarget.initial_map();
     378        7686 :       if (initial_map.GetConstructor().equals(target)) {
     379             :         DCHECK(target.AsJSFunction().map().is_constructor());
     380             :         DCHECK(newtarget.map().is_constructor());
     381        7686 :         return initial_map;
     382             :       }
     383             :     }
     384             :   }
     385             :   return base::nullopt;
     386             : }
     387             : 
     388             : // static
     389      186690 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
     390             :     JSHeapBroker* broker, Node* receiver, Node* effect,
     391             :     ZoneHandleSet<Map>* maps_return) {
     392             :   HeapObjectMatcher m(receiver);
     393      186690 :   if (m.HasValue()) {
     394       65212 :     HeapObjectRef receiver = m.Ref(broker).AsHeapObject();
     395             :     // We don't use ICs for the Array.prototype and the Object.prototype
     396             :     // because the runtime has to be able to intercept them properly, so
     397             :     // we better make sure that TurboFan doesn't outsmart the system here
     398             :     // by storing to elements of either prototype directly.
     399             :     //
     400             :     // TODO(bmeurer): This can be removed once the Array.prototype and
     401             :     // Object.prototype have NO_ELEMENTS elements kind.
     402      195636 :     if (!receiver.IsJSObject() ||
     403      188082 :         !broker->IsArrayOrObjectPrototype(receiver.AsJSObject())) {
     404       64956 :       if (receiver.map().is_stable()) {
     405             :         // The {receiver_map} is only reliable when we install a stability
     406             :         // code dependency.
     407       57215 :         *maps_return = ZoneHandleSet<Map>(receiver.map().object());
     408       57215 :         return kUnreliableReceiverMaps;
     409             :       }
     410             :     }
     411             :   }
     412             :   InferReceiverMapsResult result = kReliableReceiverMaps;
     413             :   while (true) {
     414     4960899 :     switch (effect->opcode()) {
     415             :       case IrOpcode::kMapGuard: {
     416             :         Node* const object = GetValueInput(effect, 0);
     417         178 :         if (IsSame(receiver, object)) {
     418         136 :           *maps_return = MapGuardMapsOf(effect->op());
     419         136 :           return result;
     420             :         }
     421             :         break;
     422             :       }
     423             :       case IrOpcode::kCheckMaps: {
     424             :         Node* const object = GetValueInput(effect, 0);
     425       62138 :         if (IsSame(receiver, object)) {
     426       37294 :           *maps_return = CheckMapsParametersOf(effect->op()).maps();
     427       37294 :           return result;
     428             :         }
     429             :         break;
     430             :       }
     431             :       case IrOpcode::kJSCreate: {
     432        4023 :         if (IsSame(receiver, effect)) {
     433        3184 :           base::Optional<MapRef> initial_map = GetJSCreateMap(broker, receiver);
     434        3184 :           if (initial_map.has_value()) {
     435        2936 :             *maps_return = ZoneHandleSet<Map>(initial_map->object());
     436        2936 :             return result;
     437             :           }
     438             :           // We reached the allocation of the {receiver}.
     439             :           return kNoReceiverMaps;
     440             :         }
     441             :         break;
     442             :       }
     443             :       case IrOpcode::kJSCreatePromise: {
     444          86 :         if (IsSame(receiver, effect)) {
     445          44 :           *maps_return = ZoneHandleSet<Map>(broker->native_context()
     446          44 :                                                 .promise_function()
     447          44 :                                                 .initial_map()
     448          22 :                                                 .object());
     449          22 :           return result;
     450             :         }
     451             :         break;
     452             :       }
     453             :       case IrOpcode::kStoreField: {
     454             :         // We only care about StoreField of maps.
     455             :         Node* const object = GetValueInput(effect, 0);
     456       22475 :         FieldAccess const& access = FieldAccessOf(effect->op());
     457       22475 :         if (access.base_is_tagged == kTaggedBase &&
     458             :             access.offset == HeapObject::kMapOffset) {
     459        3957 :           if (IsSame(receiver, object)) {
     460             :             Node* const value = GetValueInput(effect, 1);
     461             :             HeapObjectMatcher m(value);
     462        2832 :             if (m.HasValue()) {
     463        2832 :               *maps_return = ZoneHandleSet<Map>(m.Ref(broker).AsMap().object());
     464             :               return result;
     465             :             }
     466             :           }
     467             :           // Without alias analysis we cannot tell whether this
     468             :           // StoreField[map] affects {receiver} or not.
     469             :           result = kUnreliableReceiverMaps;
     470             :         }
     471             :         break;
     472             :       }
     473             :       case IrOpcode::kJSStoreMessage:
     474             :       case IrOpcode::kJSStoreModule:
     475             :       case IrOpcode::kStoreElement:
     476             :       case IrOpcode::kStoreTypedElement: {
     477             :         // These never change the map of objects.
     478             :         break;
     479             :       }
     480             :       case IrOpcode::kFinishRegion: {
     481             :         // FinishRegion renames the output of allocations, so we need
     482             :         // to update the {receiver} that we are looking for, if the
     483             :         // {receiver} matches the current {effect}.
     484        3957 :         if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
     485             :         break;
     486             :       }
     487             :       case IrOpcode::kEffectPhi: {
     488       26964 :         Node* control = GetControlInput(effect);
     489       26964 :         if (control->opcode() != IrOpcode::kLoop) {
     490             :           DCHECK(control->opcode() == IrOpcode::kDead ||
     491             :                  control->opcode() == IrOpcode::kMerge);
     492             :           return kNoReceiverMaps;
     493             :         }
     494             : 
     495             :         // Continue search for receiver map outside the loop. Since operations
     496             :         // inside the loop may change the map, the result is unreliable.
     497       10896 :         effect = GetEffectInput(effect, 0);
     498             :         result = kUnreliableReceiverMaps;
     499       10896 :         continue;
     500             :       }
     501             :       default: {
     502             :         DCHECK_EQ(1, effect->op()->EffectOutputCount());
     503     4837743 :         if (effect->op()->EffectInputCount() != 1) {
     504             :           // Didn't find any appropriate CheckMaps node.
     505             :           return kNoReceiverMaps;
     506             :         }
     507     4802514 :         if (!effect->op()->HasProperty(Operator::kNoWrite)) {
     508             :           // Without alias/escape analysis we cannot tell whether this
     509             :           // {effect} affects {receiver} or not.
     510             :           result = kUnreliableReceiverMaps;
     511             :         }
     512             :         break;
     513             :       }
     514             :     }
     515             : 
     516             :     // Stop walking the effect chain once we hit the definition of
     517             :     // the {receiver} along the {effect}s.
     518     4855238 :     if (IsSame(receiver, effect)) return kNoReceiverMaps;
     519             : 
     520             :     // Continue with the next {effect}.
     521             :     DCHECK_EQ(1, effect->op()->EffectInputCount());
     522     4820528 :     effect = NodeProperties::GetEffectInput(effect);
     523             :   }
     524             : }
     525             : 
     526             : // static
     527        1778 : bool NodeProperties::HasInstanceTypeWitness(JSHeapBroker* broker,
     528             :                                             Node* receiver, Node* effect,
     529             :                                             InstanceType instance_type) {
     530             :   ZoneHandleSet<Map> receiver_maps;
     531             :   NodeProperties::InferReceiverMapsResult result =
     532             :       NodeProperties::InferReceiverMaps(broker, receiver, effect,
     533        1778 :                                         &receiver_maps);
     534        1778 :   switch (result) {
     535             :     case NodeProperties::kUnreliableReceiverMaps:
     536             :     case NodeProperties::kReliableReceiverMaps:
     537             :       DCHECK_NE(0, receiver_maps.size());
     538        5770 :       for (size_t i = 0; i < receiver_maps.size(); ++i) {
     539             :         MapRef map(broker, receiver_maps[i]);
     540        1997 :         if (map.instance_type() != instance_type) return false;
     541             :       }
     542             :       return true;
     543             : 
     544             :     case NodeProperties::kNoReceiverMaps:
     545             :       return false;
     546             :   }
     547           0 :   UNREACHABLE();
     548             : }
     549             : 
     550             : // static
     551         384 : bool NodeProperties::NoObservableSideEffectBetween(Node* effect,
     552             :                                                    Node* dominator) {
     553        1878 :   while (effect != dominator) {
     554        2032 :     if (effect->op()->EffectInputCount() == 1 &&
     555             :         effect->op()->properties() & Operator::kNoWrite) {
     556         747 :       effect = NodeProperties::GetEffectInput(effect);
     557             :     } else {
     558             :       return false;
     559             :     }
     560             :   }
     561             :   return true;
     562             : }
     563             : 
     564             : // static
     565       58886 : bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
     566             :                                     Node* effect) {
     567       58886 :   switch (receiver->opcode()) {
     568             : #define CASE(Opcode) case IrOpcode::k##Opcode:
     569             :     JS_CONSTRUCT_OP_LIST(CASE)
     570             :     JS_CREATE_OP_LIST(CASE)
     571             : #undef CASE
     572             :     case IrOpcode::kCheckReceiver:
     573             :     case IrOpcode::kConvertReceiver:
     574             :     case IrOpcode::kJSGetSuperConstructor:
     575             :     case IrOpcode::kJSToObject:
     576             :       return false;
     577             :     case IrOpcode::kHeapConstant: {
     578             :       HeapObjectRef value =
     579       56039 :           HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
     580       56039 :       return value.map().IsPrimitiveMap();
     581             :     }
     582             :     default: {
     583             :       // We don't really care about the exact maps here,
     584             :       // just the instance types, which don't change
     585             :       // across potential side-effecting operations.
     586             :       ZoneHandleSet<Map> maps;
     587        2318 :       if (InferReceiverMaps(broker, receiver, effect, &maps) !=
     588             :           kNoReceiverMaps) {
     589             :         // Check if one of the {maps} is not a JSReceiver map.
     590        6086 :         for (size_t i = 0; i < maps.size(); ++i) {
     591             :           MapRef map(broker, maps[i]);
     592        2056 :           if (!map.IsJSReceiverMap()) return true;
     593             :         }
     594             :         return false;
     595             :       }
     596             :       return true;
     597             :     }
     598             :   }
     599             : }
     600             : 
     601             : // static
     602         532 : bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
     603             :                                           Node* effect) {
     604         532 :   if (CanBePrimitive(broker, receiver, effect)) {
     605         115 :     switch (receiver->opcode()) {
     606             :       case IrOpcode::kCheckInternalizedString:
     607             :       case IrOpcode::kCheckNumber:
     608             :       case IrOpcode::kCheckSmi:
     609             :       case IrOpcode::kCheckString:
     610             :       case IrOpcode::kCheckSymbol:
     611             :       case IrOpcode::kJSToLength:
     612             :       case IrOpcode::kJSToName:
     613             :       case IrOpcode::kJSToNumber:
     614             :       case IrOpcode::kJSToNumberConvertBigInt:
     615             :       case IrOpcode::kJSToNumeric:
     616             :       case IrOpcode::kJSToString:
     617             :       case IrOpcode::kToBoolean:
     618             :         return false;
     619             :       case IrOpcode::kHeapConstant: {
     620             :         HeapObjectRef value =
     621          58 :             HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
     622          58 :         OddballType type = value.map().oddball_type();
     623          58 :         return type == OddballType::kNull || type == OddballType::kUndefined;
     624             :       }
     625             :       default:
     626          57 :         return true;
     627             :     }
     628             :   }
     629             :   return false;
     630             : }
     631             : 
     632             : // static
     633      866222 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
     634             :   Node* context = NodeProperties::GetContextInput(node);
     635      940534 :   while (*depth > 0 &&
     636             :          IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
     637             :     context = NodeProperties::GetContextInput(context);
     638       16027 :     (*depth)--;
     639             :   }
     640      866222 :   return context;
     641             : }
     642             : 
     643             : // static
     644   824060061 : Type NodeProperties::GetTypeOrAny(Node* node) {
     645   824060061 :   return IsTyped(node) ? node->type() : Type::Any();
     646             : }
     647             : 
     648             : 
     649             : // static
     650     4895031 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
     651             :   int input_count = node->op()->ValueInputCount();
     652    12440153 :   for (int index = 0; index < input_count; ++index) {
     653     3829265 :     if (!IsTyped(GetValueInput(node, index))) return false;
     654             :   }
     655             :   return true;
     656             : }
     657             : 
     658             : 
     659             : // static
     660             : bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
     661   443395729 :   if (num == 0) return false;
     662             :   int const index = edge.index();
     663   302346871 :   return first <= index && index < first + num;
     664             : }
     665             : 
     666             : // static
     667   119579438 : size_t NodeProperties::HashCode(Node* node) {
     668   119579438 :   size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount());
     669   423264451 :   for (Node* input : node->inputs()) {
     670             :     h = base::hash_combine(h, input->id());
     671             :   }
     672   119575732 :   return h;
     673             : }
     674             : 
     675             : // static
     676    75875162 : bool NodeProperties::Equals(Node* a, Node* b) {
     677             :   DCHECK_NOT_NULL(a);
     678             :   DCHECK_NOT_NULL(b);
     679             :   DCHECK_NOT_NULL(a->op());
     680             :   DCHECK_NOT_NULL(b->op());
     681    75875162 :   if (!a->op()->Equals(b->op())) return false;
     682     4410154 :   if (a->InputCount() != b->InputCount()) return false;
     683             :   Node::Inputs aInputs = a->inputs();
     684             :   Node::Inputs bInputs = b->inputs();
     685             : 
     686             :   auto aIt = aInputs.begin();
     687             :   auto bIt = bInputs.begin();
     688             :   auto aEnd = aInputs.end();
     689             : 
     690    10804007 :   for (; aIt != aEnd; ++aIt, ++bIt) {
     691             :     DCHECK_NOT_NULL(*aIt);
     692             :     DCHECK_NOT_NULL(*bIt);
     693     7798051 :     if ((*aIt)->id() != (*bIt)->id()) return false;
     694             :   }
     695             :   return true;
     696             : }
     697             : 
     698             : }  // namespace compiler
     699             : }  // namespace internal
     700      120216 : }  // namespace v8

Generated by: LCOV version 1.10