LCOV - code coverage report
Current view: top level - src/compiler - typed-optimization.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 172 182 94.5 %
Date: 2017-10-20 Functions: 22 27 81.5 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/typed-optimization.h"
       6             : 
       7             : #include "src/compilation-dependencies.h"
       8             : #include "src/compiler/js-graph.h"
       9             : #include "src/compiler/node-properties.h"
      10             : #include "src/compiler/simplified-operator.h"
      11             : #include "src/compiler/type-cache.h"
      12             : #include "src/isolate-inl.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : namespace compiler {
      17             : 
      18      443514 : TypedOptimization::TypedOptimization(Editor* editor,
      19             :                                      CompilationDependencies* dependencies,
      20             :                                      JSGraph* jsgraph)
      21             :     : AdvancedReducer(editor),
      22             :       dependencies_(dependencies),
      23             :       jsgraph_(jsgraph),
      24      443514 :       true_type_(Type::HeapConstant(factory()->true_value(), graph()->zone())),
      25             :       false_type_(
      26      443516 :           Type::HeapConstant(factory()->false_value(), graph()->zone())),
      27     1330545 :       type_cache_(TypeCache::Get()) {}
      28             : 
      29      887030 : TypedOptimization::~TypedOptimization() {}
      30             : 
      31    63377566 : Reduction TypedOptimization::Reduce(Node* node) {
      32             :   // Check if the output type is a singleton.  In that case we already know the
      33             :   // result value and can simply replace the node if it's eliminable.
      34    78066498 :   if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
      35             :       node->op()->HasProperty(Operator::kEliminatable)) {
      36             :     // TODO(v8:5303): We must not eliminate FinishRegion here. This special
      37             :     // case can be removed once we have separate operators for value and
      38             :     // effect regions.
      39    14515079 :     if (node->opcode() == IrOpcode::kFinishRegion) return NoChange();
      40             :     // We can only constant-fold nodes here, that are known to not cause any
      41             :     // side-effect, may it be a JavaScript observable side-effect or a possible
      42             :     // eager deoptimization exit (i.e. {node} has an operator that doesn't have
      43             :     // the Operator::kNoDeopt property).
      44             :     Type* upper = NodeProperties::GetType(node);
      45    14283375 :     if (upper->IsInhabited()) {
      46    14283055 :       if (upper->IsHeapConstant()) {
      47             :         Node* replacement =
      48       60968 :             jsgraph()->Constant(upper->AsHeapConstant()->Value());
      49      119063 :         ReplaceWithValue(node, replacement);
      50             :         return Changed(replacement);
      51    14222084 :       } else if (upper->Is(Type::MinusZero())) {
      52          30 :         Node* replacement = jsgraph()->Constant(factory()->minus_zero_value());
      53             :         ReplaceWithValue(node, replacement);
      54             :         return Changed(replacement);
      55    14222053 :       } else if (upper->Is(Type::NaN())) {
      56         644 :         Node* replacement = jsgraph()->NaNConstant();
      57             :         ReplaceWithValue(node, replacement);
      58             :         return Changed(replacement);
      59    14221412 :       } else if (upper->Is(Type::Null())) {
      60           1 :         Node* replacement = jsgraph()->NullConstant();
      61             :         ReplaceWithValue(node, replacement);
      62             :         return Changed(replacement);
      63    14634073 :       } else if (upper->Is(Type::PlainNumber()) &&
      64      412671 :                  upper->Min() == upper->Max()) {
      65      114838 :         Node* replacement = jsgraph()->Constant(upper->Min());
      66             :         ReplaceWithValue(node, replacement);
      67             :         return Changed(replacement);
      68    14163979 :       } else if (upper->Is(Type::Undefined())) {
      69           1 :         Node* replacement = jsgraph()->UndefinedConstant();
      70             :         ReplaceWithValue(node, replacement);
      71             :         return Changed(replacement);
      72             :       }
      73             :     }
      74             :   }
      75    31453876 :   switch (node->opcode()) {
      76             :     case IrOpcode::kCheckHeapObject:
      77       44341 :       return ReduceCheckHeapObject(node);
      78             :     case IrOpcode::kCheckNotTaggedHole:
      79         952 :       return ReduceCheckNotTaggedHole(node);
      80             :     case IrOpcode::kCheckMaps:
      81       83195 :       return ReduceCheckMaps(node);
      82             :     case IrOpcode::kCheckNumber:
      83        1733 :       return ReduceCheckNumber(node);
      84             :     case IrOpcode::kCheckString:
      85        4487 :       return ReduceCheckString(node);
      86             :     case IrOpcode::kCheckSeqString:
      87        2416 :       return ReduceCheckSeqString(node);
      88             :     case IrOpcode::kCheckEqualsInternalizedString:
      89          88 :       return ReduceCheckEqualsInternalizedString(node);
      90             :     case IrOpcode::kCheckEqualsSymbol:
      91          34 :       return ReduceCheckEqualsSymbol(node);
      92             :     case IrOpcode::kLoadField:
      93     1223481 :       return ReduceLoadField(node);
      94             :     case IrOpcode::kNumberCeil:
      95             :     case IrOpcode::kNumberRound:
      96             :     case IrOpcode::kNumberTrunc:
      97        6821 :       return ReduceNumberRoundop(node);
      98             :     case IrOpcode::kNumberFloor:
      99        9261 :       return ReduceNumberFloor(node);
     100             :     case IrOpcode::kNumberToUint8Clamped:
     101         578 :       return ReduceNumberToUint8Clamped(node);
     102             :     case IrOpcode::kPhi:
     103      326211 :       return ReducePhi(node);
     104             :     case IrOpcode::kReferenceEqual:
     105      222133 :       return ReduceReferenceEqual(node);
     106             :     case IrOpcode::kSelect:
     107       17231 :       return ReduceSelect(node);
     108             :     case IrOpcode::kTypeOf:
     109       36979 :       return ReduceTypeOf(node);
     110             :     case IrOpcode::kToBoolean:
     111       84848 :       return ReduceToBoolean(node);
     112             :     case IrOpcode::kSpeculativeToNumber:
     113       24142 :       return ReduceSpeculativeToNumber(node);
     114             :     default:
     115             :       break;
     116             :   }
     117             :   return NoChange();
     118             : }
     119             : 
     120             : namespace {
     121             : 
     122       89636 : MaybeHandle<Map> GetStableMapFromObjectType(Type* object_type) {
     123       89636 :   if (object_type->IsHeapConstant()) {
     124             :     Handle<Map> object_map(object_type->AsHeapConstant()->Value()->map());
     125        5872 :     if (object_map->is_stable()) return object_map;
     126             :   }
     127       88237 :   return MaybeHandle<Map>();
     128             : }
     129             : 
     130             : }  // namespace
     131             : 
     132       44341 : Reduction TypedOptimization::ReduceCheckHeapObject(Node* node) {
     133       44341 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     134             :   Type* const input_type = NodeProperties::GetType(input);
     135       44341 :   if (!input_type->Maybe(Type::SignedSmall())) {
     136        6419 :     ReplaceWithValue(node, input);
     137             :     return Replace(input);
     138             :   }
     139             :   return NoChange();
     140             : }
     141             : 
     142         952 : Reduction TypedOptimization::ReduceCheckNotTaggedHole(Node* node) {
     143         952 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     144             :   Type* const input_type = NodeProperties::GetType(input);
     145         952 :   if (!input_type->Maybe(Type::Hole())) {
     146           0 :     ReplaceWithValue(node, input);
     147             :     return Replace(input);
     148             :   }
     149             :   return NoChange();
     150             : }
     151             : 
     152       84538 : Reduction TypedOptimization::ReduceCheckMaps(Node* node) {
     153             :   // The CheckMaps(o, ...map...) can be eliminated if map is stable,
     154             :   // o has type Constant(object) and map == object->map, and either
     155             :   //  (1) map cannot transition further, or
     156             :   //  (2) we can add a code dependency on the stability of map
     157             :   //      (to guard the Constant type information).
     158       83195 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     159             :   Type* const object_type = NodeProperties::GetType(object);
     160       83195 :   Node* const effect = NodeProperties::GetEffectInput(node);
     161             :   Handle<Map> object_map;
     162      166390 :   if (GetStableMapFromObjectType(object_type).ToHandle(&object_map)) {
     163        2686 :     for (int i = 1; i < node->op()->ValueInputCount(); ++i) {
     164           0 :       Node* const map = NodeProperties::GetValueInput(node, i);
     165             :       Type* const map_type = NodeProperties::GetType(map);
     166           0 :       if (map_type->IsHeapConstant() &&
     167             :           map_type->AsHeapConstant()->Value().is_identical_to(object_map)) {
     168           0 :         if (object_map->CanTransition()) {
     169           0 :           dependencies()->AssumeMapStable(object_map);
     170             :         }
     171             :         return Replace(effect);
     172             :       }
     173             :     }
     174             :   }
     175             :   return NoChange();
     176             : }
     177             : 
     178        1733 : Reduction TypedOptimization::ReduceCheckNumber(Node* node) {
     179        1733 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     180             :   Type* const input_type = NodeProperties::GetType(input);
     181        1733 :   if (input_type->Is(Type::Number())) {
     182        1314 :     ReplaceWithValue(node, input);
     183             :     return Replace(input);
     184             :   }
     185             :   return NoChange();
     186             : }
     187             : 
     188        4487 : Reduction TypedOptimization::ReduceCheckString(Node* node) {
     189        4487 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     190             :   Type* const input_type = NodeProperties::GetType(input);
     191        4487 :   if (input_type->Is(Type::String())) {
     192         358 :     ReplaceWithValue(node, input);
     193             :     return Replace(input);
     194             :   }
     195             :   return NoChange();
     196             : }
     197             : 
     198        2416 : Reduction TypedOptimization::ReduceCheckSeqString(Node* node) {
     199        2416 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     200             :   Type* const input_type = NodeProperties::GetType(input);
     201        2416 :   if (input_type->Is(Type::SeqString())) {
     202         377 :     ReplaceWithValue(node, input);
     203             :     return Replace(input);
     204             :   }
     205             :   return NoChange();
     206             : }
     207             : 
     208          88 : Reduction TypedOptimization::ReduceCheckEqualsInternalizedString(Node* node) {
     209          88 :   Node* const exp = NodeProperties::GetValueInput(node, 0);
     210             :   Type* const exp_type = NodeProperties::GetType(exp);
     211          88 :   Node* const val = NodeProperties::GetValueInput(node, 1);
     212             :   Type* const val_type = NodeProperties::GetType(val);
     213          88 :   Node* const effect = NodeProperties::GetEffectInput(node);
     214          88 :   if (val_type->Is(exp_type)) return Replace(effect);
     215             :   // TODO(turbofan): Should we also try to optimize the
     216             :   // non-internalized String case for {val} here?
     217             :   return NoChange();
     218             : }
     219             : 
     220          34 : Reduction TypedOptimization::ReduceCheckEqualsSymbol(Node* node) {
     221          34 :   Node* const exp = NodeProperties::GetValueInput(node, 0);
     222             :   Type* const exp_type = NodeProperties::GetType(exp);
     223          34 :   Node* const val = NodeProperties::GetValueInput(node, 1);
     224             :   Type* const val_type = NodeProperties::GetType(val);
     225          34 :   Node* const effect = NodeProperties::GetEffectInput(node);
     226          34 :   if (val_type->Is(exp_type)) return Replace(effect);
     227             :   return NoChange();
     228             : }
     229             : 
     230     2447074 : Reduction TypedOptimization::ReduceLoadField(Node* node) {
     231     1223481 :   Node* const object = NodeProperties::GetValueInput(node, 0);
     232             :   Type* const object_type = NodeProperties::GetType(object);
     233     1223481 :   FieldAccess const& access = FieldAccessOf(node->op());
     234     1223481 :   if (access.base_is_tagged == kTaggedBase &&
     235             :       access.offset == HeapObject::kMapOffset) {
     236             :     // We can replace LoadField[Map](o) with map if is stable, and
     237             :     // o has type Constant(object) and map == object->map, and either
     238             :     //  (1) map cannot transition further, or
     239             :     //  (2) deoptimization is enabled and we can add a code dependency on the
     240             :     //      stability of map (to guard the Constant type information).
     241             :     Handle<Map> object_map;
     242       12882 :     if (GetStableMapFromObjectType(object_type).ToHandle(&object_map)) {
     243          56 :       if (object_map->CanTransition()) {
     244          56 :         dependencies()->AssumeMapStable(object_map);
     245             :       }
     246          56 :       Node* const value = jsgraph()->HeapConstant(object_map);
     247          56 :       ReplaceWithValue(node, value);
     248             :       return Replace(value);
     249             :     }
     250             :   }
     251             :   return NoChange();
     252             : }
     253             : 
     254        9261 : Reduction TypedOptimization::ReduceNumberFloor(Node* node) {
     255        9724 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     256             :   Type* const input_type = NodeProperties::GetType(input);
     257       18522 :   if (input_type->Is(type_cache_.kIntegerOrMinusZeroOrNaN)) {
     258             :     return Replace(input);
     259             :   }
     260       18953 :   if (input_type->Is(Type::PlainNumber()) &&
     261         455 :       (input->opcode() == IrOpcode::kNumberDivide ||
     262             :        input->opcode() == IrOpcode::kSpeculativeNumberDivide)) {
     263         416 :     Node* const lhs = NodeProperties::GetValueInput(input, 0);
     264             :     Type* const lhs_type = NodeProperties::GetType(lhs);
     265         416 :     Node* const rhs = NodeProperties::GetValueInput(input, 1);
     266             :     Type* const rhs_type = NodeProperties::GetType(rhs);
     267         432 :     if (lhs_type->Is(Type::Unsigned32()) && rhs_type->Is(Type::Unsigned32())) {
     268             :       // We can replace
     269             :       //
     270             :       //   NumberFloor(NumberDivide(lhs: unsigned32,
     271             :       //                            rhs: unsigned32)): plain-number
     272             :       //
     273             :       // with
     274             :       //
     275             :       //   NumberToUint32(NumberDivide(lhs, rhs))
     276             :       //
     277             :       // and just smash the type of the {lhs} on the {node},
     278             :       // as the truncated result must be in the same range as
     279             :       // {lhs} since {rhs} cannot be less than 1 (due to the
     280             :       // plain-number type constraint on the {node}).
     281          16 :       NodeProperties::ChangeOp(node, simplified()->NumberToUint32());
     282             :       NodeProperties::SetType(node, lhs_type);
     283             :       return Changed(node);
     284             :     }
     285             :   }
     286             :   return NoChange();
     287             : }
     288             : 
     289        6821 : Reduction TypedOptimization::ReduceNumberRoundop(Node* node) {
     290        6821 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     291             :   Type* const input_type = NodeProperties::GetType(input);
     292       13642 :   if (input_type->Is(type_cache_.kIntegerOrMinusZeroOrNaN)) {
     293             :     return Replace(input);
     294             :   }
     295             :   return NoChange();
     296             : }
     297             : 
     298         578 : Reduction TypedOptimization::ReduceNumberToUint8Clamped(Node* node) {
     299         578 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     300             :   Type* const input_type = NodeProperties::GetType(input);
     301        1156 :   if (input_type->Is(type_cache_.kUint8)) {
     302             :     return Replace(input);
     303             :   }
     304             :   return NoChange();
     305             : }
     306             : 
     307      326211 : Reduction TypedOptimization::ReducePhi(Node* node) {
     308             :   // Try to narrow the type of the Phi {node}, which might be more precise now
     309             :   // after lowering based on types, i.e. a SpeculativeNumberAdd has a more
     310             :   // precise type than the JSAdd that was in the graph when the Typer was run.
     311             :   DCHECK_EQ(IrOpcode::kPhi, node->opcode());
     312      326211 :   int arity = node->op()->ValueInputCount();
     313             :   Type* type = NodeProperties::GetType(node->InputAt(0));
     314      978588 :   for (int i = 1; i < arity; ++i) {
     315             :     type = Type::Union(type, NodeProperties::GetType(node->InputAt(i)),
     316     1304754 :                        graph()->zone());
     317             :   }
     318             :   Type* const node_type = NodeProperties::GetType(node);
     319      326211 :   if (!node_type->Is(type)) {
     320        6626 :     type = Type::Intersect(node_type, type, graph()->zone());
     321             :     NodeProperties::SetType(node, type);
     322             :     return Changed(node);
     323             :   }
     324             :   return NoChange();
     325             : }
     326             : 
     327      274864 : Reduction TypedOptimization::ReduceReferenceEqual(Node* node) {
     328             :   DCHECK_EQ(IrOpcode::kReferenceEqual, node->opcode());
     329      222133 :   Node* const lhs = NodeProperties::GetValueInput(node, 0);
     330      222133 :   Node* const rhs = NodeProperties::GetValueInput(node, 1);
     331             :   Type* const lhs_type = NodeProperties::GetType(lhs);
     332             :   Type* const rhs_type = NodeProperties::GetType(rhs);
     333      222133 :   if (!lhs_type->Maybe(rhs_type)) {
     334       26369 :     Node* replacement = jsgraph()->FalseConstant();
     335             :     // Make sure we do not widen the type.
     336       26369 :     if (NodeProperties::GetType(replacement)
     337             :             ->Is(NodeProperties::GetType(node))) {
     338       26362 :       return Replace(jsgraph()->FalseConstant());
     339             :     }
     340             :   }
     341             :   return NoChange();
     342             : }
     343             : 
     344       17231 : Reduction TypedOptimization::ReduceSelect(Node* node) {
     345             :   DCHECK_EQ(IrOpcode::kSelect, node->opcode());
     346       17231 :   Node* const condition = NodeProperties::GetValueInput(node, 0);
     347             :   Type* const condition_type = NodeProperties::GetType(condition);
     348       17231 :   Node* const vtrue = NodeProperties::GetValueInput(node, 1);
     349             :   Type* const vtrue_type = NodeProperties::GetType(vtrue);
     350       17231 :   Node* const vfalse = NodeProperties::GetValueInput(node, 2);
     351             :   Type* const vfalse_type = NodeProperties::GetType(vfalse);
     352       34462 :   if (condition_type->Is(true_type_)) {
     353             :     // Select(condition:true, vtrue, vfalse) => vtrue
     354             :     return Replace(vtrue);
     355             :   }
     356       33716 :   if (condition_type->Is(false_type_)) {
     357             :     // Select(condition:false, vtrue, vfalse) => vfalse
     358             :     return Replace(vfalse);
     359             :   }
     360       32685 :   if (vtrue_type->Is(true_type_) && vfalse_type->Is(false_type_)) {
     361             :     // Select(condition, vtrue:true, vfalse:false) => condition
     362             :     return Replace(condition);
     363             :   }
     364       27703 :   if (vtrue_type->Is(false_type_) && vfalse_type->Is(true_type_)) {
     365             :     // Select(condition, vtrue:false, vfalse:true) => BooleanNot(condition)
     366           0 :     node->TrimInputCount(1);
     367           0 :     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
     368             :     return Changed(node);
     369             :   }
     370             :   // Try to narrow the type of the Select {node}, which might be more precise
     371             :   // now after lowering based on types.
     372       13355 :   Type* type = Type::Union(vtrue_type, vfalse_type, graph()->zone());
     373             :   Type* const node_type = NodeProperties::GetType(node);
     374       13355 :   if (!node_type->Is(type)) {
     375         637 :     type = Type::Intersect(node_type, type, graph()->zone());
     376             :     NodeProperties::SetType(node, type);
     377             :     return Changed(node);
     378             :   }
     379             :   return NoChange();
     380             : }
     381             : 
     382       24142 : Reduction TypedOptimization::ReduceSpeculativeToNumber(Node* node) {
     383             :   DCHECK_EQ(IrOpcode::kSpeculativeToNumber, node->opcode());
     384       24142 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     385             :   Type* const input_type = NodeProperties::GetType(input);
     386       24142 :   if (input_type->Is(Type::Number())) {
     387             :     // SpeculativeToNumber(x:number) => x
     388       16302 :     ReplaceWithValue(node, input);
     389             :     return Replace(input);
     390             :   }
     391             :   return NoChange();
     392             : }
     393             : 
     394       53132 : Reduction TypedOptimization::ReduceTypeOf(Node* node) {
     395             :   Node* const input = node->InputAt(0);
     396             :   Type* const type = NodeProperties::GetType(input);
     397             :   Factory* const f = factory();
     398       36979 :   if (type->Is(Type::Boolean())) {
     399        2602 :     return Replace(jsgraph()->Constant(f->boolean_string()));
     400       34377 :   } else if (type->Is(Type::Number())) {
     401       10486 :     return Replace(jsgraph()->Constant(f->number_string()));
     402       23891 :   } else if (type->Is(Type::String())) {
     403        1152 :     return Replace(jsgraph()->Constant(f->string_string()));
     404       22739 :   } else if (type->Is(Type::Symbol())) {
     405           0 :     return Replace(jsgraph()->Constant(f->symbol_string()));
     406       22739 :   } else if (type->Is(Type::OtherUndetectableOrUndefined())) {
     407         250 :     return Replace(jsgraph()->Constant(f->undefined_string()));
     408       22489 :   } else if (type->Is(Type::NonCallableOrNull())) {
     409        1613 :     return Replace(jsgraph()->Constant(f->object_string()));
     410       20876 :   } else if (type->Is(Type::Function())) {
     411          50 :     return Replace(jsgraph()->Constant(f->function_string()));
     412       20826 :   } else if (type->IsHeapConstant()) {
     413             :     return Replace(jsgraph()->Constant(
     414           0 :         Object::TypeOf(isolate(), type->AsHeapConstant()->Value())));
     415             :   }
     416             : 
     417             :   return NoChange();
     418             : }
     419             : 
     420       87428 : Reduction TypedOptimization::ReduceToBoolean(Node* node) {
     421             :   Node* const input = node->InputAt(0);
     422             :   Type* const input_type = NodeProperties::GetType(input);
     423       84848 :   if (input_type->Is(Type::Boolean())) {
     424             :     // ToBoolean(x:boolean) => x
     425             :     return Replace(input);
     426       57633 :   } else if (input_type->Is(Type::OrderedNumber())) {
     427             :     // SToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0))
     428             :     node->ReplaceInput(0, graph()->NewNode(simplified()->NumberEqual(), input,
     429        7623 :                                            jsgraph()->ZeroConstant()));
     430        2541 :     node->TrimInputCount(1);
     431        2541 :     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
     432             :     return Changed(node);
     433       55092 :   } else if (input_type->Is(Type::Number())) {
     434             :     // ToBoolean(x:number) => NumberToBoolean(x)
     435         197 :     node->TrimInputCount(1);
     436         197 :     NodeProperties::ChangeOp(node, simplified()->NumberToBoolean());
     437             :     return Changed(node);
     438       54895 :   } else if (input_type->Is(Type::DetectableReceiverOrNull())) {
     439             :     // ToBoolean(x:detectable receiver \/ null)
     440             :     //   => BooleanNot(ReferenceEqual(x,#null))
     441             :     node->ReplaceInput(0, graph()->NewNode(simplified()->ReferenceEqual(),
     442          54 :                                            input, jsgraph()->NullConstant()));
     443          18 :     node->TrimInputCount(1);
     444          18 :     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
     445             :     return Changed(node);
     446       54877 :   } else if (input_type->Is(Type::ReceiverOrNullOrUndefined())) {
     447             :     // ToBoolean(x:receiver \/ null \/ undefined)
     448             :     //   => BooleanNot(ObjectIsUndetectable(x))
     449             :     node->ReplaceInput(
     450         144 :         0, graph()->NewNode(simplified()->ObjectIsUndetectable(), input));
     451          72 :     node->TrimInputCount(1);
     452          72 :     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
     453             :     return Changed(node);
     454       54805 :   } else if (input_type->Is(Type::String())) {
     455             :     // ToBoolean(x:string) => BooleanNot(ReferenceEqual(x,""))
     456             :     node->ReplaceInput(0,
     457             :                        graph()->NewNode(simplified()->ReferenceEqual(), input,
     458          63 :                                         jsgraph()->EmptyStringConstant()));
     459          21 :     node->TrimInputCount(1);
     460          21 :     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
     461             :     return Changed(node);
     462             :   }
     463             :   return NoChange();
     464             : }
     465             : 
     466           0 : Factory* TypedOptimization::factory() const { return isolate()->factory(); }
     467             : 
     468     1562677 : Graph* TypedOptimization::graph() const { return jsgraph()->graph(); }
     469             : 
     470      924039 : Isolate* TypedOptimization::isolate() const { return jsgraph()->isolate(); }
     471             : 
     472        5517 : SimplifiedOperatorBuilder* TypedOptimization::simplified() const {
     473        5517 :   return jsgraph()->simplified();
     474             : }
     475             : 
     476             : }  // namespace compiler
     477             : }  // namespace internal
     478             : }  // namespace v8

Generated by: LCOV version 1.10