LCOV - code coverage report
Current view: top level - src/compiler - node-properties.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 159 164 97.0 %
Date: 2017-04-26 Functions: 34 36 94.4 %

          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   814240994 : int NodeProperties::PastValueIndex(Node* node) {
      23   814257378 :   return FirstValueIndex(node) + node->op()->ValueInputCount();
      24             : }
      25             : 
      26             : 
      27             : // static
      28          21 : int NodeProperties::PastContextIndex(Node* node) {
      29             :   return FirstContextIndex(node) +
      30   811154284 :          OperatorProperties::GetContextInputCount(node->op());
      31             : }
      32             : 
      33             : 
      34             : // static
      35  1602297412 : int NodeProperties::PastFrameStateIndex(Node* node) {
      36             :   return FirstFrameStateIndex(node) +
      37   801091076 :          OperatorProperties::GetFrameStateInputCount(node->op());
      38             : }
      39             : 
      40             : 
      41             : // static
      42   658113392 : int NodeProperties::PastEffectIndex(Node* node) {
      43  1164212134 :   return FirstEffectIndex(node) + node->op()->EffectInputCount();
      44             : }
      45             : 
      46             : 
      47             : // static
      48    50728216 : int NodeProperties::PastControlIndex(Node* node) {
      49   101455406 :   return FirstControlIndex(node) + node->op()->ControlInputCount();
      50             : }
      51             : 
      52             : 
      53             : // static
      54    42587821 : Node* NodeProperties::GetValueInput(Node* node, int index) {
      55             :   DCHECK(0 <= index && index < node->op()->ValueInputCount());
      56    42587821 :   return node->InputAt(FirstValueIndex(node) + index);
      57             : }
      58             : 
      59             : 
      60             : // static
      61     1704019 : Node* NodeProperties::GetContextInput(Node* node) {
      62             :   DCHECK(OperatorProperties::HasContextInput(node->op()));
      63     1704019 :   return node->InputAt(FirstContextIndex(node));
      64             : }
      65             : 
      66             : 
      67             : // static
      68     3440945 : Node* NodeProperties::GetFrameStateInput(Node* node) {
      69             :   DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
      70     3440949 :   return node->InputAt(FirstFrameStateIndex(node));
      71             : }
      72             : 
      73             : 
      74             : // static
      75    99358501 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
      76             :   DCHECK(0 <= index && index < node->op()->EffectInputCount());
      77   198716868 :   return node->InputAt(FirstEffectIndex(node) + index);
      78             : }
      79             : 
      80             : 
      81             : // static
      82   261497051 : Node* NodeProperties::GetControlInput(Node* node, int index) {
      83             :   DCHECK(0 <= index && index < node->op()->ControlInputCount());
      84   522995136 :   return node->InputAt(FirstControlIndex(node) + index);
      85             : }
      86             : 
      87             : 
      88             : // static
      89     1148241 : bool NodeProperties::IsValueEdge(Edge edge) {
      90     1148241 :   Node* const node = edge.from();
      91             :   return IsInputRange(edge, FirstValueIndex(node),
      92     2296482 :                       node->op()->ValueInputCount());
      93             : }
      94             : 
      95             : 
      96             : // static
      97           0 : bool NodeProperties::IsContextEdge(Edge edge) {
      98           0 :   Node* const node = edge.from();
      99             :   return IsInputRange(edge, FirstContextIndex(node),
     100           0 :                       OperatorProperties::GetContextInputCount(node->op()));
     101             : }
     102             : 
     103             : 
     104             : // static
     105      519797 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
     106      519797 :   Node* const node = edge.from();
     107             :   return IsInputRange(edge, FirstFrameStateIndex(node),
     108      519797 :                       OperatorProperties::GetFrameStateInputCount(node->op()));
     109             : }
     110             : 
     111             : 
     112             : // static
     113   103577177 : bool NodeProperties::IsEffectEdge(Edge edge) {
     114   103577177 :   Node* const node = edge.from();
     115             :   return IsInputRange(edge, FirstEffectIndex(node),
     116   207153264 :                       node->op()->EffectInputCount());
     117             : }
     118             : 
     119             : 
     120             : // static
     121   185791501 : bool NodeProperties::IsControlEdge(Edge edge) {
     122   185791501 :   Node* const node = edge.from();
     123             :   return IsInputRange(edge, FirstControlIndex(node),
     124   371576459 :                       node->op()->ControlInputCount());
     125             : }
     126             : 
     127             : 
     128             : // static
     129    13123235 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
     130    13123235 :   if (node->op()->HasProperty(Operator::kNoThrow)) return false;
     131   101157954 :   for (Edge const edge : node->use_edges()) {
     132    44669237 :     if (!NodeProperties::IsControlEdge(edge)) continue;
     133    32200990 :     if (edge.from()->opcode() == IrOpcode::kIfException) {
     134     1183644 :       if (out_exception != nullptr) *out_exception = edge.from();
     135     1179796 :       return true;
     136             :     }
     137             :   }
     138    11819480 :   return false;
     139             : }
     140             : 
     141             : 
     142             : // static
     143      191015 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
     144             :   DCHECK(index < node->op()->ValueInputCount());
     145      191015 :   node->ReplaceInput(FirstValueIndex(node) + index, value);
     146      191015 : }
     147             : 
     148             : 
     149             : // static
     150         583 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
     151         583 :   int value_input_count = node->op()->ValueInputCount();
     152             :   DCHECK_LE(1, value_input_count);
     153         583 :   node->ReplaceInput(0, value);
     154        2295 :   while (--value_input_count > 0) {
     155        1129 :     node->RemoveInput(value_input_count);
     156             :   }
     157         583 : }
     158             : 
     159             : 
     160             : // static
     161      505327 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
     162      505327 :   node->ReplaceInput(FirstContextIndex(node), context);
     163      505326 : }
     164             : 
     165             : 
     166             : // static
     167     8089615 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
     168             :   DCHECK(index < node->op()->ControlInputCount());
     169     8089609 :   node->ReplaceInput(FirstControlIndex(node) + index, control);
     170     8089589 : }
     171             : 
     172             : 
     173             : // static
     174     3936178 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
     175             :   DCHECK(index < node->op()->EffectInputCount());
     176     3936169 :   return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
     177             : }
     178             : 
     179             : 
     180             : // static
     181     6086861 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
     182             :   DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
     183     6086863 :   node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
     184     6086864 : }
     185             : 
     186             : 
     187             : // static
     188      348815 : void NodeProperties::RemoveNonValueInputs(Node* node) {
     189      697630 :   node->TrimInputCount(node->op()->ValueInputCount());
     190      348815 : }
     191             : 
     192             : 
     193             : // static
     194           8 : void NodeProperties::RemoveValueInputs(Node* node) {
     195           8 :   int value_input_count = node->op()->ValueInputCount();
     196          32 :   while (--value_input_count >= 0) {
     197          16 :     node->RemoveInput(value_input_count);
     198             :   }
     199           8 : }
     200             : 
     201             : 
     202      613284 : void NodeProperties::MergeControlToEnd(Graph* graph,
     203             :                                        CommonOperatorBuilder* common,
     204             :                                        Node* node) {
     205      204428 :   graph->end()->AppendInput(graph->zone(), node);
     206      204428 :   graph->end()->set_op(common->End(graph->end()->InputCount()));
     207      204428 : }
     208             : 
     209             : 
     210             : // static
     211     1640758 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
     212             :                                  Node* success, Node* exception) {
     213             :   // Requires distinguishing between value, effect and control edges.
     214    10138473 :   for (Edge edge : node->use_edges()) {
     215     4248853 :     if (IsControlEdge(edge)) {
     216     4687050 :       if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
     217             :         DCHECK_NOT_NULL(success);
     218       25471 :         edge.UpdateTo(success);
     219     3073758 :       } else if (edge.from()->opcode() == IrOpcode::kIfException) {
     220             :         DCHECK_NOT_NULL(exception);
     221       10899 :         edge.UpdateTo(exception);
     222             :       } else {
     223             :         DCHECK_NOT_NULL(success);
     224     1525980 :         edge.UpdateTo(success);
     225             :       }
     226     2686514 :     } else if (IsEffectEdge(edge)) {
     227             :       DCHECK_NOT_NULL(effect);
     228     1483435 :       edge.UpdateTo(effect);
     229             :     } else {
     230             :       DCHECK_NOT_NULL(value);
     231     1203088 :       edge.UpdateTo(value);
     232             :     }
     233             :   }
     234     1640767 : }
     235             : 
     236             : 
     237             : // static
     238    22699112 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
     239             :   node->set_op(new_op);
     240             :   Verifier::VerifyNode(node);
     241    22699112 : }
     242             : 
     243             : 
     244             : // static
     245       50910 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
     246      280607 :   Node* effect = NodeProperties::GetEffectInput(node);
     247      280607 :   while (effect->opcode() != IrOpcode::kCheckpoint) {
     248      178787 :     if (effect->opcode() == IrOpcode::kDead) return effect;
     249             :     DCHECK_EQ(1, effect->op()->EffectInputCount());
     250      178787 :     effect = NodeProperties::GetEffectInput(effect);
     251             :   }
     252       50910 :   Node* frame_state = GetFrameStateInput(effect);
     253       50910 :   return frame_state;
     254             : }
     255             : 
     256             : // static
     257      196807 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
     258      393915 :   for (auto use : node->uses()) {
     259      393598 :     if (use->opcode() == IrOpcode::kProjection &&
     260      196787 :         ProjectionIndexOf(use->op()) == projection_index) {
     261             :       return use;
     262             :     }
     263             :   }
     264             :   return nullptr;
     265             : }
     266             : 
     267             : 
     268             : // static
     269     8054470 : void NodeProperties::CollectControlProjections(Node* node, Node** projections,
     270             :                                                size_t projection_count) {
     271             : #ifdef DEBUG
     272             :   DCHECK_LE(static_cast<int>(projection_count), node->UseCount());
     273             :   std::memset(projections, 0, sizeof(*projections) * projection_count);
     274             : #endif
     275             :   size_t if_value_index = 0;
     276    49083962 :   for (Edge const edge : node->use_edges()) {
     277    20514781 :     if (!IsControlEdge(edge)) continue;
     278    16237072 :     Node* use = edge.from();
     279             :     size_t index;
     280    16237072 :     switch (use->opcode()) {
     281             :       case IrOpcode::kIfTrue:
     282             :         DCHECK_EQ(IrOpcode::kBranch, node->opcode());
     283             :         index = 0;
     284             :         break;
     285             :       case IrOpcode::kIfFalse:
     286             :         DCHECK_EQ(IrOpcode::kBranch, node->opcode());
     287             :         index = 1;
     288     7091812 :         break;
     289             :       case IrOpcode::kIfSuccess:
     290             :         DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
     291             :         index = 0;
     292             :         break;
     293             :       case IrOpcode::kIfException:
     294             :         DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
     295             :         index = 1;
     296      926118 :         break;
     297             :       case IrOpcode::kIfValue:
     298             :         DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
     299      165030 :         index = if_value_index++;
     300      165030 :         break;
     301             :       case IrOpcode::kIfDefault:
     302             :         DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
     303       36475 :         index = projection_count - 1;
     304       36475 :         break;
     305             :       default:
     306             :         continue;
     307             :     }
     308             :     DCHECK_LT(if_value_index, projection_count);
     309             :     DCHECK_LT(index, projection_count);
     310             :     DCHECK_NULL(projections[index]);
     311    16237001 :     projections[index] = use;
     312             :   }
     313             : #ifdef DEBUG
     314             :   for (size_t index = 0; index < projection_count; ++index) {
     315             :     DCHECK_NOT_NULL(projections[index]);
     316             :   }
     317             : #endif
     318     8054400 : }
     319             : 
     320             : // static
     321     3123644 : bool NodeProperties::IsSame(Node* a, Node* b) {
     322             :   for (;;) {
     323     1581121 :     if (a->opcode() == IrOpcode::kCheckHeapObject) {
     324             :       a = GetValueInput(a, 0);
     325          84 :       continue;
     326             :     }
     327     1581037 :     if (b->opcode() == IrOpcode::kCheckHeapObject) {
     328             :       b = GetValueInput(b, 0);
     329       38430 :       continue;
     330             :     }
     331     1542607 :     return a == b;
     332             :   }
     333             : }
     334             : 
     335             : // static
     336      193496 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
     337     1563016 :     Node* receiver, Node* effect, ZoneHandleSet<Map>* maps_return) {
     338             :   HeapObjectMatcher m(receiver);
     339      193496 :   if (m.HasValue()) {
     340             :     Handle<Map> receiver_map(m.Value()->map());
     341       95010 :     if (receiver_map->is_stable()) {
     342             :       // The {receiver_map} is only reliable when we install a stability
     343             :       // code dependency.
     344       90851 :       *maps_return = ZoneHandleSet<Map>(receiver_map);
     345             :       return kUnreliableReceiverMaps;
     346             :     }
     347             :   }
     348             :   InferReceiverMapsResult result = kReliableReceiverMaps;
     349             :   while (true) {
     350     1563016 :     switch (effect->opcode()) {
     351             :       case IrOpcode::kCheckMaps: {
     352             :         Node* const object = GetValueInput(effect, 0);
     353       51837 :         if (IsSame(receiver, object)) {
     354       26050 :           *maps_return = CheckMapsParametersOf(effect->op()).maps();
     355       26050 :           return result;
     356             :         }
     357             :         break;
     358             :       }
     359             :       case IrOpcode::kJSCreate: {
     360         698 :         if (IsSame(receiver, effect)) {
     361             :           HeapObjectMatcher mtarget(GetValueInput(effect, 0));
     362             :           HeapObjectMatcher mnewtarget(GetValueInput(effect, 1));
     363         520 :           if (mtarget.HasValue() && mnewtarget.HasValue()) {
     364             :             Handle<JSFunction> original_constructor =
     365             :                 Handle<JSFunction>::cast(mnewtarget.Value());
     366         520 :             if (original_constructor->has_initial_map()) {
     367             :               Handle<Map> initial_map(original_constructor->initial_map());
     368         520 :               if (initial_map->constructor_or_backpointer() ==
     369             :                   *mtarget.Value()) {
     370         520 :                 *maps_return = ZoneHandleSet<Map>(initial_map);
     371             :                 return result;
     372             :               }
     373             :             }
     374             :           }
     375             :           // We reached the allocation of the {receiver}.
     376             :           return kNoReceiverMaps;
     377             :         }
     378             :         break;
     379             :       }
     380             :       case IrOpcode::kStoreField: {
     381             :         // We only care about StoreField of maps.
     382             :         Node* const object = GetValueInput(effect, 0);
     383        9922 :         FieldAccess const& access = FieldAccessOf(effect->op());
     384        9922 :         if (access.base_is_tagged == kTaggedBase &&
     385             :             access.offset == HeapObject::kMapOffset) {
     386        3351 :           if (IsSame(receiver, object)) {
     387             :             Node* const value = GetValueInput(effect, 1);
     388             :             HeapObjectMatcher m(value);
     389        2790 :             if (m.HasValue()) {
     390        2790 :               *maps_return = ZoneHandleSet<Map>(Handle<Map>::cast(m.Value()));
     391             :               return result;
     392             :             }
     393             :           }
     394             :           // Without alias analysis we cannot tell whether this
     395             :           // StoreField[map] affects {receiver} or not.
     396             :           result = kUnreliableReceiverMaps;
     397             :         }
     398             :         break;
     399             :       }
     400             :       case IrOpcode::kJSStoreMessage:
     401             :       case IrOpcode::kJSStoreModule:
     402             :       case IrOpcode::kStoreElement:
     403             :       case IrOpcode::kStoreTypedElement: {
     404             :         // These never change the map of objects.
     405             :         break;
     406             :       }
     407             :       case IrOpcode::kFinishRegion: {
     408             :         // FinishRegion renames the output of allocations, so we need
     409             :         // to update the {receiver} that we are looking for, if the
     410             :         // {receiver} matches the current {effect}.
     411        3351 :         if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
     412             :         break;
     413             :       }
     414             :       default: {
     415             :         DCHECK_EQ(1, effect->op()->EffectOutputCount());
     416     1488586 :         if (effect->op()->EffectInputCount() != 1) {
     417             :           // Didn't find any appropriate CheckMaps node.
     418             :           return kNoReceiverMaps;
     419             :         }
     420     1438000 :         if (!effect->op()->HasProperty(Operator::kNoWrite)) {
     421             :           // Without alias/escape analysis we cannot tell whether this
     422             :           // {effect} affects {receiver} or not.
     423             :           result = kUnreliableReceiverMaps;
     424             :         }
     425             :         break;
     426             :       }
     427             :     }
     428             : 
     429             :     // Stop walking the effect chain once we hit the definition of
     430             :     // the {receiver} along the {effect}s.
     431     1483070 :     if (IsSame(receiver, effect)) return kNoReceiverMaps;
     432             : 
     433             :     // Continue with the next {effect}.
     434             :     DCHECK_EQ(1, effect->op()->EffectInputCount());
     435     1460371 :     effect = NodeProperties::GetEffectInput(effect);
     436     1460371 :   }
     437             : }
     438             : 
     439             : // static
     440      773126 : MaybeHandle<Context> NodeProperties::GetSpecializationContext(
     441      773126 :     Node* node, MaybeHandle<Context> context) {
     442      773126 :   switch (node->opcode()) {
     443             :     case IrOpcode::kHeapConstant:
     444             :       return Handle<Context>::cast(OpParameter<Handle<HeapObject>>(node));
     445             :     case IrOpcode::kParameter: {
     446      262949 :       Node* const start = NodeProperties::GetValueInput(node, 0);
     447             :       DCHECK_EQ(IrOpcode::kStart, start->opcode());
     448      262949 :       int const index = ParameterIndexOf(node->op());
     449             :       // The context is always the last parameter to a JavaScript function, and
     450             :       // {Parameter} indices start at -1, so value outputs of {Start} look like
     451             :       // this: closure, receiver, param0, ..., paramN, context.
     452      525898 :       if (index == start->op()->ValueOutputCount() - 2) {
     453      262893 :         return context;
     454             :       }
     455             :       break;
     456             :     }
     457             :     default:
     458             :       break;
     459             :   }
     460             :   return MaybeHandle<Context>();
     461             : }
     462             : 
     463             : 
     464             : // static
     465      773125 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
     466       13410 :   Node* context = NodeProperties::GetContextInput(node);
     467     1563417 :   while (*depth > 0 &&
     468             :          IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
     469             :     context = NodeProperties::GetContextInput(context);
     470        3757 :     (*depth)--;
     471             :   }
     472      773125 :   return context;
     473             : }
     474             : 
     475             : // static
     476           0 : Type* NodeProperties::GetTypeOrAny(Node* node) {
     477           0 :   return IsTyped(node) ? node->type() : Type::Any();
     478             : }
     479             : 
     480             : 
     481             : // static
     482     2538552 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
     483     2538552 :   int input_count = node->op()->ValueInputCount();
     484     3539881 :   for (int index = 0; index < input_count; ++index) {
     485     1068319 :     if (!IsTyped(GetValueInput(node, index))) return false;
     486             :   }
     487             :   return true;
     488             : }
     489             : 
     490             : 
     491             : // static
     492             : bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
     493   291029083 :   if (num == 0) return false;
     494             :   int const index = edge.index();
     495   221579592 :   return first <= index && index < first + num;
     496             : }
     497             : 
     498             : }  // namespace compiler
     499             : }  // namespace internal
     500             : }  // namespace v8

Generated by: LCOV version 1.10