LCOV - code coverage report
Current view: top level - src/compiler - node-properties.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 215 230 93.5 %
Date: 2019-01-20 Functions: 43 46 93.5 %

          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             : #include "src/zone/zone-handle-set.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace compiler {
      21             : 
      22             : // static
      23  1086960339 : int NodeProperties::PastValueIndex(Node* node) {
      24  1087113055 :   return FirstValueIndex(node) + node->op()->ValueInputCount();
      25             : }
      26             : 
      27             : 
      28             : // static
      29         501 : int NodeProperties::PastContextIndex(Node* node) {
      30             :   return FirstContextIndex(node) +
      31  1080260046 :          OperatorProperties::GetContextInputCount(node->op());
      32             : }
      33             : 
      34             : 
      35             : // static
      36  2136580776 : int NodeProperties::PastFrameStateIndex(Node* node) {
      37             :   return FirstFrameStateIndex(node) +
      38  1068193455 :          OperatorProperties::GetFrameStateInputCount(node->op());
      39             : }
      40             : 
      41             : 
      42             : // static
      43   712692555 : int NodeProperties::PastEffectIndex(Node* node) {
      44  1261302716 :   return FirstEffectIndex(node) + node->op()->EffectInputCount();
      45             : }
      46             : 
      47             : 
      48             : // static
      49    59695063 : int NodeProperties::PastControlIndex(Node* node) {
      50   119390358 :   return FirstControlIndex(node) + node->op()->ControlInputCount();
      51             : }
      52             : 
      53             : 
      54             : // static
      55   153992285 : Node* NodeProperties::GetValueInput(Node* node, int index) {
      56             :   DCHECK(0 <= index && index < node->op()->ValueInputCount());
      57   153992285 :   return node->InputAt(FirstValueIndex(node) + index);
      58             : }
      59             : 
      60             : 
      61             : // static
      62     5224454 : Node* NodeProperties::GetContextInput(Node* node) {
      63             :   DCHECK(OperatorProperties::HasContextInput(node->op()));
      64     5224454 :   return node->InputAt(FirstContextIndex(node));
      65             : }
      66             : 
      67             : 
      68             : // static
      69     4339555 : Node* NodeProperties::GetFrameStateInput(Node* node) {
      70             :   DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
      71     4339565 :   return node->InputAt(FirstFrameStateIndex(node));
      72             : }
      73             : 
      74             : 
      75             : // static
      76   223446998 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
      77             :   DCHECK(0 <= index && index < node->op()->EffectInputCount());
      78   446883340 :   return node->InputAt(FirstEffectIndex(node) + index);
      79             : }
      80             : 
      81             : 
      82             : // static
      83   300712066 : Node* NodeProperties::GetControlInput(Node* node, int index) {
      84             :   DCHECK(0 <= index && index < node->op()->ControlInputCount());
      85   300674043 :   return node->InputAt(FirstControlIndex(node) + index);
      86             : }
      87             : 
      88             : 
      89             : // static
      90     8263794 : bool NodeProperties::IsValueEdge(Edge edge) {
      91     8263794 :   Node* const node = edge.from();
      92             :   return IsInputRange(edge, FirstValueIndex(node),
      93    16527588 :                       node->op()->ValueInputCount());
      94             : }
      95             : 
      96             : 
      97             : // static
      98           0 : bool NodeProperties::IsContextEdge(Edge edge) {
      99           0 :   Node* const node = edge.from();
     100             :   return IsInputRange(edge, FirstContextIndex(node),
     101           0 :                       OperatorProperties::GetContextInputCount(node->op()));
     102             : }
     103             : 
     104             : 
     105             : // static
     106      543022 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
     107      543022 :   Node* const node = edge.from();
     108             :   return IsInputRange(edge, FirstFrameStateIndex(node),
     109      543022 :                       OperatorProperties::GetFrameStateInputCount(node->op()));
     110             : }
     111             : 
     112             : 
     113             : // static
     114   195683825 : bool NodeProperties::IsEffectEdge(Edge edge) {
     115   195683825 :   Node* const node = edge.from();
     116             :   return IsInputRange(edge, FirstEffectIndex(node),
     117   391363738 :                       node->op()->EffectInputCount());
     118             : }
     119             : 
     120             : 
     121             : // static
     122   176774009 : bool NodeProperties::IsControlEdge(Edge edge) {
     123   176774009 :   Node* const node = edge.from();
     124             :   return IsInputRange(edge, FirstControlIndex(node),
     125   353543813 :                       node->op()->ControlInputCount());
     126             : }
     127             : 
     128             : 
     129             : // static
     130    11284618 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
     131    11284618 :   if (node->op()->HasProperty(Operator::kNoThrow)) return false;
     132   124808395 :   for (Edge const edge : node->use_edges()) {
     133    51468890 :     if (!NodeProperties::IsControlEdge(edge)) continue;
     134    36935228 :     if (edge.from()->opcode() == IrOpcode::kIfException) {
     135      711513 :       if (out_exception != nullptr) *out_exception = edge.from();
     136      698644 :       return true;
     137             :     }
     138             :   }
     139    10586023 :   return false;
     140             : }
     141             : 
     142             : // static
     143        1600 : Node* NodeProperties::FindSuccessfulControlProjection(Node* node) {
     144             :   DCHECK_GT(node->op()->ControlOutputCount(), 0);
     145        1600 :   if (node->op()->HasProperty(Operator::kNoThrow)) return node;
     146       53432 :   for (Edge const edge : node->use_edges()) {
     147       25224 :     if (!NodeProperties::IsControlEdge(edge)) continue;
     148       17096 :     if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
     149         216 :       return edge.from();
     150             :     }
     151             :   }
     152        1384 :   return node;
     153             : }
     154             : 
     155             : // static
     156      892206 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
     157             :   DCHECK(index < node->op()->ValueInputCount());
     158      892206 :   node->ReplaceInput(FirstValueIndex(node) + index, value);
     159      892206 : }
     160             : 
     161             : 
     162             : // static
     163         829 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
     164         829 :   int value_input_count = node->op()->ValueInputCount();
     165             :   DCHECK_LE(1, value_input_count);
     166         829 :   node->ReplaceInput(0, value);
     167        3065 :   while (--value_input_count > 0) {
     168        1407 :     node->RemoveInput(value_input_count);
     169             :   }
     170         829 : }
     171             : 
     172             : 
     173             : // static
     174      391389 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
     175      391389 :   node->ReplaceInput(FirstContextIndex(node), context);
     176      391389 : }
     177             : 
     178             : 
     179             : // static
     180    11471532 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
     181             :   DCHECK(index < node->op()->ControlInputCount());
     182    11471540 :   node->ReplaceInput(FirstControlIndex(node) + index, control);
     183    11471536 : }
     184             : 
     185             : 
     186             : // static
     187     4294908 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
     188             :   DCHECK(index < node->op()->EffectInputCount());
     189     4294909 :   return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
     190             : }
     191             : 
     192             : 
     193             : // static
     194     7128926 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
     195             :   DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
     196     7128930 :   node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
     197     7128937 : }
     198             : 
     199             : 
     200             : // static
     201      110546 : void NodeProperties::RemoveNonValueInputs(Node* node) {
     202      221092 :   node->TrimInputCount(node->op()->ValueInputCount());
     203      110546 : }
     204             : 
     205             : 
     206             : // static
     207           0 : void NodeProperties::RemoveValueInputs(Node* node) {
     208           0 :   int value_input_count = node->op()->ValueInputCount();
     209           0 :   while (--value_input_count >= 0) {
     210           0 :     node->RemoveInput(value_input_count);
     211             :   }
     212           0 : }
     213             : 
     214             : 
     215     1988480 : void NodeProperties::MergeControlToEnd(Graph* graph,
     216             :                                        CommonOperatorBuilder* common,
     217             :                                        Node* node) {
     218      662824 :   graph->end()->AppendInput(graph->zone(), node);
     219      662829 :   graph->end()->set_op(common->End(graph->end()->InputCount()));
     220      662827 : }
     221             : 
     222             : 
     223             : // static
     224     2007367 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
     225             :                                  Node* success, Node* exception) {
     226             :   // Requires distinguishing between value, effect and control edges.
     227    16752302 :   for (Edge edge : node->use_edges()) {
     228     6368769 :     if (IsControlEdge(edge)) {
     229     6531825 :       if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
     230             :         DCHECK_NOT_NULL(success);
     231       27176 :         edge.UpdateTo(success);
     232     4300198 :       } else if (edge.from()->opcode() == IrOpcode::kIfException) {
     233             :         DCHECK_NOT_NULL(exception);
     234        8270 :         edge.UpdateTo(exception);
     235             :       } else {
     236             :         DCHECK_NOT_NULL(success);
     237     2141829 :         edge.UpdateTo(success);
     238             :       }
     239     4191560 :     } else if (IsEffectEdge(edge)) {
     240             :       DCHECK_NOT_NULL(effect);
     241     1825979 :       edge.UpdateTo(effect);
     242             :     } else {
     243             :       DCHECK_NOT_NULL(value);
     244     2365578 :       edge.UpdateTo(value);
     245             :     }
     246             :   }
     247     2007397 : }
     248             : 
     249             : 
     250             : // static
     251    39362668 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
     252             :   node->set_op(new_op);
     253             :   Verifier::VerifyNode(node);
     254    39362668 : }
     255             : 
     256             : 
     257             : // static
     258       89214 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
     259      353631 :   Node* effect = NodeProperties::GetEffectInput(node);
     260      353631 :   while (effect->opcode() != IrOpcode::kCheckpoint) {
     261      175203 :     if (effect->opcode() == IrOpcode::kDead) return effect;
     262             :     DCHECK_EQ(1, effect->op()->EffectInputCount());
     263      175203 :     effect = NodeProperties::GetEffectInput(effect);
     264             :   }
     265       89214 :   Node* frame_state = GetFrameStateInput(effect);
     266       89214 :   return frame_state;
     267             : }
     268             : 
     269             : // static
     270      206191 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
     271      618915 :   for (auto use : node->uses()) {
     272      412391 :     if (use->opcode() == IrOpcode::kProjection &&
     273      206185 :         ProjectionIndexOf(use->op()) == projection_index) {
     274             :       return use;
     275             :     }
     276             :   }
     277             :   return nullptr;
     278             : }
     279             : 
     280             : 
     281             : // static
     282           0 : void NodeProperties::CollectValueProjections(Node* node, Node** projections,
     283             :                                              size_t projection_count) {
     284             : #ifdef DEBUG
     285             :   for (size_t index = 0; index < projection_count; ++index) {
     286             :     DCHECK_NULL(projections[index]);
     287             :   }
     288             : #endif
     289           0 :   for (Edge const edge : node->use_edges()) {
     290           0 :     if (!IsValueEdge(edge)) continue;
     291           0 :     Node* use = edge.from();
     292             :     DCHECK_EQ(IrOpcode::kProjection, use->opcode());
     293           0 :     projections[ProjectionIndexOf(use->op())] = use;
     294             :   }
     295           0 : }
     296             : 
     297             : 
     298             : // static
     299    10609647 : void NodeProperties::CollectControlProjections(Node* node, Node** projections,
     300             :                                                size_t projection_count) {
     301             : #ifdef DEBUG
     302             :   DCHECK_LE(static_cast<int>(projection_count), node->UseCount());
     303             :   std::memset(projections, 0, sizeof(*projections) * projection_count);
     304             : #endif
     305             :   size_t if_value_index = 0;
     306    70777251 :   for (Edge const edge : node->use_edges()) {
     307    24778970 :     if (!IsControlEdge(edge)) continue;
     308    21896016 :     Node* use = edge.from();
     309             :     size_t index;
     310    21896016 :     switch (use->opcode()) {
     311             :       case IrOpcode::kIfTrue:
     312             :         DCHECK_EQ(IrOpcode::kBranch, node->opcode());
     313             :         index = 0;
     314             :         break;
     315             :       case IrOpcode::kIfFalse:
     316             :         DCHECK_EQ(IrOpcode::kBranch, node->opcode());
     317             :         index = 1;
     318     9853496 :         break;
     319             :       case IrOpcode::kIfSuccess:
     320             :         DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
     321             :         index = 0;
     322             :         break;
     323             :       case IrOpcode::kIfException:
     324             :         DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
     325             :         index = 1;
     326      683995 :         break;
     327             :       case IrOpcode::kIfValue:
     328             :         DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
     329      748881 :         index = if_value_index++;
     330      748881 :         break;
     331             :       case IrOpcode::kIfDefault:
     332             :         DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
     333       72176 :         index = projection_count - 1;
     334       72176 :         break;
     335             :       default:
     336             :         continue;
     337             :     }
     338             :     DCHECK_LT(if_value_index, projection_count);
     339             :     DCHECK_LT(index, projection_count);
     340             :     DCHECK_NULL(projections[index]);
     341    21895975 :     projections[index] = use;
     342             :   }
     343             : #ifdef DEBUG
     344             :   for (size_t index = 0; index < projection_count; ++index) {
     345             :     DCHECK_NOT_NULL(projections[index]);
     346             :   }
     347             : #endif
     348    10609664 : }
     349             : 
     350             : // static
     351    20284551 : bool NodeProperties::IsSame(Node* a, Node* b) {
     352             :   for (;;) {
     353    10169586 :     if (a->opcode() == IrOpcode::kCheckHeapObject) {
     354             :       a = GetValueInput(a, 0);
     355        1591 :       continue;
     356             :     }
     357    10167995 :     if (b->opcode() == IrOpcode::kCheckHeapObject) {
     358             :       b = GetValueInput(b, 0);
     359       51439 :       continue;
     360             :     }
     361    10116556 :     return a == b;
     362             :   }
     363             : }
     364             : 
     365             : // static
     366      206386 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
     367    10150008 :     JSHeapBroker* broker, Node* receiver, Node* effect,
     368             :     ZoneHandleSet<Map>* maps_return) {
     369             :   HeapObjectMatcher m(receiver);
     370      206386 :   if (m.HasValue()) {
     371       75791 :     HeapObjectRef receiver = m.Ref(broker).AsHeapObject();
     372             :     // We don't use ICs for the Array.prototype and the Object.prototype
     373             :     // because the runtime has to be able to intercept them properly, so
     374             :     // we better make sure that TurboFan doesn't outsmart the system here
     375             :     // by storing to elements of either prototype directly.
     376             :     //
     377             :     // TODO(bmeurer): This can be removed once the Array.prototype and
     378             :     // Object.prototype have NO_ELEMENTS elements kind.
     379      227373 :     if (!receiver.IsJSObject() ||
     380      214409 :         !broker->IsArrayOrObjectPrototype(receiver.AsJSObject())) {
     381       75542 :       if (receiver.map().is_stable()) {
     382             :         // The {receiver_map} is only reliable when we install a stability
     383             :         // code dependency.
     384       67626 :         *maps_return = ZoneHandleSet<Map>(receiver.map().object());
     385       67626 :         return kUnreliableReceiverMaps;
     386             :       }
     387             :     }
     388             :   }
     389             :   InferReceiverMapsResult result = kReliableReceiverMaps;
     390             :   while (true) {
     391    10150008 :     switch (effect->opcode()) {
     392             :       case IrOpcode::kMapGuard: {
     393             :         Node* const object = GetValueInput(effect, 0);
     394         176 :         if (IsSame(receiver, object)) {
     395         134 :           *maps_return = MapGuardMapsOf(effect->op()).maps();
     396         134 :           return result;
     397             :         }
     398             :         break;
     399             :       }
     400             :       case IrOpcode::kCheckMaps: {
     401             :         Node* const object = GetValueInput(effect, 0);
     402       68559 :         if (IsSame(receiver, object)) {
     403       41893 :           *maps_return = CheckMapsParametersOf(effect->op()).maps();
     404       41891 :           return result;
     405             :         }
     406             :         break;
     407             :       }
     408             :       case IrOpcode::kJSCreate: {
     409        4029 :         if (IsSame(receiver, effect)) {
     410             :           HeapObjectMatcher mtarget(GetValueInput(effect, 0));
     411             :           HeapObjectMatcher mnewtarget(GetValueInput(effect, 1));
     412        9660 :           if (mtarget.HasValue() && mnewtarget.HasValue() &&
     413        9198 :               mnewtarget.Ref(broker).IsJSFunction()) {
     414             :             JSFunctionRef original_constructor =
     415        2982 :                 mnewtarget.Ref(broker).AsJSFunction();
     416        2982 :             if (original_constructor.has_initial_map()) {
     417        2982 :               original_constructor.Serialize();
     418        2982 :               MapRef initial_map = original_constructor.initial_map();
     419        2982 :               if (initial_map.GetConstructor().equals(mtarget.Ref(broker))) {
     420        2982 :                 *maps_return = ZoneHandleSet<Map>(initial_map.object());
     421        2982 :                 return result;
     422             :               }
     423             :             }
     424             :           }
     425             :           // We reached the allocation of the {receiver}.
     426             :           return kNoReceiverMaps;
     427             :         }
     428             :         break;
     429             :       }
     430             :       case IrOpcode::kJSCreatePromise: {
     431          85 :         if (IsSame(receiver, effect)) {
     432             :           *maps_return = ZoneHandleSet<Map>(broker->native_context()
     433          44 :                                                 .promise_function()
     434          44 :                                                 .initial_map()
     435          22 :                                                 .object());
     436          22 :           return result;
     437             :         }
     438             :         break;
     439             :       }
     440             :       case IrOpcode::kStoreField: {
     441             :         // We only care about StoreField of maps.
     442             :         Node* const object = GetValueInput(effect, 0);
     443       22757 :         FieldAccess const& access = FieldAccessOf(effect->op());
     444       22757 :         if (access.base_is_tagged == kTaggedBase &&
     445             :             access.offset == HeapObject::kMapOffset) {
     446        3821 :           if (IsSame(receiver, object)) {
     447             :             Node* const value = GetValueInput(effect, 1);
     448             :             HeapObjectMatcher m(value);
     449        2823 :             if (m.HasValue()) {
     450        2823 :               *maps_return = ZoneHandleSet<Map>(m.Ref(broker).AsMap().object());
     451             :               return result;
     452             :             }
     453             :           }
     454             :           // Without alias analysis we cannot tell whether this
     455             :           // StoreField[map] affects {receiver} or not.
     456             :           result = kUnreliableReceiverMaps;
     457             :         }
     458             :         break;
     459             :       }
     460             :       case IrOpcode::kJSStoreMessage:
     461             :       case IrOpcode::kJSStoreModule:
     462             :       case IrOpcode::kStoreElement:
     463             :       case IrOpcode::kStoreTypedElement: {
     464             :         // These never change the map of objects.
     465             :         break;
     466             :       }
     467             :       case IrOpcode::kFinishRegion: {
     468             :         // FinishRegion renames the output of allocations, so we need
     469             :         // to update the {receiver} that we are looking for, if the
     470             :         // {receiver} matches the current {effect}.
     471        3821 :         if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
     472             :         break;
     473             :       }
     474             :       case IrOpcode::kEffectPhi: {
     475       28243 :         Node* control = GetControlInput(effect);
     476       28243 :         if (control->opcode() != IrOpcode::kLoop) {
     477             :           DCHECK(control->opcode() == IrOpcode::kDead ||
     478             :                  control->opcode() == IrOpcode::kMerge);
     479             :           return kNoReceiverMaps;
     480             :         }
     481             : 
     482             :         // Continue search for receiver map outside the loop. Since operations
     483             :         // inside the loop may change the map, the result is unreliable.
     484       12121 :         effect = GetEffectInput(effect, 0);
     485             :         result = kUnreliableReceiverMaps;
     486       12121 :         continue;
     487             :       }
     488             :       default: {
     489             :         DCHECK_EQ(1, effect->op()->EffectOutputCount());
     490    10018808 :         if (effect->op()->EffectInputCount() != 1) {
     491             :           // Didn't find any appropriate CheckMaps node.
     492             :           return kNoReceiverMaps;
     493             :         }
     494     9981213 :         if (!effect->op()->HasProperty(Operator::kNoWrite)) {
     495             :           // Without alias/escape analysis we cannot tell whether this
     496             :           // {effect} affects {receiver} or not.
     497             :           result = kUnreliableReceiverMaps;
     498             :         }
     499             :         break;
     500             :       }
     501             :     }
     502             : 
     503             :     // Stop walking the effect chain once we hit the definition of
     504             :     // the {receiver} along the {effect}s.
     505    10036077 :     if (IsSame(receiver, effect)) return kNoReceiverMaps;
     506             : 
     507             :     // Continue with the next {effect}.
     508             :     DCHECK_EQ(1, effect->op()->EffectInputCount());
     509     9999126 :     effect = NodeProperties::GetEffectInput(effect);
     510             :   }
     511             : }
     512             : 
     513             : // static
     514        1023 : MaybeHandle<Map> NodeProperties::GetMapWitness(JSHeapBroker* broker,
     515             :                                                Node* node) {
     516             :   ZoneHandleSet<Map> maps;
     517             :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     518        1023 :   Node* effect = NodeProperties::GetEffectInput(node);
     519             :   NodeProperties::InferReceiverMapsResult result =
     520        1023 :       NodeProperties::InferReceiverMaps(broker, receiver, effect, &maps);
     521        2046 :   if (result == NodeProperties::kReliableReceiverMaps && maps.size() == 1) {
     522        1007 :     return maps[0];
     523             :   }
     524          16 :   return MaybeHandle<Map>();
     525             : }
     526             : 
     527             : // static
     528        1358 : bool NodeProperties::HasInstanceTypeWitness(JSHeapBroker* broker,
     529             :                                             Node* receiver, Node* effect,
     530             :                                             InstanceType instance_type) {
     531             :   ZoneHandleSet<Map> receiver_maps;
     532             :   NodeProperties::InferReceiverMapsResult result =
     533             :       NodeProperties::InferReceiverMaps(broker, receiver, effect,
     534        1358 :                                         &receiver_maps);
     535        1358 :   switch (result) {
     536             :     case NodeProperties::kUnreliableReceiverMaps:
     537             :     case NodeProperties::kReliableReceiverMaps:
     538             :       DCHECK_NE(0, receiver_maps.size());
     539        4584 :       for (size_t i = 0; i < receiver_maps.size(); ++i) {
     540             :         MapRef map(broker, receiver_maps[i]);
     541        1614 :         if (map.instance_type() != instance_type) return false;
     542             :       }
     543             :       return true;
     544             : 
     545             :     case NodeProperties::kNoReceiverMaps:
     546             :       return false;
     547             :   }
     548           0 :   UNREACHABLE();
     549             : }
     550             : 
     551             : // static
     552        2439 : bool NodeProperties::NoObservableSideEffectBetween(Node* effect,
     553             :                                                    Node* dominator) {
     554        2611 :   while (effect != dominator) {
     555        3647 :     if (effect->op()->EffectInputCount() == 1 &&
     556             :         effect->op()->properties() & Operator::kNoWrite) {
     557        1393 :       effect = NodeProperties::GetEffectInput(effect);
     558             :     } else {
     559             :       return false;
     560             :     }
     561             :   }
     562             :   return true;
     563             : }
     564             : 
     565             : // static
     566       59728 : bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
     567             :                                     Node* effect) {
     568       59728 :   switch (receiver->opcode()) {
     569             : #define CASE(Opcode) case IrOpcode::k##Opcode:
     570             :     JS_CONSTRUCT_OP_LIST(CASE)
     571             :     JS_CREATE_OP_LIST(CASE)
     572             : #undef CASE
     573             :     case IrOpcode::kCheckReceiver:
     574             :     case IrOpcode::kConvertReceiver:
     575             :     case IrOpcode::kJSGetSuperConstructor:
     576             :     case IrOpcode::kJSToObject:
     577             :       return false;
     578             :     case IrOpcode::kHeapConstant: {
     579             :       HeapObjectRef value =
     580       56681 :           HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
     581       56681 :       return value.map().IsPrimitiveMap();
     582             :     }
     583             :     default: {
     584             :       // We don't really care about the exact maps here,
     585             :       // just the instance types, which don't change
     586             :       // across potential side-effecting operations.
     587             :       ZoneHandleSet<Map> maps;
     588        2499 :       if (InferReceiverMaps(broker, receiver, effect, &maps) !=
     589             :           kNoReceiverMaps) {
     590             :         // Check if one of the {maps} is not a JSReceiver map.
     591        6101 :         for (size_t i = 0; i < maps.size(); ++i) {
     592             :           MapRef map(broker, maps[i]);
     593        2061 :           if (!map.IsJSReceiverMap()) return true;
     594             :         }
     595             :         return false;
     596             :       }
     597             :       return true;
     598             :     }
     599             :   }
     600             : }
     601             : 
     602             : // static
     603         879 : bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
     604             :                                           Node* effect) {
     605         649 :   if (CanBePrimitive(broker, receiver, effect)) {
     606         230 :     switch (receiver->opcode()) {
     607             :       case IrOpcode::kCheckInternalizedString:
     608             :       case IrOpcode::kCheckNumber:
     609             :       case IrOpcode::kCheckSmi:
     610             :       case IrOpcode::kCheckString:
     611             :       case IrOpcode::kCheckSymbol:
     612             :       case IrOpcode::kJSToLength:
     613             :       case IrOpcode::kJSToName:
     614             :       case IrOpcode::kJSToNumber:
     615             :       case IrOpcode::kJSToNumberConvertBigInt:
     616             :       case IrOpcode::kJSToNumeric:
     617             :       case IrOpcode::kJSToString:
     618             :       case IrOpcode::kToBoolean:
     619             :         return false;
     620             :       case IrOpcode::kHeapConstant: {
     621             :         HeapObjectRef value =
     622          92 :             HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
     623          92 :         OddballType type = value.map().oddball_type();
     624          92 :         return type == OddballType::kNull || type == OddballType::kUndefined;
     625             :       }
     626             :       default:
     627         138 :         return true;
     628             :     }
     629             :   }
     630             :   return false;
     631             : }
     632             : 
     633             : // static
     634      831324 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
     635       28720 :   Node* context = NodeProperties::GetContextInput(node);
     636     1707072 :   while (*depth > 0 &&
     637             :          IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
     638             :     context = NodeProperties::GetContextInput(context);
     639       15704 :     (*depth)--;
     640             :   }
     641      831324 :   return context;
     642             : }
     643             : 
     644             : // static
     645   709386705 : Type NodeProperties::GetTypeOrAny(Node* node) {
     646   709386705 :   return IsTyped(node) ? node->type() : Type::Any();
     647             : }
     648             : 
     649             : 
     650             : // static
     651     5131546 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
     652     5131546 :   int input_count = node->op()->ValueInputCount();
     653     9021096 :   for (int index = 0; index < input_count; ++index) {
     654     3946253 :     if (!IsTyped(GetValueInput(node, index))) return false;
     655             :   }
     656             :   return true;
     657             : }
     658             : 
     659             : 
     660             : // static
     661             : bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
     662   381256533 :   if (num == 0) return false;
     663             :   int const index = edge.index();
     664   258439459 :   return first <= index && index < first + num;
     665             : }
     666             : 
     667             : // static
     668   223583206 : size_t NodeProperties::HashCode(Node* node) {
     669   111791603 :   size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount());
     670   752479997 :   for (Node* input : node->inputs()) {
     671             :     h = base::hash_combine(h, input->id());
     672             :   }
     673   111788825 :   return h;
     674             : }
     675             : 
     676             : // static
     677   125610076 : bool NodeProperties::Equals(Node* a, Node* b) {
     678             :   DCHECK_NOT_NULL(a);
     679             :   DCHECK_NOT_NULL(b);
     680             :   DCHECK_NOT_NULL(a->op());
     681             :   DCHECK_NOT_NULL(b->op());
     682   125610076 :   if (!a->op()->Equals(b->op())) return false;
     683     3727964 :   if (a->InputCount() != b->InputCount()) return false;
     684             :   Node::Inputs aInputs = a->inputs();
     685             :   Node::Inputs bInputs = b->inputs();
     686             : 
     687             :   auto aIt = aInputs.begin();
     688             :   auto bIt = bInputs.begin();
     689             :   auto aEnd = aInputs.end();
     690             : 
     691    13598070 :   for (; aIt != aEnd; ++aIt, ++bIt) {
     692             :     DCHECK_NOT_NULL(*aIt);
     693             :     DCHECK_NOT_NULL(*bIt);
     694    22538298 :     if ((*aIt)->id() != (*bIt)->id()) return false;
     695             :   }
     696             :   return true;
     697             : }
     698             : 
     699             : }  // namespace compiler
     700             : }  // namespace internal
     701      183867 : }  // namespace v8

Generated by: LCOV version 1.10