LCOV - code coverage report
Current view: top level - src/compiler - js-typed-lowering.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 939 962 97.6 %
Date: 2017-10-20 Functions: 69 76 90.8 %

          Line data    Source code
       1             : // Copyright 2014 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/js-typed-lowering.h"
       6             : 
       7             : #include "src/ast/modules.h"
       8             : #include "src/builtins/builtins-utils.h"
       9             : #include "src/code-factory.h"
      10             : #include "src/compiler/access-builder.h"
      11             : #include "src/compiler/allocation-builder.h"
      12             : #include "src/compiler/js-graph.h"
      13             : #include "src/compiler/linkage.h"
      14             : #include "src/compiler/node-matchers.h"
      15             : #include "src/compiler/node-properties.h"
      16             : #include "src/compiler/operator-properties.h"
      17             : #include "src/compiler/type-cache.h"
      18             : #include "src/compiler/types.h"
      19             : #include "src/objects-inl.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : namespace compiler {
      24             : 
      25             : // A helper class to simplify the process of reducing a single binop node with a
      26             : // JSOperator. This class manages the rewriting of context, control, and effect
      27             : // dependencies during lowering of a binop and contains numerous helper
      28             : // functions for matching the types of inputs to an operation.
      29             : class JSBinopReduction final {
      30             :  public:
      31             :   JSBinopReduction(JSTypedLowering* lowering, Node* node)
      32      549584 :       : lowering_(lowering), node_(node) {}
      33             : 
      34      109888 :   bool GetCompareNumberOperationHint(NumberOperationHint* hint) {
      35             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      36      109888 :     switch (CompareOperationHintOf(node_->op())) {
      37             :       case CompareOperationHint::kSignedSmall:
      38        8383 :         *hint = NumberOperationHint::kSignedSmall;
      39             :         return true;
      40             :       case CompareOperationHint::kNumber:
      41        8527 :         *hint = NumberOperationHint::kNumber;
      42             :         return true;
      43             :       case CompareOperationHint::kNumberOrOddball:
      44           0 :         *hint = NumberOperationHint::kNumberOrOddball;
      45             :         return true;
      46             :       case CompareOperationHint::kAny:
      47             :       case CompareOperationHint::kNone:
      48             :       case CompareOperationHint::kString:
      49             :       case CompareOperationHint::kSymbol:
      50             :       case CompareOperationHint::kReceiver:
      51             :       case CompareOperationHint::kInternalizedString:
      52             :         break;
      53             :     }
      54             :     return false;
      55             :   }
      56             : 
      57      149020 :   bool IsInternalizedStringCompareOperation() {
      58             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      59      149020 :     return (CompareOperationHintOf(node_->op()) ==
      60      153024 :             CompareOperationHint::kInternalizedString) &&
      61      153024 :            BothInputsMaybe(Type::InternalizedString());
      62             :   }
      63             : 
      64       95386 :   bool IsReceiverCompareOperation() {
      65             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      66       95386 :     return (CompareOperationHintOf(node_->op()) ==
      67       96179 :             CompareOperationHint::kReceiver) &&
      68       96179 :            BothInputsMaybe(Type::Receiver());
      69             :   }
      70             : 
      71      113977 :   bool IsStringCompareOperation() {
      72             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      73      113977 :     return (CompareOperationHintOf(node_->op()) ==
      74      117119 :             CompareOperationHint::kString) &&
      75      117119 :            BothInputsMaybe(Type::String());
      76             :   }
      77             : 
      78       91513 :   bool IsSymbolCompareOperation() {
      79             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      80       91513 :     return (CompareOperationHintOf(node_->op()) ==
      81       91513 :             CompareOperationHint::kSymbol) &&
      82       91513 :            BothInputsMaybe(Type::Symbol());
      83             :   }
      84             : 
      85             :   // Check if a string addition will definitely result in creating a ConsString,
      86             :   // i.e. if the combined length of the resulting string exceeds the ConsString
      87             :   // minimum length.
      88       49577 :   bool ShouldCreateConsString() {
      89             :     DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode());
      90             :     DCHECK(OneInputIs(Type::String()));
      91       80891 :     if (BothInputsAre(Type::String()) ||
      92       31314 :         BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString) {
      93       20279 :       HeapObjectBinopMatcher m(node_);
      94       35716 :       if (m.right().HasValue() && m.right().Value()->IsString()) {
      95             :         Handle<String> right_string = Handle<String>::cast(m.right().Value());
      96       15437 :         if (right_string->length() >= ConsString::kMinLength) return true;
      97             :       }
      98       19895 :       if (m.left().HasValue() && m.left().Value()->IsString()) {
      99             :         Handle<String> left_string = Handle<String>::cast(m.left().Value());
     100        1651 :         if (left_string->length() >= ConsString::kMinLength) {
     101             :           // The invariant for ConsString requires the left hand side to be
     102             :           // a sequential or external string if the right hand side is the
     103             :           // empty string. Since we don't know anything about the right hand
     104             :           // side here, we must ensure that the left hand side satisfy the
     105             :           // constraints independent of the right hand side.
     106         448 :           return left_string->IsSeqString() || left_string->IsExternalString();
     107             :         }
     108             :       }
     109             :     }
     110             :     return false;
     111             :   }
     112             : 
     113             :   // Inserts a CheckReceiver for the left input.
     114        4758 :   void CheckLeftInputToReceiver() {
     115             :     Node* left_input = graph()->NewNode(simplified()->CheckReceiver(), left(),
     116         793 :                                         effect(), control());
     117         793 :     node_->ReplaceInput(0, left_input);
     118             :     update_effect(left_input);
     119         793 :   }
     120             : 
     121             :   // Checks that both inputs are Receiver, and if we don't know
     122             :   // statically that one side is already a Receiver, insert a
     123             :   // CheckReceiver node.
     124         826 :   void CheckInputsToReceiver() {
     125         113 :     if (!left_type()->Is(Type::Receiver())) {
     126         113 :       CheckLeftInputToReceiver();
     127             :     }
     128         113 :     if (!right_type()->Is(Type::Receiver())) {
     129             :       Node* right_input = graph()->NewNode(simplified()->CheckReceiver(),
     130         100 :                                            right(), effect(), control());
     131         100 :       node_->ReplaceInput(1, right_input);
     132             :       update_effect(right_input);
     133             :     }
     134         113 :   }
     135             : 
     136             :   // Checks that both inputs are Symbol, and if we don't know
     137             :   // statically that one side is already a Symbol, insert a
     138             :   // CheckSymbol node.
     139           0 :   void CheckInputsToSymbol() {
     140           0 :     if (!left_type()->Is(Type::Symbol())) {
     141             :       Node* left_input = graph()->NewNode(simplified()->CheckSymbol(), left(),
     142           0 :                                           effect(), control());
     143           0 :       node_->ReplaceInput(0, left_input);
     144             :       update_effect(left_input);
     145             :     }
     146           0 :     if (!right_type()->Is(Type::Symbol())) {
     147             :       Node* right_input = graph()->NewNode(simplified()->CheckSymbol(), right(),
     148           0 :                                            effect(), control());
     149           0 :       node_->ReplaceInput(1, right_input);
     150             :       update_effect(right_input);
     151             :     }
     152           0 :   }
     153             : 
     154             :   // Checks that both inputs are String, and if we don't know
     155             :   // statically that one side is already a String, insert a
     156             :   // CheckString node.
     157       27314 :   void CheckInputsToString() {
     158        3142 :     if (!left_type()->Is(Type::String())) {
     159             :       Node* left_input = graph()->NewNode(simplified()->CheckString(), left(),
     160        3110 :                                           effect(), control());
     161        3110 :       node_->ReplaceInput(0, left_input);
     162             :       update_effect(left_input);
     163             :     }
     164        3142 :     if (!right_type()->Is(Type::String())) {
     165             :       Node* right_input = graph()->NewNode(simplified()->CheckString(), right(),
     166         395 :                                            effect(), control());
     167         395 :       node_->ReplaceInput(1, right_input);
     168             :       update_effect(right_input);
     169             :     }
     170        3142 :   }
     171             : 
     172             :   // Checks that both inputs are InternalizedString, and if we don't know
     173             :   // statically that one side is already an InternalizedString, insert a
     174             :   // CheckInternalizedString node.
     175       32902 :   void CheckInputsToInternalizedString() {
     176        4004 :     if (!left_type()->Is(Type::UniqueName())) {
     177             :       Node* left_input = graph()->NewNode(
     178        4004 :           simplified()->CheckInternalizedString(), left(), effect(), control());
     179        4004 :       node_->ReplaceInput(0, left_input);
     180             :       update_effect(left_input);
     181             :     }
     182        4004 :     if (!right_type()->Is(Type::UniqueName())) {
     183             :       Node* right_input =
     184             :           graph()->NewNode(simplified()->CheckInternalizedString(), right(),
     185         145 :                            effect(), control());
     186         145 :       node_->ReplaceInput(1, right_input);
     187             :       update_effect(right_input);
     188             :     }
     189        4004 :   }
     190             : 
     191      290456 :   void ConvertInputsToNumber() {
     192             :     DCHECK(left_type()->Is(Type::PlainPrimitive()));
     193             :     DCHECK(right_type()->Is(Type::PlainPrimitive()));
     194      145228 :     node_->ReplaceInput(0, ConvertPlainPrimitiveToNumber(left()));
     195      145228 :     node_->ReplaceInput(1, ConvertPlainPrimitiveToNumber(right()));
     196      145228 :   }
     197             : 
     198       22702 :   void ConvertInputsToUI32(Signedness left_signedness,
     199       45404 :                            Signedness right_signedness) {
     200       22702 :     node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
     201       22702 :     node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness));
     202       22702 :   }
     203             : 
     204       17876 :   void SwapInputs() {
     205             :     Node* l = left();
     206             :     Node* r = right();
     207        8938 :     node_->ReplaceInput(0, r);
     208        8938 :     node_->ReplaceInput(1, l);
     209        8938 :   }
     210             : 
     211             :   // Remove all effect and control inputs and outputs to this node and change
     212             :   // to the pure operator {op}.
     213      225414 :   Reduction ChangeToPureOperator(const Operator* op, Type* type = Type::Any()) {
     214             :     DCHECK_EQ(0, op->EffectInputCount());
     215             :     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
     216             :     DCHECK_EQ(0, op->ControlInputCount());
     217             :     DCHECK_EQ(2, op->ValueInputCount());
     218             : 
     219             :     // Remove the effects from the node, and update its effect/control usages.
     220      450828 :     if (node_->op()->EffectInputCount() > 0) {
     221      225414 :       lowering_->RelaxEffectsAndControls(node_);
     222             :     }
     223             :     // Remove the inputs corresponding to context, effect, and control.
     224      225414 :     NodeProperties::RemoveNonValueInputs(node_);
     225             :     // Finally, update the operator to the new one.
     226      225414 :     NodeProperties::ChangeOp(node_, op);
     227             : 
     228             :     // TODO(jarin): Replace the explicit typing hack with a call to some method
     229             :     // that encapsulates changing the operator and re-typing.
     230      225414 :     Type* node_type = NodeProperties::GetType(node_);
     231      225414 :     NodeProperties::SetType(node_, Type::Intersect(node_type, type, zone()));
     232             : 
     233      225414 :     return lowering_->Changed(node_);
     234             :   }
     235             : 
     236       16910 :   Reduction ChangeToSpeculativeOperator(const Operator* op, Type* upper_bound) {
     237             :     DCHECK_EQ(1, op->EffectInputCount());
     238             :     DCHECK_EQ(1, op->EffectOutputCount());
     239             :     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
     240             :     DCHECK_EQ(1, op->ControlInputCount());
     241             :     DCHECK_EQ(0, op->ControlOutputCount());
     242             :     DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
     243             :     DCHECK_EQ(2, op->ValueInputCount());
     244             : 
     245             :     DCHECK_EQ(1, node_->op()->EffectInputCount());
     246             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
     247             :     DCHECK_EQ(1, node_->op()->ControlInputCount());
     248             :     DCHECK_EQ(2, node_->op()->ValueInputCount());
     249             : 
     250             :     // Reconnect the control output to bypass the IfSuccess node and
     251             :     // possibly disconnect from the IfException node.
     252       33820 :     lowering_->RelaxControls(node_);
     253             : 
     254             :     // Remove the frame state and the context.
     255       33820 :     if (OperatorProperties::HasFrameStateInput(node_->op())) {
     256           0 :       node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
     257             :     }
     258       33820 :     node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
     259             : 
     260       16910 :     NodeProperties::ChangeOp(node_, op);
     261             : 
     262             :     // Update the type to number.
     263       16910 :     Type* node_type = NodeProperties::GetType(node_);
     264             :     NodeProperties::SetType(node_,
     265       16910 :                             Type::Intersect(node_type, upper_bound, zone()));
     266             : 
     267       16910 :     return lowering_->Changed(node_);
     268             :   }
     269             : 
     270      106714 :   const Operator* NumberOp() {
     271      106714 :     switch (node_->opcode()) {
     272             :       case IrOpcode::kJSAdd:
     273           0 :         return simplified()->NumberAdd();
     274             :       case IrOpcode::kJSSubtract:
     275       20049 :         return simplified()->NumberSubtract();
     276             :       case IrOpcode::kJSMultiply:
     277        4401 :         return simplified()->NumberMultiply();
     278             :       case IrOpcode::kJSDivide:
     279        3494 :         return simplified()->NumberDivide();
     280             :       case IrOpcode::kJSModulus:
     281        2711 :         return simplified()->NumberModulus();
     282             :       case IrOpcode::kJSBitwiseAnd:
     283        3701 :         return simplified()->NumberBitwiseAnd();
     284             :       case IrOpcode::kJSBitwiseOr:
     285        5179 :         return simplified()->NumberBitwiseOr();
     286             :       case IrOpcode::kJSBitwiseXor:
     287        3098 :         return simplified()->NumberBitwiseXor();
     288             :       case IrOpcode::kJSShiftLeft:
     289        3485 :         return simplified()->NumberShiftLeft();
     290             :       case IrOpcode::kJSShiftRight:
     291        3784 :         return simplified()->NumberShiftRight();
     292             :       case IrOpcode::kJSShiftRightLogical:
     293        3455 :         return simplified()->NumberShiftRightLogical();
     294             :       default:
     295             :         break;
     296             :     }
     297           0 :     UNREACHABLE();
     298             :   }
     299             : 
     300       67316 :   const Operator* NumberOpFromSpeculativeNumberOp() {
     301       67316 :     switch (node_->opcode()) {
     302             :       case IrOpcode::kSpeculativeNumberEqual:
     303       11390 :         return simplified()->NumberEqual();
     304             :       case IrOpcode::kSpeculativeNumberLessThan:
     305        9422 :         return simplified()->NumberLessThan();
     306             :       case IrOpcode::kSpeculativeNumberLessThanOrEqual:
     307         354 :         return simplified()->NumberLessThanOrEqual();
     308             :       case IrOpcode::kSpeculativeNumberAdd:
     309           0 :         return simplified()->NumberAdd();
     310             :       case IrOpcode::kSpeculativeNumberSubtract:
     311        1264 :         return simplified()->NumberSubtract();
     312             :       case IrOpcode::kSpeculativeNumberMultiply:
     313        7376 :         return simplified()->NumberMultiply();
     314             :       case IrOpcode::kSpeculativeNumberDivide:
     315        3440 :         return simplified()->NumberDivide();
     316             :       case IrOpcode::kSpeculativeNumberModulus:
     317         412 :         return simplified()->NumberModulus();
     318             :       default:
     319             :         break;
     320             :     }
     321           0 :     UNREACHABLE();
     322             :   }
     323             : 
     324     3398588 :   bool LeftInputIs(Type* t) { return left_type()->Is(t); }
     325             : 
     326     1348132 :   bool RightInputIs(Type* t) { return right_type()->Is(t); }
     327             : 
     328      225025 :   bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); }
     329             : 
     330     1372562 :   bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); }
     331             : 
     332       15878 :   bool BothInputsMaybe(Type* t) {
     333       15878 :     return left_type()->Maybe(t) && right_type()->Maybe(t);
     334             :   }
     335             : 
     336      341545 :   bool OneInputCannotBe(Type* t) {
     337      341545 :     return !left_type()->Maybe(t) || !right_type()->Maybe(t);
     338             :   }
     339             : 
     340      214522 :   bool NeitherInputCanBe(Type* t) {
     341      214522 :     return !left_type()->Maybe(t) && !right_type()->Maybe(t);
     342             :   }
     343             : 
     344        8547 :   Node* effect() { return NodeProperties::GetEffectInput(node_); }
     345        8547 :   Node* control() { return NodeProperties::GetControlInput(node_); }
     346             :   Node* context() { return NodeProperties::GetContextInput(node_); }
     347      352834 :   Node* left() { return NodeProperties::GetValueInput(node_, 0); }
     348      371969 :   Node* right() { return NodeProperties::GetValueInput(node_, 1); }
     349             :   Type* left_type() { return NodeProperties::GetType(node_->InputAt(0)); }
     350             :   Type* right_type() { return NodeProperties::GetType(node_->InputAt(1)); }
     351             :   Type* type() { return NodeProperties::GetType(node_); }
     352             : 
     353             :   SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
     354             :   Graph* graph() const { return lowering_->graph(); }
     355             :   JSGraph* jsgraph() { return lowering_->jsgraph(); }
     356             :   JSOperatorBuilder* javascript() { return lowering_->javascript(); }
     357             :   CommonOperatorBuilder* common() { return jsgraph()->common(); }
     358      484648 :   Zone* zone() const { return graph()->zone(); }
     359             : 
     360             :  private:
     361             :   JSTypedLowering* lowering_;  // The containing lowering instance.
     362             :   Node* node_;                 // The original node.
     363             : 
     364      307256 :   Node* ConvertPlainPrimitiveToNumber(Node* node) {
     365             :     DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
     366             :     // Avoid inserting too many eager ToNumber() operations.
     367      290456 :     Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
     368      290456 :     if (reduction.Changed()) return reduction.replacement();
     369        8400 :     if (NodeProperties::GetType(node)->Is(Type::Number())) {
     370             :       return node;
     371             :     }
     372       16800 :     return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
     373             :   }
     374             : 
     375       92930 :   Node* ConvertToUI32(Node* node, Signedness signedness) {
     376             :     // Avoid introducing too many eager NumberToXXnt32() operations.
     377             :     Type* type = NodeProperties::GetType(node);
     378       45404 :     if (signedness == kSigned) {
     379       31225 :       if (!type->Is(Type::Signed32())) {
     380       14799 :         node = graph()->NewNode(simplified()->NumberToInt32(), node);
     381             :       }
     382             :     } else {
     383             :       DCHECK_EQ(kUnsigned, signedness);
     384       14179 :       if (!type->Is(Type::Unsigned32())) {
     385        8964 :         node = graph()->NewNode(simplified()->NumberToUint32(), node);
     386             :       }
     387             :     }
     388       45404 :     return node;
     389             :   }
     390             : 
     391             :   void update_effect(Node* effect) {
     392        8547 :     NodeProperties::ReplaceEffectInput(node_, effect);
     393             :   }
     394             : };
     395             : 
     396             : 
     397             : // TODO(turbofan): js-typed-lowering improvements possible
     398             : // - immediately put in type bounds for all new nodes
     399             : // - relax effects from generic but not-side-effecting operations
     400             : 
     401      462956 : JSTypedLowering::JSTypedLowering(Editor* editor,
     402             :                                  JSGraph* jsgraph, Zone* zone)
     403             :     : AdvancedReducer(editor),
     404             :       jsgraph_(jsgraph),
     405             :       empty_string_type_(
     406      462956 :           Type::HeapConstant(factory()->empty_string(), graph()->zone())),
     407             :       pointer_comparable_type_(
     408             :           Type::Union(Type::Oddball(),
     409             :                       Type::Union(Type::SymbolOrReceiver(), empty_string_type_,
     410             :                                   graph()->zone()),
     411      462957 :                       graph()->zone())),
     412     1388870 :       type_cache_(TypeCache::Get()) {}
     413             : 
     414      105108 : Reduction JSTypedLowering::ReduceSpeculativeNumberAdd(Node* node) {
     415             :   JSBinopReduction r(this, node);
     416       52554 :   NumberOperationHint hint = NumberOperationHintOf(node->op());
     417      105108 :   if ((hint == NumberOperationHint::kNumber ||
     418       52554 :        hint == NumberOperationHint::kNumberOrOddball) &&
     419      104091 :       r.BothInputsAre(Type::PlainPrimitive()) &&
     420       51537 :       r.NeitherInputCanBe(Type::StringOrReceiver())) {
     421             :     // SpeculativeNumberAdd(x:-string, y:-string) =>
     422             :     //     NumberAdd(ToNumber(x), ToNumber(y))
     423       51522 :     r.ConvertInputsToNumber();
     424       51522 :     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
     425             :   }
     426             :   return NoChange();
     427             : }
     428             : 
     429      233217 : Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
     430             :   JSBinopReduction r(this, node);
     431       90137 :   if (r.BothInputsAre(Type::Number())) {
     432             :     // JSAdd(x:number, y:number) => NumberAdd(x, y)
     433       16211 :     r.ConvertInputsToNumber();
     434       16211 :     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
     435             :   }
     436      100175 :   if (r.BothInputsAre(Type::PlainPrimitive()) &&
     437       26249 :       r.NeitherInputCanBe(Type::StringOrReceiver())) {
     438             :     // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
     439          21 :     r.ConvertInputsToNumber();
     440          21 :     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
     441             :   }
     442       73905 :   if (r.OneInputIs(Type::String())) {
     443             :     // We know that (at least) one input is already a String,
     444             :     // so try to strength-reduce the non-String input.
     445       51179 :     if (r.LeftInputIs(Type::String())) {
     446       82092 :       Reduction const reduction = ReduceJSToStringInput(r.right());
     447       41046 :       if (reduction.Changed()) {
     448       19749 :         NodeProperties::ReplaceValueInput(node, reduction.replacement(), 1);
     449             :       }
     450       10133 :     } else if (r.RightInputIs(Type::String())) {
     451       20266 :       Reduction const reduction = ReduceJSToStringInput(r.left());
     452       10133 :       if (reduction.Changed()) {
     453         116 :         NodeProperties::ReplaceValueInput(node, reduction.replacement(), 0);
     454             :       }
     455             :     }
     456             :     // We might be able to constant-fold the String concatenation now.
     457       51179 :     if (r.BothInputsAre(Type::String())) {
     458       19865 :       HeapObjectBinopMatcher m(node);
     459       19865 :       if (m.IsFoldable()) {
     460             :         Handle<String> left = Handle<String>::cast(m.left().Value());
     461             :         Handle<String> right = Handle<String>::cast(m.right().Value());
     462        1602 :         if (left->length() + right->length() > String::kMaxLength) {
     463             :           // No point in trying to optimize this, as it will just throw.
     464             :           return NoChange();
     465             :         }
     466             :         Node* value = jsgraph()->HeapConstant(
     467        3204 :             factory()->NewConsString(left, right).ToHandleChecked());
     468        1684 :         ReplaceWithValue(node, value);
     469             :         return Replace(value);
     470             :       }
     471             :     }
     472             :     // We might know for sure that we're creating a ConsString here.
     473       49577 :     if (r.ShouldCreateConsString()) {
     474        2363 :       return ReduceCreateConsString(node);
     475             :     }
     476             :     // Eliminate useless concatenation of empty string.
     477       47214 :     if (BinaryOperationHintOf(node->op()) == BinaryOperationHint::kString) {
     478        3345 :       Node* effect = NodeProperties::GetEffectInput(node);
     479        3345 :       Node* control = NodeProperties::GetControlInput(node);
     480        3345 :       if (r.LeftInputIs(empty_string_type_)) {
     481             :         Node* value = effect = graph()->NewNode(simplified()->CheckString(),
     482          86 :                                                 r.right(), effect, control);
     483             :         ReplaceWithValue(node, value, effect, control);
     484             :         return Replace(value);
     485        3302 :       } else if (r.RightInputIs(empty_string_type_)) {
     486             :         Node* value = effect = graph()->NewNode(simplified()->CheckString(),
     487          78 :                                                 r.left(), effect, control);
     488             :         ReplaceWithValue(node, value, effect, control);
     489             :         return Replace(value);
     490             :       }
     491             :     }
     492             :     StringAddFlags flags = STRING_ADD_CHECK_NONE;
     493       47132 :     if (!r.LeftInputIs(Type::String())) {
     494             :       flags = STRING_ADD_CONVERT_LEFT;
     495       37254 :     } else if (!r.RightInputIs(Type::String())) {
     496             :       flags = STRING_ADD_CONVERT_RIGHT;
     497             :     }
     498       47132 :     Operator::Properties properties = node->op()->properties();
     499       47132 :     if (r.NeitherInputCanBe(Type::Receiver())) {
     500             :       // Both sides are already strings, so we know that the
     501             :       // string addition will not cause any observable side
     502             :       // effects; it can still throw obviously.
     503       17563 :       properties = Operator::kNoWrite | Operator::kNoDeopt;
     504             :     }
     505             :     // JSAdd(x:string, y) => CallStub[StringAdd](x, y)
     506             :     // JSAdd(x, y:string) => CallStub[StringAdd](x, y)
     507             :     Callable const callable =
     508       47132 :         CodeFactory::StringAdd(isolate(), flags, NOT_TENURED);
     509             :     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
     510             :         isolate(), graph()->zone(), callable.descriptor(), 0,
     511      141396 :         CallDescriptor::kNeedsFrameState, properties);
     512             :     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
     513             :     node->InsertInput(graph()->zone(), 0,
     514       94264 :                       jsgraph()->HeapConstant(callable.code()));
     515       47132 :     NodeProperties::ChangeOp(node, common()->Call(desc));
     516             :     return Changed(node);
     517             :   }
     518             :   return NoChange();
     519             : }
     520             : 
     521       56427 : Reduction JSTypedLowering::ReduceNumberBinop(Node* node) {
     522             :   JSBinopReduction r(this, node);
     523       56427 :   if (r.BothInputsAre(Type::PlainPrimitive())) {
     524       30655 :     r.ConvertInputsToNumber();
     525       30655 :     return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
     526             :   }
     527             :   return NoChange();
     528             : }
     529             : 
     530       84548 : Reduction JSTypedLowering::ReduceSpeculativeNumberBinop(Node* node) {
     531             :   JSBinopReduction r(this, node);
     532       42274 :   NumberOperationHint hint = NumberOperationHintOf(node->op());
     533       84548 :   if ((hint == NumberOperationHint::kNumber ||
     534       63141 :        hint == NumberOperationHint::kNumberOrOddball) &&
     535       20867 :       r.BothInputsAre(Type::NumberOrUndefinedOrNullOrBoolean())) {
     536       12492 :     r.ConvertInputsToNumber();
     537             :     return r.ChangeToPureOperator(r.NumberOpFromSpeculativeNumberOp(),
     538       12492 :                                   Type::Number());
     539             :   }
     540             :   return NoChange();
     541             : }
     542             : 
     543       23797 : Reduction JSTypedLowering::ReduceInt32Binop(Node* node) {
     544             :   JSBinopReduction r(this, node);
     545       23797 :   if (r.BothInputsAre(Type::PlainPrimitive())) {
     546       11978 :     r.ConvertInputsToNumber();
     547       11978 :     r.ConvertInputsToUI32(kSigned, kSigned);
     548       11978 :     return r.ChangeToPureOperator(r.NumberOp(), Type::Signed32());
     549             :   }
     550             :   return NoChange();
     551             : }
     552             : 
     553       12376 : Reduction JSTypedLowering::ReduceUI32Shift(Node* node, Signedness signedness) {
     554             :   JSBinopReduction r(this, node);
     555       12376 :   if (r.BothInputsAre(Type::PlainPrimitive())) {
     556       10724 :     r.ConvertInputsToNumber();
     557       10724 :     r.ConvertInputsToUI32(signedness, kUnsigned);
     558             :     return r.ChangeToPureOperator(r.NumberOp(), signedness == kUnsigned
     559             :                                                     ? Type::Unsigned32()
     560       10724 :                                                     : Type::Signed32());
     561             :   }
     562             :   return NoChange();
     563             : }
     564             : 
     565        7089 : Reduction JSTypedLowering::ReduceCreateConsString(Node* node) {
     566        2363 :   Node* first = NodeProperties::GetValueInput(node, 0);
     567        2363 :   Node* second = NodeProperties::GetValueInput(node, 1);
     568        2363 :   Node* context = NodeProperties::GetContextInput(node);
     569        2363 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     570        2363 :   Node* effect = NodeProperties::GetEffectInput(node);
     571        2363 :   Node* control = NodeProperties::GetControlInput(node);
     572             : 
     573             :   // Make sure {first} is actually a String.
     574             :   Type* first_type = NodeProperties::GetType(first);
     575        2363 :   if (!first_type->Is(Type::String())) {
     576             :     first = effect =
     577         345 :         graph()->NewNode(simplified()->CheckString(), first, effect, control);
     578             :     first_type = NodeProperties::GetType(first);
     579             :   }
     580             : 
     581             :   // Make sure {second} is actually a String.
     582             :   Type* second_type = NodeProperties::GetType(second);
     583        2363 :   if (!second_type->Is(Type::String())) {
     584             :     second = effect =
     585         303 :         graph()->NewNode(simplified()->CheckString(), second, effect, control);
     586             :     second_type = NodeProperties::GetType(second);
     587             :   }
     588             : 
     589             :   // Determine the {first} length.
     590        2363 :   Node* first_length = BuildGetStringLength(first, &effect, control);
     591        2363 :   Node* second_length = BuildGetStringLength(second, &effect, control);
     592             : 
     593             :   // Compute the resulting length.
     594             :   Node* length =
     595        2363 :       graph()->NewNode(simplified()->NumberAdd(), first_length, second_length);
     596             : 
     597        2363 :   if (isolate()->IsStringLengthOverflowIntact()) {
     598             :     // We can just deoptimize if the {length} is out-of-bounds. Besides
     599             :     // generating a shorter code sequence than the version below, this
     600             :     // has the additional benefit of not holding on to the lazy {frame_state}
     601             :     // and thus potentially reduces the number of live ranges and allows for
     602             :     // more truncations.
     603             :     length = effect = graph()->NewNode(simplified()->CheckBounds(), length,
     604             :                                        jsgraph()->Constant(String::kMaxLength),
     605        6924 :                                        effect, control);
     606             :   } else {
     607             :     // Check if we would overflow the allowed maximum string length.
     608             :     Node* check =
     609             :         graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
     610         110 :                          jsgraph()->Constant(String::kMaxLength));
     611             :     Node* branch =
     612          55 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
     613          55 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
     614          55 :     Node* efalse = effect;
     615             :     {
     616             :       // Throw a RangeError in case of overflow.
     617             :       Node* vfalse = efalse = if_false = graph()->NewNode(
     618             :           javascript()->CallRuntime(Runtime::kThrowInvalidStringLength),
     619          55 :           context, frame_state, efalse, if_false);
     620             : 
     621             :       // Update potential {IfException} uses of {node} to point to the
     622             :       // %ThrowInvalidStringLength runtime call node instead.
     623          55 :       Node* on_exception = nullptr;
     624          55 :       if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
     625          25 :         NodeProperties::ReplaceControlInput(on_exception, vfalse);
     626          25 :         NodeProperties::ReplaceEffectInput(on_exception, efalse);
     627          25 :         if_false = graph()->NewNode(common()->IfSuccess(), vfalse);
     628        2443 :         Revisit(on_exception);
     629             :       }
     630             : 
     631             :       // The above %ThrowInvalidStringLength runtime call is an unconditional
     632             :       // throw, making it impossible to return a successful completion in this
     633             :       // case. We simply connect the successful completion to the graph end.
     634          55 :       if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
     635             :       // TODO(bmeurer): This should be on the AdvancedReducer somehow.
     636          55 :       NodeProperties::MergeControlToEnd(graph(), common(), if_false);
     637          55 :       Revisit(graph()->end());
     638             :     }
     639          55 :     control = graph()->NewNode(common()->IfTrue(), branch);
     640             :   }
     641             : 
     642             :   // Figure out the map for the resulting ConsString.
     643             :   // TODO(turbofan): We currently just use the cons_string_map here for
     644             :   // the sake of simplicity; we could also try to be smarter here and
     645             :   // use the one_byte_cons_string_map instead when the resulting ConsString
     646             :   // contains only one byte characters.
     647        2363 :   Node* value_map = jsgraph()->HeapConstant(factory()->cons_string_map());
     648             : 
     649             :   // Allocate the resulting ConsString.
     650        2363 :   AllocationBuilder a(jsgraph(), effect, control);
     651        2363 :   a.Allocate(ConsString::kSize, NOT_TENURED, Type::OtherString());
     652        2363 :   a.Store(AccessBuilder::ForMap(), value_map);
     653             :   a.Store(AccessBuilder::ForNameHashField(),
     654        2363 :           jsgraph()->Constant(Name::kEmptyHashField));
     655        2363 :   a.Store(AccessBuilder::ForStringLength(), length);
     656        2363 :   a.Store(AccessBuilder::ForConsStringFirst(), first);
     657        2363 :   a.Store(AccessBuilder::ForConsStringSecond(), second);
     658             : 
     659             :   // Morph the {node} into a {FinishRegion}.
     660             :   ReplaceWithValue(node, node, node, control);
     661        2363 :   a.FinishAndChange(node);
     662        2363 :   return Changed(node);
     663             : }
     664             : 
     665        4726 : Node* JSTypedLowering::BuildGetStringLength(Node* value, Node** effect,
     666        2363 :                                             Node* control) {
     667             :   HeapObjectMatcher m(value);
     668             :   Node* length =
     669        2363 :       (m.HasValue() && m.Value()->IsString())
     670             :           ? jsgraph()->Constant(Handle<String>::cast(m.Value())->length())
     671             :           : (*effect) = graph()->NewNode(
     672             :                 simplified()->LoadField(AccessBuilder::ForStringLength()),
     673       11815 :                 value, *effect, control);
     674        4726 :   return length;
     675             : }
     676             : 
     677       67587 : Reduction JSTypedLowering::ReduceSpeculativeNumberComparison(Node* node) {
     678             :   JSBinopReduction r(this, node);
     679      114236 :   if (r.BothInputsAre(Type::Signed32()) ||
     680       46649 :       r.BothInputsAre(Type::Unsigned32())) {
     681       21166 :     return r.ChangeToPureOperator(r.NumberOpFromSpeculativeNumberOp());
     682             :   }
     683             :   return NoChange();
     684             : }
     685             : 
     686       55380 : Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
     687             :   JSBinopReduction r(this, node);
     688       37351 :   if (r.BothInputsAre(Type::String())) {
     689             :     // If both inputs are definitely strings, perform a string comparison.
     690             :     const Operator* stringOp;
     691        1058 :     switch (node->opcode()) {
     692             :       case IrOpcode::kJSLessThan:
     693         478 :         stringOp = simplified()->StringLessThan();
     694         478 :         break;
     695             :       case IrOpcode::kJSGreaterThan:
     696         199 :         stringOp = simplified()->StringLessThan();
     697         199 :         r.SwapInputs();  // a > b => b < a
     698         199 :         break;
     699             :       case IrOpcode::kJSLessThanOrEqual:
     700         190 :         stringOp = simplified()->StringLessThanOrEqual();
     701         190 :         break;
     702             :       case IrOpcode::kJSGreaterThanOrEqual:
     703         191 :         stringOp = simplified()->StringLessThanOrEqual();
     704         191 :         r.SwapInputs();  // a >= b => b <= a
     705         191 :         break;
     706             :       default:
     707             :         return NoChange();
     708             :     }
     709        1058 :     r.ChangeToPureOperator(stringOp);
     710             :     return Changed(node);
     711             :   }
     712             : 
     713             :   const Operator* less_than;
     714             :   const Operator* less_than_or_equal;
     715       67467 :   if (r.BothInputsAre(Type::Signed32()) ||
     716       31174 :       r.BothInputsAre(Type::Unsigned32())) {
     717        5284 :     less_than = simplified()->NumberLessThan();
     718        5284 :     less_than_or_equal = simplified()->NumberLessThanOrEqual();
     719       59977 :   } else if (r.OneInputCannotBe(Type::StringOrReceiver()) &&
     720       28968 :              r.BothInputsAre(Type::PlainPrimitive())) {
     721       11625 :     r.ConvertInputsToNumber();
     722       11625 :     less_than = simplified()->NumberLessThan();
     723       11625 :     less_than_or_equal = simplified()->NumberLessThanOrEqual();
     724       19384 :   } else if (r.IsStringCompareOperation()) {
     725          62 :     r.CheckInputsToString();
     726          62 :     less_than = simplified()->StringLessThan();
     727          62 :     less_than_or_equal = simplified()->StringLessThanOrEqual();
     728             :   } else {
     729             :     return NoChange();
     730             :   }
     731             :   const Operator* comparison;
     732       16971 :   switch (node->opcode()) {
     733             :     case IrOpcode::kJSLessThan:
     734             :       comparison = less_than;
     735             :       break;
     736             :     case IrOpcode::kJSGreaterThan:
     737             :       comparison = less_than;
     738        6709 :       r.SwapInputs();  // a > b => b < a
     739        6709 :       break;
     740             :     case IrOpcode::kJSLessThanOrEqual:
     741             :       comparison = less_than_or_equal;
     742        1968 :       break;
     743             :     case IrOpcode::kJSGreaterThanOrEqual:
     744             :       comparison = less_than_or_equal;
     745        1839 :       r.SwapInputs();  // a >= b => b <= a
     746        1839 :       break;
     747             :     default:
     748             :       return NoChange();
     749             :   }
     750       16971 :   return r.ChangeToPureOperator(comparison);
     751             : }
     752             : 
     753       13709 : Reduction JSTypedLowering::ReduceJSEqual(Node* node) {
     754             :   JSBinopReduction r(this, node);
     755             : 
     756       13709 :   if (r.BothInputsAre(Type::UniqueName())) {
     757         925 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     758             :   }
     759       12784 :   if (r.IsInternalizedStringCompareOperation()) {
     760         101 :     r.CheckInputsToInternalizedString();
     761         101 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     762             :   }
     763       12683 :   if (r.BothInputsAre(Type::String())) {
     764         241 :     return r.ChangeToPureOperator(simplified()->StringEqual());
     765             :   }
     766       12442 :   if (r.BothInputsAre(Type::Boolean())) {
     767          38 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     768             :   }
     769       12404 :   if (r.BothInputsAre(Type::Receiver())) {
     770          25 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     771             :   }
     772       12379 :   if (r.OneInputIs(Type::Undetectable())) {
     773             :     RelaxEffectsAndControls(node);
     774          51 :     node->RemoveInput(r.LeftInputIs(Type::Undetectable()) ? 0 : 1);
     775          51 :     node->TrimInputCount(1);
     776          51 :     NodeProperties::ChangeOp(node, simplified()->ObjectIsUndetectable());
     777             :     return Changed(node);
     778             :   }
     779             : 
     780       20942 :   if (r.BothInputsAre(Type::Signed32()) ||
     781        8614 :       r.BothInputsAre(Type::Unsigned32())) {
     782        3766 :     return r.ChangeToPureOperator(simplified()->NumberEqual());
     783        8562 :   } else if (r.BothInputsAre(Type::Number())) {
     784         832 :     return r.ChangeToPureOperator(simplified()->NumberEqual());
     785        7730 :   } else if (r.IsReceiverCompareOperation()) {
     786         113 :     r.CheckInputsToReceiver();
     787         113 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     788        7617 :   } else if (r.IsStringCompareOperation()) {
     789          24 :     r.CheckInputsToString();
     790          24 :     return r.ChangeToPureOperator(simplified()->StringEqual());
     791        7593 :   } else if (r.IsSymbolCompareOperation()) {
     792           0 :     r.CheckInputsToSymbol();
     793           0 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     794             :   }
     795             :   return NoChange();
     796             : }
     797             : 
     798      154848 : Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node) {
     799             :   JSBinopReduction r(this, node);
     800      306744 :   if (r.left() == r.right()) {
     801             :     // x === x is always true if x != NaN
     802             :     Node* replacement = graph()->NewNode(
     803             :         simplified()->BooleanNot(),
     804       13545 :         graph()->NewNode(simplified()->ObjectIsNaN(), r.left()));
     805        5991 :     ReplaceWithValue(node, replacement);
     806             :     return Replace(replacement);
     807             :   }
     808      148857 :   if (r.OneInputCannotBe(Type::NumberOrString())) {
     809             :     // For values with canonical representation (i.e. neither String, nor
     810             :     // Number) an empty type intersection means the values cannot be strictly
     811             :     // equal.
     812       10512 :     if (!r.left_type()->Maybe(r.right_type())) {
     813        1476 :       Node* replacement = jsgraph()->FalseConstant();
     814             :       ReplaceWithValue(node, replacement);
     815             :       return Replace(replacement);
     816             :     }
     817             :   }
     818             : 
     819      147381 :   if (r.BothInputsAre(Type::Unique())) {
     820        8640 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     821             :   }
     822      138741 :   if (r.OneInputIs(pointer_comparable_type_)) {
     823        2505 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     824             :   }
     825      136236 :   if (r.IsInternalizedStringCompareOperation()) {
     826        3903 :     r.CheckInputsToInternalizedString();
     827        3903 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     828             :   }
     829      132333 :   if (r.BothInputsAre(Type::String())) {
     830        2360 :     return r.ChangeToPureOperator(simplified()->StringEqual());
     831             :   }
     832             : 
     833             :   NumberOperationHint hint;
     834      240266 :   if (r.BothInputsAre(Type::Signed32()) ||
     835      110293 :       r.BothInputsAre(Type::Unsigned32())) {
     836       20085 :     return r.ChangeToPureOperator(simplified()->NumberEqual());
     837      109888 :   } else if (r.GetCompareNumberOperationHint(&hint)) {
     838             :     return r.ChangeToSpeculativeOperator(
     839       33820 :         simplified()->SpeculativeNumberEqual(hint), Type::Boolean());
     840       92978 :   } else if (r.BothInputsAre(Type::Number())) {
     841        5322 :     return r.ChangeToPureOperator(simplified()->NumberEqual());
     842       87656 :   } else if (r.IsReceiverCompareOperation()) {
     843             :     // For strict equality, it's enough to know that one input is a Receiver,
     844             :     // as a strict equality comparison with a Receiver can only yield true if
     845             :     // both sides refer to the same Receiver than.
     846         680 :     r.CheckLeftInputToReceiver();
     847         680 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     848       86976 :   } else if (r.IsStringCompareOperation()) {
     849        3056 :     r.CheckInputsToString();
     850        3056 :     return r.ChangeToPureOperator(simplified()->StringEqual());
     851       83920 :   } else if (r.IsSymbolCompareOperation()) {
     852           0 :     r.CheckInputsToSymbol();
     853           0 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     854             :   }
     855             :   return NoChange();
     856             : }
     857             : 
     858         175 : Reduction JSTypedLowering::ReduceJSToInteger(Node* node) {
     859         175 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     860             :   Type* const input_type = NodeProperties::GetType(input);
     861         350 :   if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
     862             :     // JSToInteger(x:integer) => x
     863           0 :     ReplaceWithValue(node, input);
     864             :     return Replace(input);
     865             :   }
     866             :   return NoChange();
     867             : }
     868             : 
     869        1086 : Reduction JSTypedLowering::ReduceJSToName(Node* node) {
     870        1086 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     871             :   Type* const input_type = NodeProperties::GetType(input);
     872        1086 :   if (input_type->Is(Type::Name())) {
     873             :     // JSToName(x:name) => x
     874         167 :     ReplaceWithValue(node, input);
     875             :     return Replace(input);
     876             :   }
     877             :   return NoChange();
     878             : }
     879             : 
     880         894 : Reduction JSTypedLowering::ReduceJSToLength(Node* node) {
     881         867 :   Node* input = NodeProperties::GetValueInput(node, 0);
     882             :   Type* input_type = NodeProperties::GetType(input);
     883        1734 :   if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
     884          27 :     if (input_type->Max() <= 0.0) {
     885           2 :       input = jsgraph()->ZeroConstant();
     886          25 :     } else if (input_type->Min() >= kMaxSafeInteger) {
     887           2 :       input = jsgraph()->Constant(kMaxSafeInteger);
     888             :     } else {
     889          23 :       if (input_type->Min() <= 0.0) {
     890             :         input = graph()->NewNode(simplified()->NumberMax(),
     891          46 :                                  jsgraph()->ZeroConstant(), input);
     892             :       }
     893          23 :       if (input_type->Max() > kMaxSafeInteger) {
     894             :         input = graph()->NewNode(simplified()->NumberMin(),
     895           0 :                                  jsgraph()->Constant(kMaxSafeInteger), input);
     896             :       }
     897             :     }
     898          27 :     ReplaceWithValue(node, input);
     899             :     return Replace(input);
     900             :   }
     901             :   return NoChange();
     902             : }
     903             : 
     904      306382 : Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
     905             :   // Try constant-folding of JSToNumber with constant inputs.
     906             :   Type* input_type = NodeProperties::GetType(input);
     907      302005 :   if (input_type->Is(Type::String())) {
     908             :     HeapObjectMatcher m(input);
     909        3546 :     if (m.HasValue() && m.Value()->IsString()) {
     910             :       Handle<Object> input_value = m.Value();
     911             :       return Replace(jsgraph()->Constant(
     912        2424 :           String::ToNumber(Handle<String>::cast(input_value))));
     913             :     }
     914             :   }
     915      300793 :   if (input_type->IsHeapConstant()) {
     916             :     Handle<Object> input_value = input_type->AsHeapConstant()->Value();
     917        1199 :     if (input_value->IsOddball()) {
     918             :       return Replace(jsgraph()->Constant(
     919        2394 :           Oddball::ToNumber(Handle<Oddball>::cast(input_value))));
     920             :     }
     921             :   }
     922      299596 :   if (input_type->Is(Type::Number())) {
     923             :     // JSToNumber(x:number) => x
     924             :     return Changed(input);
     925             :   }
     926       19134 :   if (input_type->Is(Type::Undefined())) {
     927             :     // JSToNumber(undefined) => #NaN
     928         984 :     return Replace(jsgraph()->NaNConstant());
     929             :   }
     930       18150 :   if (input_type->Is(Type::Null())) {
     931             :     // JSToNumber(null) => #0
     932         984 :     return Replace(jsgraph()->ZeroConstant());
     933             :   }
     934             :   return NoChange();
     935             : }
     936             : 
     937       11549 : Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
     938             :   // Try to reduce the input first.
     939             :   Node* const input = node->InputAt(0);
     940       11549 :   Reduction reduction = ReduceJSToNumberInput(input);
     941       11549 :   if (reduction.Changed()) {
     942        2783 :     ReplaceWithValue(node, reduction.replacement());
     943        2783 :     return reduction;
     944             :   }
     945             :   Type* const input_type = NodeProperties::GetType(input);
     946        8766 :   if (input_type->Is(Type::PlainPrimitive())) {
     947             :     RelaxEffectsAndControls(node);
     948         186 :     node->TrimInputCount(1);
     949         186 :     NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber());
     950             :     return Changed(node);
     951             :   }
     952             :   return NoChange();
     953             : }
     954             : 
     955       55896 : Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
     956       55021 :   if (input->opcode() == IrOpcode::kJSToString) {
     957             :     // Recursively try to reduce the input first.
     958         976 :     Reduction result = ReduceJSToString(input);
     959         976 :     if (result.Changed()) return result;
     960             :     return Changed(input);  // JSToString(JSToString(x)) => JSToString(x)
     961             :   }
     962             :   Type* input_type = NodeProperties::GetType(input);
     963       54045 :   if (input_type->Is(Type::String())) {
     964             :     return Changed(input);  // JSToString(x:string) => x
     965             :   }
     966       36107 :   if (input_type->Is(Type::Boolean())) {
     967             :     return Replace(graph()->NewNode(
     968             :         common()->Select(MachineRepresentation::kTagged), input,
     969             :         jsgraph()->HeapConstant(factory()->true_string()),
     970         276 :         jsgraph()->HeapConstant(factory()->false_string())));
     971             :   }
     972       36038 :   if (input_type->Is(Type::Undefined())) {
     973          79 :     return Replace(jsgraph()->HeapConstant(factory()->undefined_string()));
     974             :   }
     975       35959 :   if (input_type->Is(Type::Null())) {
     976          25 :     return Replace(jsgraph()->HeapConstant(factory()->null_string()));
     977             :   }
     978       35934 :   if (input_type->Is(Type::NaN())) {
     979          82 :     return Replace(jsgraph()->HeapConstant(factory()->NaN_string()));
     980             :   }
     981       37816 :   if (input_type->Is(Type::OrderedNumber()) &&
     982        1964 :       input_type->Min() == input_type->Max()) {
     983             :     // Note that we can use Type::OrderedNumber(), since
     984             :     // both 0 and -0 map to the String "0" in JavaScript.
     985             :     return Replace(jsgraph()->HeapConstant(
     986        3500 :         factory()->NumberToString(factory()->NewNumber(input_type->Min()))));
     987             :   }
     988             :   // TODO(turbofan): js-typed-lowering of ToString(x:number)
     989             :   return NoChange();
     990             : }
     991             : 
     992        3842 : Reduction JSTypedLowering::ReduceJSToString(Node* node) {
     993             :   DCHECK_EQ(IrOpcode::kJSToString, node->opcode());
     994             :   // Try to reduce the input first.
     995             :   Node* const input = node->InputAt(0);
     996        3842 :   Reduction reduction = ReduceJSToStringInput(input);
     997        3842 :   if (reduction.Changed()) {
     998         179 :     ReplaceWithValue(node, reduction.replacement());
     999         179 :     return reduction;
    1000             :   }
    1001             :   return NoChange();
    1002             : }
    1003             : 
    1004        7634 : Reduction JSTypedLowering::ReduceJSToObject(Node* node) {
    1005             :   DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
    1006        3096 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1007             :   Type* receiver_type = NodeProperties::GetType(receiver);
    1008        3096 :   Node* context = NodeProperties::GetContextInput(node);
    1009        3096 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    1010        3096 :   Node* effect = NodeProperties::GetEffectInput(node);
    1011        3096 :   Node* control = NodeProperties::GetControlInput(node);
    1012        3096 :   if (receiver_type->Is(Type::Receiver())) {
    1013        3168 :     ReplaceWithValue(node, receiver, effect, control);
    1014             :     return Replace(receiver);
    1015             :   }
    1016             : 
    1017             :   // Check whether {receiver} is a spec object.
    1018        2269 :   Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
    1019             :   Node* branch =
    1020        2269 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    1021             : 
    1022        2269 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1023             :   Node* etrue = effect;
    1024             :   Node* rtrue = receiver;
    1025             : 
    1026        2269 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    1027             :   Node* efalse = effect;
    1028             :   Node* rfalse;
    1029             :   {
    1030             :     // Convert {receiver} using the ToObjectStub.
    1031        2269 :     Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject);
    1032             :     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    1033             :         isolate(), graph()->zone(), callable.descriptor(), 0,
    1034        6807 :         CallDescriptor::kNeedsFrameState, node->op()->properties());
    1035             :     rfalse = efalse = if_false = graph()->NewNode(
    1036             :         common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
    1037        6807 :         receiver, context, frame_state, efalse, if_false);
    1038             :   }
    1039             : 
    1040             :   // Update potential {IfException} uses of {node} to point to the above
    1041             :   // ToObject stub call node instead. Note that the stub can only throw on
    1042             :   // receivers that can be null or undefined.
    1043        2269 :   Node* on_exception = nullptr;
    1044        4458 :   if (receiver_type->Maybe(Type::NullOrUndefined()) &&
    1045        2189 :       NodeProperties::IsExceptionalCall(node, &on_exception)) {
    1046          72 :     NodeProperties::ReplaceControlInput(on_exception, if_false);
    1047          72 :     NodeProperties::ReplaceEffectInput(on_exception, efalse);
    1048          72 :     if_false = graph()->NewNode(common()->IfSuccess(), if_false);
    1049          72 :     Revisit(on_exception);
    1050             :   }
    1051             : 
    1052        2269 :   control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    1053        2269 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    1054             : 
    1055             :   // Morph the {node} into an appropriate Phi.
    1056             :   ReplaceWithValue(node, node, effect, control);
    1057        2269 :   node->ReplaceInput(0, rtrue);
    1058        2269 :   node->ReplaceInput(1, rfalse);
    1059        2269 :   node->ReplaceInput(2, control);
    1060        2269 :   node->TrimInputCount(3);
    1061             :   NodeProperties::ChangeOp(node,
    1062        2269 :                            common()->Phi(MachineRepresentation::kTagged, 2));
    1063             :   return Changed(node);
    1064             : }
    1065             : 
    1066      931326 : Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
    1067             :   DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
    1068      465663 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1069             :   Type* receiver_type = NodeProperties::GetType(receiver);
    1070      465663 :   Node* effect = NodeProperties::GetEffectInput(node);
    1071      465663 :   Node* control = NodeProperties::GetControlInput(node);
    1072      465663 :   Handle<Name> name = NamedAccessOf(node->op()).name();
    1073             :   // Optimize "length" property of strings.
    1074      493995 :   if (name.is_identical_to(factory()->length_string()) &&
    1075             :       receiver_type->Is(Type::String())) {
    1076             :     Node* value = effect = graph()->NewNode(
    1077             :         simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
    1078         795 :         effect, control);
    1079         265 :     ReplaceWithValue(node, value, effect);
    1080             :     return Replace(value);
    1081             :   }
    1082             :   return NoChange();
    1083             : }
    1084             : 
    1085       10124 : Reduction JSTypedLowering::ReduceJSHasInPrototypeChain(Node* node) {
    1086             :   DCHECK_EQ(IrOpcode::kJSHasInPrototypeChain, node->opcode());
    1087        1288 :   Node* value = NodeProperties::GetValueInput(node, 0);
    1088             :   Type* value_type = NodeProperties::GetType(value);
    1089        1288 :   Node* prototype = NodeProperties::GetValueInput(node, 1);
    1090        1288 :   Node* context = NodeProperties::GetContextInput(node);
    1091        1288 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    1092        1288 :   Node* effect = NodeProperties::GetEffectInput(node);
    1093        1288 :   Node* control = NodeProperties::GetControlInput(node);
    1094             : 
    1095             :   // If {value} cannot be a receiver, then it cannot have {prototype} in
    1096             :   // it's prototype chain (all Primitive values have a null prototype).
    1097        1288 :   if (value_type->Is(Type::Primitive())) {
    1098          30 :     Node* value = jsgraph()->FalseConstant();
    1099        1352 :     ReplaceWithValue(node, value, effect, control);
    1100             :     return Replace(value);
    1101             :   }
    1102             : 
    1103        1258 :   Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
    1104             :   Node* branch0 =
    1105        1258 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
    1106             : 
    1107        1258 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    1108             :   Node* etrue0 = effect;
    1109        1258 :   Node* vtrue0 = jsgraph()->FalseConstant();
    1110             : 
    1111        1258 :   control = graph()->NewNode(common()->IfFalse(), branch0);
    1112             : 
    1113             :   // Loop through the {value}s prototype chain looking for the {prototype}.
    1114        1258 :   Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
    1115             :   Node* eloop = effect =
    1116        1258 :       graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    1117             :   Node* vloop = value = graph()->NewNode(
    1118        1258 :       common()->Phi(MachineRepresentation::kTagged, 2), value, value, loop);
    1119             :   NodeProperties::SetType(vloop, Type::NonInternal());
    1120             : 
    1121             :   // Load the {value} map and instance type.
    1122             :   Node* value_map = effect = graph()->NewNode(
    1123        3774 :       simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
    1124             :   Node* value_instance_type = effect = graph()->NewNode(
    1125             :       simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
    1126        3774 :       effect, control);
    1127             : 
    1128             :   // Check if the {value} is a special receiver, because for special
    1129             :   // receivers, i.e. proxies or API values that need access checks,
    1130             :   // we have to use the %HasInPrototypeChain runtime function instead.
    1131             :   Node* check1 = graph()->NewNode(
    1132             :       simplified()->NumberLessThanOrEqual(), value_instance_type,
    1133        2516 :       jsgraph()->Constant(LAST_SPECIAL_RECEIVER_TYPE));
    1134             :   Node* branch1 =
    1135        1258 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
    1136             : 
    1137        1258 :   control = graph()->NewNode(common()->IfFalse(), branch1);
    1138             : 
    1139        1258 :   Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    1140             :   Node* etrue1 = effect;
    1141             :   Node* vtrue1;
    1142             : 
    1143             :   // Check if the {value} is not a receiver at all.
    1144             :   Node* check10 =
    1145             :       graph()->NewNode(simplified()->NumberLessThan(), value_instance_type,
    1146        2516 :                        jsgraph()->Constant(FIRST_JS_RECEIVER_TYPE));
    1147             :   Node* branch10 =
    1148        1258 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check10, if_true1);
    1149             : 
    1150             :   // A primitive value cannot match the {prototype} we're looking for.
    1151        1258 :   if_true1 = graph()->NewNode(common()->IfTrue(), branch10);
    1152        1258 :   vtrue1 = jsgraph()->FalseConstant();
    1153             : 
    1154        1258 :   Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10);
    1155             :   Node* efalse1 = etrue1;
    1156             :   Node* vfalse1;
    1157             :   {
    1158             :     // Slow path, need to call the %HasInPrototypeChain runtime function.
    1159             :     vfalse1 = efalse1 = if_false1 = graph()->NewNode(
    1160             :         javascript()->CallRuntime(Runtime::kHasInPrototypeChain), value,
    1161        1258 :         prototype, context, frame_state, efalse1, if_false1);
    1162             : 
    1163             :     // Replace any potential {IfException} uses of {node} to catch
    1164             :     // exceptions from this %HasInPrototypeChain runtime call instead.
    1165        1258 :     Node* on_exception = nullptr;
    1166        1258 :     if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    1167          64 :       NodeProperties::ReplaceControlInput(on_exception, vfalse1);
    1168          64 :       NodeProperties::ReplaceEffectInput(on_exception, efalse1);
    1169          64 :       if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1);
    1170          64 :       Revisit(on_exception);
    1171             :     }
    1172             :   }
    1173             : 
    1174             :   // Load the {value} prototype.
    1175             :   Node* value_prototype = effect = graph()->NewNode(
    1176             :       simplified()->LoadField(AccessBuilder::ForMapPrototype()), value_map,
    1177        3774 :       effect, control);
    1178             : 
    1179             :   // Check if we reached the end of {value}s prototype chain.
    1180             :   Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(),
    1181        2516 :                                   value_prototype, jsgraph()->NullConstant());
    1182        1258 :   Node* branch2 = graph()->NewNode(common()->Branch(), check2, control);
    1183             : 
    1184        1258 :   Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
    1185             :   Node* etrue2 = effect;
    1186        1258 :   Node* vtrue2 = jsgraph()->FalseConstant();
    1187             : 
    1188        1258 :   control = graph()->NewNode(common()->IfFalse(), branch2);
    1189             : 
    1190             :   // Check if we reached the {prototype}.
    1191             :   Node* check3 = graph()->NewNode(simplified()->ReferenceEqual(),
    1192        1258 :                                   value_prototype, prototype);
    1193        1258 :   Node* branch3 = graph()->NewNode(common()->Branch(), check3, control);
    1194             : 
    1195        1258 :   Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
    1196             :   Node* etrue3 = effect;
    1197        1258 :   Node* vtrue3 = jsgraph()->TrueConstant();
    1198             : 
    1199        1258 :   control = graph()->NewNode(common()->IfFalse(), branch3);
    1200             : 
    1201             :   // Close the loop.
    1202        1258 :   vloop->ReplaceInput(1, value_prototype);
    1203        1258 :   eloop->ReplaceInput(1, effect);
    1204        1258 :   loop->ReplaceInput(1, control);
    1205             : 
    1206             :   control = graph()->NewNode(common()->Merge(5), if_true0, if_true1, if_true2,
    1207        1258 :                              if_true3, if_false1);
    1208             :   effect = graph()->NewNode(common()->EffectPhi(5), etrue0, etrue1, etrue2,
    1209        1258 :                             etrue3, efalse1, control);
    1210             : 
    1211             :   // Morph the {node} into an appropriate Phi.
    1212             :   ReplaceWithValue(node, node, effect, control);
    1213        1258 :   node->ReplaceInput(0, vtrue0);
    1214        1258 :   node->ReplaceInput(1, vtrue1);
    1215        1258 :   node->ReplaceInput(2, vtrue2);
    1216        1258 :   node->ReplaceInput(3, vtrue3);
    1217        1258 :   node->ReplaceInput(4, vfalse1);
    1218        1258 :   node->ReplaceInput(5, control);
    1219        1258 :   node->TrimInputCount(6);
    1220             :   NodeProperties::ChangeOp(node,
    1221        1258 :                            common()->Phi(MachineRepresentation::kTagged, 5));
    1222             :   return Changed(node);
    1223             : }
    1224             : 
    1225          99 : Reduction JSTypedLowering::ReduceJSOrdinaryHasInstance(Node* node) {
    1226             :   DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
    1227          75 :   Node* constructor = NodeProperties::GetValueInput(node, 0);
    1228             :   Type* constructor_type = NodeProperties::GetType(constructor);
    1229          75 :   Node* object = NodeProperties::GetValueInput(node, 1);
    1230             :   Type* object_type = NodeProperties::GetType(object);
    1231             : 
    1232             :   // Check if the {constructor} cannot be callable.
    1233             :   // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 1.
    1234          75 :   if (!constructor_type->Maybe(Type::Callable())) {
    1235           8 :     Node* value = jsgraph()->FalseConstant();
    1236          24 :     ReplaceWithValue(node, value);
    1237             :     return Replace(value);
    1238             :   }
    1239             : 
    1240             :   // If the {constructor} cannot be a JSBoundFunction and then {object}
    1241             :   // cannot be a JSReceiver, then this can be constant-folded to false.
    1242             :   // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 2 and 3.
    1243          83 :   if (!object_type->Maybe(Type::Receiver()) &&
    1244          16 :       !constructor_type->Maybe(Type::BoundFunction())) {
    1245          16 :     Node* value = jsgraph()->FalseConstant();
    1246             :     ReplaceWithValue(node, value);
    1247             :     return Replace(value);
    1248             :   }
    1249             : 
    1250             :   return NoChange();
    1251             : }
    1252             : 
    1253     1374800 : Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
    1254             :   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
    1255     2063945 :   ContextAccess const& access = ContextAccessOf(node->op());
    1256      687400 :   Node* effect = NodeProperties::GetEffectInput(node);
    1257      687400 :   Node* context = NodeProperties::GetContextInput(node);
    1258      687400 :   Node* control = graph()->start();
    1259     1378290 :   for (size_t i = 0; i < access.depth(); ++i) {
    1260             :     context = effect = graph()->NewNode(
    1261             :         simplified()->LoadField(
    1262             :             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
    1263        5235 :         context, effect, control);
    1264             :   }
    1265      687400 :   node->ReplaceInput(0, context);
    1266      687400 :   node->ReplaceInput(1, effect);
    1267      687400 :   node->AppendInput(jsgraph()->zone(), control);
    1268             :   NodeProperties::ChangeOp(
    1269             :       node,
    1270     1374800 :       simplified()->LoadField(AccessBuilder::ForContextSlot(access.index())));
    1271      687400 :   return Changed(node);
    1272             : }
    1273             : 
    1274      345503 : Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
    1275             :   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
    1276     1036557 :   ContextAccess const& access = ContextAccessOf(node->op());
    1277      345503 :   Node* effect = NodeProperties::GetEffectInput(node);
    1278      345503 :   Node* context = NodeProperties::GetContextInput(node);
    1279      345503 :   Node* control = graph()->start();
    1280      345503 :   Node* value = NodeProperties::GetValueInput(node, 0);
    1281      691102 :   for (size_t i = 0; i < access.depth(); ++i) {
    1282             :     context = effect = graph()->NewNode(
    1283             :         simplified()->LoadField(
    1284             :             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
    1285         144 :         context, effect, control);
    1286             :   }
    1287      345503 :   node->ReplaceInput(0, context);
    1288      345503 :   node->ReplaceInput(1, value);
    1289      345503 :   node->ReplaceInput(2, effect);
    1290             :   NodeProperties::ChangeOp(
    1291             :       node,
    1292      691006 :       simplified()->StoreField(AccessBuilder::ForContextSlot(access.index())));
    1293      345503 :   return Changed(node);
    1294             : }
    1295             : 
    1296        7307 : Node* JSTypedLowering::BuildGetModuleCell(Node* node) {
    1297             :   DCHECK(node->opcode() == IrOpcode::kJSLoadModule ||
    1298             :          node->opcode() == IrOpcode::kJSStoreModule);
    1299        7163 :   Node* effect = NodeProperties::GetEffectInput(node);
    1300        7163 :   Node* control = NodeProperties::GetControlInput(node);
    1301             : 
    1302        7163 :   int32_t cell_index = OpParameter<int32_t>(node);
    1303        7163 :   Node* module = NodeProperties::GetValueInput(node, 0);
    1304             :   Type* module_type = NodeProperties::GetType(module);
    1305             : 
    1306        7163 :   if (module_type->IsHeapConstant()) {
    1307             :     Handle<Module> module_constant =
    1308             :         Handle<Module>::cast(module_type->AsHeapConstant()->Value());
    1309         144 :     Handle<Cell> cell_constant(module_constant->GetCell(cell_index), isolate());
    1310         144 :     return jsgraph()->HeapConstant(cell_constant);
    1311             :   }
    1312             : 
    1313             :   FieldAccess field_access;
    1314             :   int index;
    1315        7019 :   if (ModuleDescriptor::GetCellIndexKind(cell_index) ==
    1316             :       ModuleDescriptor::kExport) {
    1317        6932 :     field_access = AccessBuilder::ForModuleRegularExports();
    1318        6932 :     index = cell_index - 1;
    1319             :   } else {
    1320             :     DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
    1321             :               ModuleDescriptor::kImport);
    1322          87 :     field_access = AccessBuilder::ForModuleRegularImports();
    1323          87 :     index = -cell_index - 1;
    1324             :   }
    1325             :   Node* array = effect = graph()->NewNode(simplified()->LoadField(field_access),
    1326        7019 :                                           module, effect, control);
    1327             :   return graph()->NewNode(
    1328        7019 :       simplified()->LoadField(AccessBuilder::ForFixedArraySlot(index)), array,
    1329       21057 :       effect, control);
    1330             : }
    1331             : 
    1332         280 : Reduction JSTypedLowering::ReduceJSLoadModule(Node* node) {
    1333             :   DCHECK_EQ(IrOpcode::kJSLoadModule, node->opcode());
    1334         280 :   Node* effect = NodeProperties::GetEffectInput(node);
    1335         280 :   Node* control = NodeProperties::GetControlInput(node);
    1336             : 
    1337         280 :   Node* cell = BuildGetModuleCell(node);
    1338         560 :   if (cell->op()->EffectOutputCount() > 0) effect = cell;
    1339             :   Node* value = effect =
    1340             :       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForCellValue()),
    1341         840 :                        cell, effect, control);
    1342             : 
    1343         280 :   ReplaceWithValue(node, value, effect, control);
    1344         280 :   return Changed(value);
    1345             : }
    1346             : 
    1347        6883 : Reduction JSTypedLowering::ReduceJSStoreModule(Node* node) {
    1348             :   DCHECK_EQ(IrOpcode::kJSStoreModule, node->opcode());
    1349        6883 :   Node* effect = NodeProperties::GetEffectInput(node);
    1350        6883 :   Node* control = NodeProperties::GetControlInput(node);
    1351        6883 :   Node* value = NodeProperties::GetValueInput(node, 1);
    1352             :   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(OpParameter<int32_t>(node)),
    1353             :             ModuleDescriptor::kExport);
    1354             : 
    1355        6883 :   Node* cell = BuildGetModuleCell(node);
    1356       13766 :   if (cell->op()->EffectOutputCount() > 0) effect = cell;
    1357             :   effect =
    1358             :       graph()->NewNode(simplified()->StoreField(AccessBuilder::ForCellValue()),
    1359       20649 :                        cell, value, effect, control);
    1360             : 
    1361        6883 :   ReplaceWithValue(node, effect, effect, control);
    1362        6883 :   return Changed(value);
    1363             : }
    1364             : 
    1365      177848 : Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
    1366             :   DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode());
    1367      128052 :   ConvertReceiverMode mode = ConvertReceiverModeOf(node->op());
    1368      128052 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1369             :   Type* receiver_type = NodeProperties::GetType(receiver);
    1370      128052 :   Node* context = NodeProperties::GetContextInput(node);
    1371             :   Type* context_type = NodeProperties::GetType(context);
    1372      128052 :   Node* effect = NodeProperties::GetEffectInput(node);
    1373      128052 :   Node* control = NodeProperties::GetControlInput(node);
    1374             : 
    1375             :   // Check if {receiver} is known to be a receiver.
    1376      128052 :   if (receiver_type->Is(Type::Receiver())) {
    1377      128052 :     ReplaceWithValue(node, receiver, effect, control);
    1378             :     return Replace(receiver);
    1379             :   }
    1380             : 
    1381             :   // If the {receiver} is known to be null or undefined, we can just replace it
    1382             :   // with the global proxy unconditionally.
    1383      128025 :   if (receiver_type->Is(Type::NullOrUndefined()) ||
    1384             :       mode == ConvertReceiverMode::kNullOrUndefined) {
    1385      127095 :     if (context_type->IsHeapConstant()) {
    1386             :       Handle<JSObject> global_proxy(
    1387             :           Handle<Context>::cast(context_type->AsHeapConstant()->Value())
    1388             :               ->global_proxy(),
    1389       47867 :           isolate());
    1390       47867 :       receiver = jsgraph()->Constant(global_proxy);
    1391             :     } else {
    1392             :       Node* native_context = effect = graph()->NewNode(
    1393             :           javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
    1394       79228 :           context, effect);
    1395             :       receiver = effect = graph()->NewNode(
    1396             :           javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
    1397       79228 :           native_context, effect);
    1398             :     }
    1399             :     ReplaceWithValue(node, receiver, effect, control);
    1400             :     return Replace(receiver);
    1401             :   }
    1402             : 
    1403             :   // If {receiver} cannot be null or undefined we can skip a few checks.
    1404         930 :   if (!receiver_type->Maybe(Type::NullOrUndefined()) ||
    1405             :       mode == ConvertReceiverMode::kNotNullOrUndefined) {
    1406         907 :     Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
    1407             :     Node* branch =
    1408         907 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    1409             : 
    1410         907 :     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1411             :     Node* etrue = effect;
    1412             :     Node* rtrue = receiver;
    1413             : 
    1414         907 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    1415             :     Node* efalse = effect;
    1416             :     Node* rfalse;
    1417             :     {
    1418             :       // Convert {receiver} using the ToObjectStub. The call does not require a
    1419             :       // frame-state in this case, because neither null nor undefined is passed.
    1420         907 :       Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject);
    1421             :       CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    1422             :           isolate(), graph()->zone(), callable.descriptor(), 0,
    1423        2721 :           CallDescriptor::kNoFlags, node->op()->properties());
    1424             :       rfalse = efalse = graph()->NewNode(
    1425             :           common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
    1426        2721 :           receiver, context, efalse);
    1427             :     }
    1428             : 
    1429         907 :     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    1430         907 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    1431             : 
    1432             :     // Morph the {node} into an appropriate Phi.
    1433             :     ReplaceWithValue(node, node, effect, control);
    1434         907 :     node->ReplaceInput(0, rtrue);
    1435         907 :     node->ReplaceInput(1, rfalse);
    1436         907 :     node->ReplaceInput(2, control);
    1437         907 :     node->TrimInputCount(3);
    1438             :     NodeProperties::ChangeOp(node,
    1439         907 :                              common()->Phi(MachineRepresentation::kTagged, 2));
    1440             :     return Changed(node);
    1441             :   }
    1442             : 
    1443             :   // Check if {receiver} is already a JSReceiver.
    1444          23 :   Node* check0 = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
    1445             :   Node* branch0 =
    1446          23 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
    1447          23 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    1448          23 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    1449             : 
    1450             :   // Check {receiver} for undefined.
    1451             :   Node* check1 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
    1452          46 :                                   jsgraph()->UndefinedConstant());
    1453             :   Node* branch1 =
    1454          23 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, if_false0);
    1455          23 :   Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    1456          23 :   Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    1457             : 
    1458             :   // Check {receiver} for null.
    1459             :   Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
    1460          46 :                                   jsgraph()->NullConstant());
    1461             :   Node* branch2 =
    1462          23 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check2, if_false1);
    1463          23 :   Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
    1464          23 :   Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
    1465             : 
    1466             :   // We just use {receiver} directly.
    1467             :   Node* if_noop = if_true0;
    1468             :   Node* enoop = effect;
    1469             :   Node* rnoop = receiver;
    1470             : 
    1471             :   // Convert {receiver} using ToObject.
    1472             :   Node* if_convert = if_false2;
    1473             :   Node* econvert = effect;
    1474             :   Node* rconvert;
    1475             :   {
    1476             :     // Convert {receiver} using the ToObjectStub. The call does not require a
    1477             :     // frame-state in this case, because neither null nor undefined is passed.
    1478          23 :     Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject);
    1479             :     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    1480             :         isolate(), graph()->zone(), callable.descriptor(), 0,
    1481          69 :         CallDescriptor::kNoFlags, node->op()->properties());
    1482             :     rconvert = econvert = graph()->NewNode(
    1483             :         common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
    1484          69 :         receiver, context, econvert);
    1485             :   }
    1486             : 
    1487             :   // Replace {receiver} with global proxy of {context}.
    1488          23 :   Node* if_global = graph()->NewNode(common()->Merge(2), if_true1, if_true2);
    1489             :   Node* eglobal = effect;
    1490             :   Node* rglobal;
    1491             :   {
    1492          23 :     if (context_type->IsHeapConstant()) {
    1493             :       Handle<JSObject> global_proxy(
    1494             :           Handle<Context>::cast(context_type->AsHeapConstant()->Value())
    1495             :               ->global_proxy(),
    1496          23 :           isolate());
    1497          23 :       rglobal = jsgraph()->Constant(global_proxy);
    1498             :     } else {
    1499             :       Node* native_context = eglobal = graph()->NewNode(
    1500             :           javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
    1501           0 :           context, eglobal);
    1502             :       rglobal = eglobal = graph()->NewNode(
    1503             :           javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
    1504           0 :           native_context, eglobal);
    1505             :     }
    1506             :   }
    1507             : 
    1508             :   control =
    1509          23 :       graph()->NewNode(common()->Merge(3), if_noop, if_convert, if_global);
    1510             :   effect = graph()->NewNode(common()->EffectPhi(3), enoop, econvert, eglobal,
    1511          23 :                             control);
    1512             :   // Morph the {node} into an appropriate Phi.
    1513             :   ReplaceWithValue(node, node, effect, control);
    1514          23 :   node->ReplaceInput(0, rnoop);
    1515          23 :   node->ReplaceInput(1, rconvert);
    1516          23 :   node->ReplaceInput(2, rglobal);
    1517          23 :   node->ReplaceInput(3, control);
    1518          23 :   node->TrimInputCount(4);
    1519             :   NodeProperties::ChangeOp(node,
    1520          23 :                            common()->Phi(MachineRepresentation::kTagged, 3));
    1521             :   return Changed(node);
    1522             : }
    1523             : 
    1524             : namespace {
    1525             : 
    1526       23520 : void ReduceBuiltin(Isolate* isolate, JSGraph* jsgraph, Node* node,
    1527             :                    int builtin_index, int arity, CallDescriptor::Flags flags) {
    1528             :   // Patch {node} to a direct CEntryStub call.
    1529             :   //
    1530             :   // ----------- A r g u m e n t s -----------
    1531             :   // -- 0: CEntryStub
    1532             :   // --- Stack args ---
    1533             :   // -- 1: receiver
    1534             :   // -- [2, 2 + n[: the n actual arguments passed to the builtin
    1535             :   // -- 2 + n: argc, including the receiver and implicit args (Smi)
    1536             :   // -- 2 + n + 1: target
    1537             :   // -- 2 + n + 2: new_target
    1538             :   // --- Register args ---
    1539             :   // -- 2 + n + 3: the C entry point
    1540             :   // -- 2 + n + 4: argc (Int32)
    1541             :   // -----------------------------------
    1542             : 
    1543             :   // The logic contained here is mirrored in Builtins::Generate_Adaptor.
    1544             :   // Keep these in sync.
    1545             : 
    1546        7840 :   const bool is_construct = (node->opcode() == IrOpcode::kJSConstruct);
    1547             : 
    1548             :   DCHECK(Builtins::HasCppImplementation(builtin_index));
    1549             :   DCHECK_EQ(0, flags & CallDescriptor::kSupportsTailCalls);
    1550             : 
    1551        7840 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1552             :   Node* new_target = is_construct
    1553        2558 :                          ? NodeProperties::GetValueInput(node, arity + 1)
    1554       10398 :                          : jsgraph->UndefinedConstant();
    1555             : 
    1556             :   // API and CPP builtins are implemented in C++, and we can inline both.
    1557             :   // CPP builtins create a builtin exit frame, API builtins don't.
    1558        7840 :   const bool has_builtin_exit_frame = Builtins::IsCpp(builtin_index);
    1559             : 
    1560             :   Node* stub = jsgraph->CEntryStubConstant(1, kDontSaveFPRegs, kArgvOnStack,
    1561        7840 :                                            has_builtin_exit_frame);
    1562        7840 :   node->ReplaceInput(0, stub);
    1563             : 
    1564             :   Zone* zone = jsgraph->zone();
    1565        7840 :   if (is_construct) {
    1566             :     // Unify representations between construct and call nodes.
    1567             :     // Remove new target and add receiver as a stack parameter.
    1568        2558 :     Node* receiver = jsgraph->UndefinedConstant();
    1569        2558 :     node->RemoveInput(arity + 1);
    1570        2558 :     node->InsertInput(zone, 1, receiver);
    1571             :   }
    1572             : 
    1573        7840 :   const int argc = arity + BuiltinArguments::kNumExtraArgsWithReceiver;
    1574        7840 :   Node* argc_node = jsgraph->Constant(argc);
    1575             : 
    1576             :   static const int kStubAndReceiver = 2;
    1577        7840 :   int cursor = arity + kStubAndReceiver;
    1578        7840 :   node->InsertInput(zone, cursor++, jsgraph->PaddingConstant());
    1579        7840 :   node->InsertInput(zone, cursor++, argc_node);
    1580        7840 :   node->InsertInput(zone, cursor++, target);
    1581        7840 :   node->InsertInput(zone, cursor++, new_target);
    1582             : 
    1583        7840 :   Address entry = Builtins::CppEntryOf(builtin_index);
    1584        7840 :   ExternalReference entry_ref(ExternalReference(entry, isolate));
    1585        7840 :   Node* entry_node = jsgraph->ExternalConstant(entry_ref);
    1586             : 
    1587        7840 :   node->InsertInput(zone, cursor++, entry_node);
    1588        7840 :   node->InsertInput(zone, cursor++, argc_node);
    1589             : 
    1590             :   static const int kReturnCount = 1;
    1591        7840 :   const char* debug_name = Builtins::name(builtin_index);
    1592        7840 :   Operator::Properties properties = node->op()->properties();
    1593             :   CallDescriptor* desc = Linkage::GetCEntryStubCallDescriptor(
    1594        7840 :       zone, kReturnCount, argc, debug_name, properties, flags);
    1595             : 
    1596        7840 :   NodeProperties::ChangeOp(node, jsgraph->common()->Call(desc));
    1597        7840 : }
    1598             : 
    1599             : bool NeedsArgumentAdaptorFrame(Handle<SharedFunctionInfo> shared, int arity) {
    1600             :   static const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
    1601             :   const int num_decl_parms = shared->internal_formal_parameter_count();
    1602      196588 :   return (num_decl_parms != arity && num_decl_parms != sentinel);
    1603             : }
    1604             : 
    1605             : }  // namespace
    1606             : 
    1607        2181 : Reduction JSTypedLowering::ReduceJSConstructForwardVarargs(Node* node) {
    1608             :   DCHECK_EQ(IrOpcode::kJSConstructForwardVarargs, node->opcode());
    1609             :   ConstructForwardVarargsParameters p =
    1610         453 :       ConstructForwardVarargsParametersOf(node->op());
    1611             :   DCHECK_LE(2u, p.arity());
    1612         453 :   int const arity = static_cast<int>(p.arity() - 2);
    1613         453 :   int const start_index = static_cast<int>(p.start_index());
    1614         453 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1615             :   Type* target_type = NodeProperties::GetType(target);
    1616         453 :   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
    1617             : 
    1618             :   // Check if {target} is a JSFunction.
    1619         453 :   if (target_type->Is(Type::Function())) {
    1620             :     // Patch {node} to an indirect call via ConstructFunctionForwardVarargs.
    1621         432 :     Callable callable = CodeFactory::ConstructFunctionForwardVarargs(isolate());
    1622         432 :     node->RemoveInput(arity + 1);
    1623             :     node->InsertInput(graph()->zone(), 0,
    1624         864 :                       jsgraph()->HeapConstant(callable.code()));
    1625         432 :     node->InsertInput(graph()->zone(), 2, new_target);
    1626         864 :     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
    1627         864 :     node->InsertInput(graph()->zone(), 4, jsgraph()->Constant(start_index));
    1628         864 :     node->InsertInput(graph()->zone(), 5, jsgraph()->UndefinedConstant());
    1629             :     NodeProperties::ChangeOp(
    1630             :         node, common()->Call(Linkage::GetStubCallDescriptor(
    1631             :                   isolate(), graph()->zone(), callable.descriptor(), arity + 1,
    1632        1296 :                   CallDescriptor::kNeedsFrameState)));
    1633             :     return Changed(node);
    1634             :   }
    1635             : 
    1636             :   return NoChange();
    1637             : }
    1638             : 
    1639       90129 : Reduction JSTypedLowering::ReduceJSConstruct(Node* node) {
    1640             :   DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
    1641       28064 :   ConstructParameters const& p = ConstructParametersOf(node->op());
    1642             :   DCHECK_LE(2u, p.arity());
    1643       28064 :   int const arity = static_cast<int>(p.arity() - 2);
    1644       28064 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1645             :   Type* target_type = NodeProperties::GetType(target);
    1646       28064 :   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
    1647       28064 :   Node* effect = NodeProperties::GetEffectInput(node);
    1648       28064 :   Node* control = NodeProperties::GetControlInput(node);
    1649             : 
    1650             :   // Check if {target} is a known JSFunction.
    1651       46260 :   if (target_type->IsHeapConstant() &&
    1652             :       target_type->AsHeapConstant()->Value()->IsJSFunction()) {
    1653             :     Handle<JSFunction> function =
    1654             :         Handle<JSFunction>::cast(target_type->AsHeapConstant()->Value());
    1655             :     Handle<SharedFunctionInfo> shared(function->shared(), isolate());
    1656             :     const int builtin_index = shared->construct_stub()->builtin_index();
    1657             :     const bool is_builtin = (builtin_index != -1);
    1658             : 
    1659             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    1660             : 
    1661       19422 :     if (is_builtin && Builtins::HasCppImplementation(builtin_index) &&
    1662             :         !NeedsArgumentAdaptorFrame(shared, arity)) {
    1663             :       // Patch {node} to a direct CEntryStub call.
    1664             : 
    1665             :       // Load the context from the {target}.
    1666             :       Node* context = effect = graph()->NewNode(
    1667             :           simplified()->LoadField(AccessBuilder::ForJSFunctionContext()),
    1668        7674 :           target, effect, control);
    1669        2558 :       NodeProperties::ReplaceContextInput(node, context);
    1670             : 
    1671             :       // Update the effect dependency for the {node}.
    1672        2558 :       NodeProperties::ReplaceEffectInput(node, effect);
    1673             : 
    1674        2558 :       ReduceBuiltin(isolate(), jsgraph(), node, builtin_index, arity, flags);
    1675             :     } else {
    1676             :       // Patch {node} to an indirect call via the {function}s construct stub.
    1677             :       Callable callable(handle(shared->construct_stub(), isolate()),
    1678       28612 :                         ConstructStubDescriptor(isolate()));
    1679       14306 :       node->RemoveInput(arity + 1);
    1680             :       node->InsertInput(graph()->zone(), 0,
    1681       28612 :                         jsgraph()->HeapConstant(callable.code()));
    1682       14306 :       node->InsertInput(graph()->zone(), 2, new_target);
    1683       28612 :       node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
    1684       28612 :       node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
    1685       28612 :       node->InsertInput(graph()->zone(), 5, jsgraph()->UndefinedConstant());
    1686             :       NodeProperties::ChangeOp(
    1687             :           node, common()->Call(Linkage::GetStubCallDescriptor(
    1688             :                     isolate(), graph()->zone(), callable.descriptor(),
    1689       42918 :                     1 + arity, flags)));
    1690             :     }
    1691             :     return Changed(node);
    1692             :   }
    1693             : 
    1694             :   // Check if {target} is a JSFunction.
    1695       11200 :   if (target_type->Is(Type::Function())) {
    1696             :     // Patch {node} to an indirect call via the ConstructFunction builtin.
    1697         761 :     Callable callable = CodeFactory::ConstructFunction(isolate());
    1698         761 :     node->RemoveInput(arity + 1);
    1699             :     node->InsertInput(graph()->zone(), 0,
    1700        1522 :                       jsgraph()->HeapConstant(callable.code()));
    1701         761 :     node->InsertInput(graph()->zone(), 2, new_target);
    1702        1522 :     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
    1703        1522 :     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
    1704             :     NodeProperties::ChangeOp(
    1705             :         node, common()->Call(Linkage::GetStubCallDescriptor(
    1706             :                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
    1707        2283 :                   CallDescriptor::kNeedsFrameState)));
    1708             :     return Changed(node);
    1709             :   }
    1710             : 
    1711             :   return NoChange();
    1712             : }
    1713             : 
    1714        1338 : Reduction JSTypedLowering::ReduceJSCallForwardVarargs(Node* node) {
    1715             :   DCHECK_EQ(IrOpcode::kJSCallForwardVarargs, node->opcode());
    1716         384 :   CallForwardVarargsParameters p = CallForwardVarargsParametersOf(node->op());
    1717             :   DCHECK_LE(2u, p.arity());
    1718         384 :   int const arity = static_cast<int>(p.arity() - 2);
    1719         384 :   int const start_index = static_cast<int>(p.start_index());
    1720         384 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1721             :   Type* target_type = NodeProperties::GetType(target);
    1722             : 
    1723             :   // Check if {target} is a JSFunction.
    1724         384 :   if (target_type->Is(Type::Function())) {
    1725             :     // Compute flags for the call.
    1726             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    1727             :     // Patch {node} to an indirect call via CallFunctionForwardVarargs.
    1728         318 :     Callable callable = CodeFactory::CallFunctionForwardVarargs(isolate());
    1729             :     node->InsertInput(graph()->zone(), 0,
    1730         636 :                       jsgraph()->HeapConstant(callable.code()));
    1731         636 :     node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(arity));
    1732         636 :     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(start_index));
    1733             :     NodeProperties::ChangeOp(
    1734             :         node, common()->Call(Linkage::GetStubCallDescriptor(
    1735             :                   isolate(), graph()->zone(), callable.descriptor(), arity + 1,
    1736        1272 :                   flags)));
    1737             :     return Changed(node);
    1738             :   }
    1739             : 
    1740             :   return NoChange();
    1741             : }
    1742             : 
    1743     1039195 : Reduction JSTypedLowering::ReduceJSCall(Node* node) {
    1744             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1745      733450 :   CallParameters const& p = CallParametersOf(node->op());
    1746      480809 :   int const arity = static_cast<int>(p.arity() - 2);
    1747             :   ConvertReceiverMode convert_mode = p.convert_mode();
    1748      480809 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1749             :   Type* target_type = NodeProperties::GetType(target);
    1750      480809 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1751             :   Type* receiver_type = NodeProperties::GetType(receiver);
    1752      480809 :   Node* effect = NodeProperties::GetEffectInput(node);
    1753      480811 :   Node* control = NodeProperties::GetControlInput(node);
    1754             : 
    1755             :   // Try to infer receiver {convert_mode} from {receiver} type.
    1756      480810 :   if (receiver_type->Is(Type::NullOrUndefined())) {
    1757             :     convert_mode = ConvertReceiverMode::kNullOrUndefined;
    1758      157166 :   } else if (!receiver_type->Maybe(Type::NullOrUndefined())) {
    1759             :     convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
    1760             :   }
    1761             : 
    1762             :   // Check if {target} is a known JSFunction.
    1763      674888 :   if (target_type->IsHeapConstant() &&
    1764             :       target_type->AsHeapConstant()->Value()->IsJSFunction()) {
    1765             :     Handle<JSFunction> function =
    1766             :         Handle<JSFunction>::cast(target_type->AsHeapConstant()->Value());
    1767             :     Handle<SharedFunctionInfo> shared(function->shared(), isolate());
    1768             :     const int builtin_index = shared->code()->builtin_index();
    1769             :     const bool is_builtin = (builtin_index != -1);
    1770             : 
    1771             :     // Class constructors are callable, but [[Call]] will raise an exception.
    1772             :     // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
    1773      194030 :     if (IsClassConstructor(shared->kind())) return NoChange();
    1774             : 
    1775             :     // Load the context from the {target}.
    1776             :     Node* context = effect = graph()->NewNode(
    1777             :         simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
    1778      582090 :         effect, control);
    1779      194030 :     NodeProperties::ReplaceContextInput(node, context);
    1780             : 
    1781             :     // Check if we need to convert the {receiver}.
    1782      353302 :     if (is_sloppy(shared->language_mode()) && !shared->native() &&
    1783             :         !receiver_type->Is(Type::Receiver())) {
    1784             :       receiver = effect =
    1785             :           graph()->NewNode(javascript()->ConvertReceiver(convert_mode),
    1786       79511 :                            receiver, context, effect, control);
    1787       79511 :       NodeProperties::ReplaceValueInput(node, receiver, 1);
    1788             :     }
    1789             : 
    1790             :     // Update the effect dependency for the {node}.
    1791      194030 :     NodeProperties::ReplaceEffectInput(node, effect);
    1792             : 
    1793             :     // Compute flags for the call.
    1794             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    1795      194030 :     Node* new_target = jsgraph()->UndefinedConstant();
    1796      194030 :     Node* argument_count = jsgraph()->Constant(arity);
    1797      194030 :     if (NeedsArgumentAdaptorFrame(shared, arity)) {
    1798             :       // Patch {node} to an indirect call via the ArgumentsAdaptorTrampoline.
    1799       48383 :       Callable callable = CodeFactory::ArgumentAdaptor(isolate());
    1800             :       node->InsertInput(graph()->zone(), 0,
    1801       96766 :                         jsgraph()->HeapConstant(callable.code()));
    1802       48383 :       node->InsertInput(graph()->zone(), 2, new_target);
    1803       48383 :       node->InsertInput(graph()->zone(), 3, argument_count);
    1804             :       node->InsertInput(
    1805             :           graph()->zone(), 4,
    1806       96766 :           jsgraph()->Constant(shared->internal_formal_parameter_count()));
    1807             :       NodeProperties::ChangeOp(
    1808             :           node, common()->Call(Linkage::GetStubCallDescriptor(
    1809             :                     isolate(), graph()->zone(), callable.descriptor(),
    1810      193532 :                     1 + arity, flags)));
    1811      145647 :     } else if (is_builtin && Builtins::HasCppImplementation(builtin_index)) {
    1812             :       // Patch {node} to a direct CEntryStub call.
    1813        5282 :       ReduceBuiltin(isolate(), jsgraph(), node, builtin_index, arity, flags);
    1814             :     } else {
    1815             :       // Patch {node} to a direct call.
    1816      280730 :       node->InsertInput(graph()->zone(), arity + 2, new_target);
    1817      280730 :       node->InsertInput(graph()->zone(), arity + 3, argument_count);
    1818             :       NodeProperties::ChangeOp(node,
    1819             :                                common()->Call(Linkage::GetJSCallDescriptor(
    1820      421095 :                                    graph()->zone(), false, 1 + arity, flags)));
    1821             :     }
    1822             :     return Changed(node);
    1823             :   }
    1824             : 
    1825             :   // Check if {target} is a JSFunction.
    1826      286780 :   if (target_type->Is(Type::Function())) {
    1827             :     // Compute flags for the call.
    1828             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    1829             :     // Patch {node} to an indirect call via the CallFunction builtin.
    1830       34139 :     Callable callable = CodeFactory::CallFunction(isolate(), convert_mode);
    1831             :     node->InsertInput(graph()->zone(), 0,
    1832       68280 :                       jsgraph()->HeapConstant(callable.code()));
    1833       68276 :     node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(arity));
    1834             :     NodeProperties::ChangeOp(
    1835             :         node, common()->Call(Linkage::GetStubCallDescriptor(
    1836             :                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
    1837      136559 :                   flags)));
    1838             :     return Changed(node);
    1839             :   }
    1840             : 
    1841             :   // Maybe we did at least learn something about the {receiver}.
    1842      252641 :   if (p.convert_mode() != convert_mode) {
    1843             :     NodeProperties::ChangeOp(
    1844         929 :         node, javascript()->Call(p.arity(), p.frequency(), p.feedback(),
    1845         929 :                                  convert_mode));
    1846             :     return Changed(node);
    1847             :   }
    1848             : 
    1849             :   return NoChange();
    1850             : }
    1851             : 
    1852        2186 : Reduction JSTypedLowering::ReduceJSForInNext(Node* node) {
    1853             :   DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode());
    1854        1691 :   ForInMode const mode = ForInModeOf(node->op());
    1855        1691 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1856        1691 :   Node* cache_array = NodeProperties::GetValueInput(node, 1);
    1857        1691 :   Node* cache_type = NodeProperties::GetValueInput(node, 2);
    1858        1691 :   Node* index = NodeProperties::GetValueInput(node, 3);
    1859        1691 :   Node* context = NodeProperties::GetContextInput(node);
    1860        1691 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    1861        1691 :   Node* effect = NodeProperties::GetEffectInput(node);
    1862        1691 :   Node* control = NodeProperties::GetControlInput(node);
    1863             : 
    1864             :   // Load the map of the {receiver}.
    1865             :   Node* receiver_map = effect =
    1866             :       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
    1867        5073 :                        receiver, effect, control);
    1868             : 
    1869        1691 :   switch (mode) {
    1870             :     case ForInMode::kUseEnumCacheKeys:
    1871             :     case ForInMode::kUseEnumCacheKeysAndIndices: {
    1872             :       // Ensure that the expected map still matches that of the {receiver}.
    1873             :       Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
    1874        1196 :                                      receiver_map, cache_type);
    1875             :       effect =
    1876             :           graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kNoReason),
    1877        1196 :                            check, effect, control);
    1878             : 
    1879             :       // Since the change to LoadElement() below is effectful, we connect
    1880             :       // node to all effect uses.
    1881        1745 :       ReplaceWithValue(node, node, node, control);
    1882             : 
    1883             :       // Morph the {node} into a LoadElement.
    1884        1196 :       node->ReplaceInput(0, cache_array);
    1885        1196 :       node->ReplaceInput(1, index);
    1886        1196 :       node->ReplaceInput(2, effect);
    1887        1196 :       node->ReplaceInput(3, control);
    1888        1196 :       node->TrimInputCount(4);
    1889             :       NodeProperties::ChangeOp(
    1890             :           node,
    1891        2392 :           simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()));
    1892             :       NodeProperties::SetType(node, Type::InternalizedString());
    1893             :       break;
    1894             :     }
    1895             :     case ForInMode::kGeneric: {
    1896             :       // Load the next {key} from the {cache_array}.
    1897             :       Node* key = effect = graph()->NewNode(
    1898             :           simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
    1899        1485 :           cache_array, index, effect, control);
    1900             : 
    1901             :       // Check if the expected map still matches that of the {receiver}.
    1902             :       Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
    1903         495 :                                      receiver_map, cache_type);
    1904             :       Node* branch =
    1905         495 :           graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    1906             : 
    1907         495 :       Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1908             :       Node* etrue;
    1909             :       Node* vtrue;
    1910             :       {
    1911             :         // Don't need filtering since expected map still matches that of the
    1912             :         // {receiver}.
    1913             :         etrue = effect;
    1914             :         vtrue = key;
    1915             :       }
    1916             : 
    1917         495 :       Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    1918             :       Node* efalse;
    1919             :       Node* vfalse;
    1920             :       {
    1921             :         // Filter the {key} to check if it's still a valid property of the
    1922             :         // {receiver} (does the ToName conversion implicitly).
    1923             :         Callable const callable =
    1924         495 :             Builtins::CallableFor(isolate(), Builtins::kForInFilter);
    1925             :         CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    1926             :             isolate(), graph()->zone(), callable.descriptor(), 0,
    1927        1485 :             CallDescriptor::kNeedsFrameState);
    1928             :         vfalse = efalse = if_false = graph()->NewNode(
    1929             :             common()->Call(desc), jsgraph()->HeapConstant(callable.code()), key,
    1930        1485 :             receiver, context, frame_state, effect, if_false);
    1931             : 
    1932             :         // Update potential {IfException} uses of {node} to point to the above
    1933             :         // ForInFilter stub call node instead.
    1934         495 :         Node* if_exception = nullptr;
    1935         495 :         if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
    1936          54 :           if_false = graph()->NewNode(common()->IfSuccess(), vfalse);
    1937          54 :           NodeProperties::ReplaceControlInput(if_exception, vfalse);
    1938          54 :           NodeProperties::ReplaceEffectInput(if_exception, efalse);
    1939          54 :           Revisit(if_exception);
    1940             :         }
    1941             :       }
    1942             : 
    1943         495 :       control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    1944         495 :       effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    1945             :       ReplaceWithValue(node, node, effect, control);
    1946             : 
    1947             :       // Morph the {node} into a Phi.
    1948         495 :       node->ReplaceInput(0, vtrue);
    1949         495 :       node->ReplaceInput(1, vfalse);
    1950         495 :       node->ReplaceInput(2, control);
    1951         495 :       node->TrimInputCount(3);
    1952             :       NodeProperties::ChangeOp(
    1953         495 :           node, common()->Phi(MachineRepresentation::kTagged, 2));
    1954             :     }
    1955             :   }
    1956             : 
    1957        1691 :   return Changed(node);
    1958             : }
    1959             : 
    1960        3014 : Reduction JSTypedLowering::ReduceJSForInPrepare(Node* node) {
    1961             :   DCHECK_EQ(IrOpcode::kJSForInPrepare, node->opcode());
    1962        1507 :   ForInMode const mode = ForInModeOf(node->op());
    1963        1507 :   Node* enumerator = NodeProperties::GetValueInput(node, 0);
    1964        1507 :   Node* effect = NodeProperties::GetEffectInput(node);
    1965        1507 :   Node* control = NodeProperties::GetControlInput(node);
    1966             :   Node* cache_type = enumerator;
    1967             :   Node* cache_array = nullptr;
    1968             :   Node* cache_length = nullptr;
    1969             : 
    1970        1507 :   switch (mode) {
    1971             :     case ForInMode::kUseEnumCacheKeys:
    1972             :     case ForInMode::kUseEnumCacheKeysAndIndices: {
    1973             :       // Check that the {enumerator} is a Map.
    1974             :       effect = graph()->NewNode(
    1975             :           simplified()->CheckMaps(CheckMapsFlag::kNone,
    1976             :                                   ZoneHandleSet<Map>(factory()->meta_map())),
    1977        2336 :           enumerator, effect, control);
    1978             : 
    1979             :       // Load the enum cache from the {enumerator} map.
    1980             :       Node* descriptor_array = effect = graph()->NewNode(
    1981             :           simplified()->LoadField(AccessBuilder::ForMapDescriptors()),
    1982        3504 :           enumerator, effect, control);
    1983             :       Node* enum_cache = effect = graph()->NewNode(
    1984             :           simplified()->LoadField(AccessBuilder::ForDescriptorArrayEnumCache()),
    1985        3504 :           descriptor_array, effect, control);
    1986             :       cache_array = effect = graph()->NewNode(
    1987             :           simplified()->LoadField(AccessBuilder::ForEnumCacheKeys()),
    1988        3504 :           enum_cache, effect, control);
    1989             : 
    1990             :       // Load the enum length of the {enumerator} map.
    1991             :       Node* bit_field3 = effect = graph()->NewNode(
    1992             :           simplified()->LoadField(AccessBuilder::ForMapBitField3()), enumerator,
    1993        3504 :           effect, control);
    1994             :       STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
    1995             :       cache_length =
    1996             :           graph()->NewNode(simplified()->NumberBitwiseAnd(), bit_field3,
    1997        2336 :                            jsgraph()->Constant(Map::EnumLengthBits::kMask));
    1998        1168 :       break;
    1999             :     }
    2000             :     case ForInMode::kGeneric: {
    2001             :       // Check if the {enumerator} is a Map or a FixedArray.
    2002             :       Node* check = effect = graph()->NewNode(
    2003             :           simplified()->CompareMaps(ZoneHandleSet<Map>(factory()->meta_map())),
    2004         678 :           enumerator, effect, control);
    2005             :       Node* branch =
    2006         339 :           graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    2007             : 
    2008         339 :       Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    2009             :       Node* etrue = effect;
    2010             :       Node* cache_array_true;
    2011             :       Node* cache_length_true;
    2012             :       {
    2013             :         // Load the enum cache from the {enumerator} map.
    2014             :         Node* descriptor_array = etrue = graph()->NewNode(
    2015             :             simplified()->LoadField(AccessBuilder::ForMapDescriptors()),
    2016        1017 :             enumerator, etrue, if_true);
    2017             :         Node* enum_cache = etrue =
    2018             :             graph()->NewNode(simplified()->LoadField(
    2019             :                                  AccessBuilder::ForDescriptorArrayEnumCache()),
    2020        1017 :                              descriptor_array, etrue, if_true);
    2021             :         cache_array_true = etrue = graph()->NewNode(
    2022             :             simplified()->LoadField(AccessBuilder::ForEnumCacheKeys()),
    2023        1017 :             enum_cache, etrue, if_true);
    2024             : 
    2025             :         // Load the enum length of the {enumerator} map.
    2026             :         Node* bit_field3 = etrue = graph()->NewNode(
    2027             :             simplified()->LoadField(AccessBuilder::ForMapBitField3()),
    2028        1017 :             enumerator, etrue, if_true);
    2029             :         STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
    2030             :         cache_length_true =
    2031             :             graph()->NewNode(simplified()->NumberBitwiseAnd(), bit_field3,
    2032         678 :                              jsgraph()->Constant(Map::EnumLengthBits::kMask));
    2033             :       }
    2034             : 
    2035         339 :       Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    2036             :       Node* efalse = effect;
    2037             :       Node* cache_array_false;
    2038             :       Node* cache_length_false;
    2039             :       {
    2040             :         // The {enumerator} is the FixedArray with the keys to iterate.
    2041             :         cache_array_false = enumerator;
    2042             :         cache_length_false = efalse = graph()->NewNode(
    2043             :             simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
    2044        1017 :             cache_array_false, efalse, if_false);
    2045             :       }
    2046             : 
    2047             :       // Rewrite the uses of the {node}.
    2048         339 :       control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    2049         339 :       effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    2050             :       cache_array =
    2051             :           graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2052         339 :                            cache_array_true, cache_array_false, control);
    2053             :       cache_length =
    2054             :           graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2055         339 :                            cache_length_true, cache_length_false, control);
    2056         339 :       break;
    2057             :     }
    2058             :   }
    2059             : 
    2060             :   // Update the uses of {node}.
    2061       25619 :   for (Edge edge : node->use_edges()) {
    2062        4521 :     Node* const user = edge.from();
    2063       12056 :     if (NodeProperties::IsEffectEdge(edge)) {
    2064        1507 :       edge.UpdateTo(effect);
    2065       12056 :       Revisit(user);
    2066       10549 :     } else if (NodeProperties::IsControlEdge(edge)) {
    2067        6028 :       edge.UpdateTo(control);
    2068             :       Revisit(user);
    2069             :     } else {
    2070             :       DCHECK(NodeProperties::IsValueEdge(edge));
    2071        4521 :       switch (ProjectionIndexOf(user->op())) {
    2072             :         case 0:
    2073             :           Replace(user, cache_type);
    2074             :           break;
    2075             :         case 1:
    2076             :           Replace(user, cache_array);
    2077             :           break;
    2078             :         case 2:
    2079             :           Replace(user, cache_length);
    2080             :           break;
    2081             :         default:
    2082           0 :           UNREACHABLE();
    2083             :       }
    2084             :     }
    2085             :   }
    2086        1507 :   node->Kill();
    2087        1507 :   return Replace(effect);
    2088             : }
    2089             : 
    2090       52586 : Reduction JSTypedLowering::ReduceJSLoadMessage(Node* node) {
    2091             :   DCHECK_EQ(IrOpcode::kJSLoadMessage, node->opcode());
    2092             :   ExternalReference const ref =
    2093       26293 :       ExternalReference::address_of_pending_message_obj(isolate());
    2094       26293 :   node->ReplaceInput(0, jsgraph()->ExternalConstant(ref));
    2095             :   NodeProperties::ChangeOp(
    2096       52586 :       node, simplified()->LoadField(AccessBuilder::ForExternalTaggedValue()));
    2097       26293 :   return Changed(node);
    2098             : }
    2099             : 
    2100       52586 : Reduction JSTypedLowering::ReduceJSStoreMessage(Node* node) {
    2101             :   DCHECK_EQ(IrOpcode::kJSStoreMessage, node->opcode());
    2102             :   ExternalReference const ref =
    2103       26293 :       ExternalReference::address_of_pending_message_obj(isolate());
    2104       26293 :   Node* value = NodeProperties::GetValueInput(node, 0);
    2105       26293 :   node->ReplaceInput(0, jsgraph()->ExternalConstant(ref));
    2106       26293 :   node->ReplaceInput(1, value);
    2107             :   NodeProperties::ChangeOp(
    2108       52586 :       node, simplified()->StoreField(AccessBuilder::ForExternalTaggedValue()));
    2109       26293 :   return Changed(node);
    2110             : }
    2111             : 
    2112        4946 : Reduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
    2113             :   DCHECK_EQ(IrOpcode::kJSGeneratorStore, node->opcode());
    2114        4946 :   Node* generator = NodeProperties::GetValueInput(node, 0);
    2115        4946 :   Node* continuation = NodeProperties::GetValueInput(node, 1);
    2116        4946 :   Node* offset = NodeProperties::GetValueInput(node, 2);
    2117        4946 :   Node* context = NodeProperties::GetContextInput(node);
    2118        4946 :   Node* effect = NodeProperties::GetEffectInput(node);
    2119        4946 :   Node* control = NodeProperties::GetControlInput(node);
    2120        4946 :   int register_count = OpParameter<int>(node);
    2121             : 
    2122        4946 :   FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectRegisterFile();
    2123        4946 :   FieldAccess context_field = AccessBuilder::ForJSGeneratorObjectContext();
    2124             :   FieldAccess continuation_field =
    2125        4946 :       AccessBuilder::ForJSGeneratorObjectContinuation();
    2126             :   FieldAccess input_or_debug_pos_field =
    2127        4946 :       AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
    2128             : 
    2129             :   Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
    2130        4946 :                                           generator, effect, control);
    2131             : 
    2132       40163 :   for (int i = 0; i < register_count; ++i) {
    2133       35217 :     Node* value = NodeProperties::GetValueInput(node, 3 + i);
    2134             :     effect = graph()->NewNode(
    2135       35217 :         simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), array,
    2136      105651 :         value, effect, control);
    2137             :   }
    2138             : 
    2139             :   effect = graph()->NewNode(simplified()->StoreField(context_field), generator,
    2140        4946 :                             context, effect, control);
    2141             :   effect = graph()->NewNode(simplified()->StoreField(continuation_field),
    2142        4946 :                             generator, continuation, effect, control);
    2143             :   effect = graph()->NewNode(simplified()->StoreField(input_or_debug_pos_field),
    2144        4946 :                             generator, offset, effect, control);
    2145             : 
    2146        4946 :   ReplaceWithValue(node, effect, effect, control);
    2147        4946 :   return Changed(effect);
    2148             : }
    2149             : 
    2150        3046 : Reduction JSTypedLowering::ReduceJSGeneratorRestoreContinuation(Node* node) {
    2151             :   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreContinuation, node->opcode());
    2152        1523 :   Node* generator = NodeProperties::GetValueInput(node, 0);
    2153        1523 :   Node* effect = NodeProperties::GetEffectInput(node);
    2154        1523 :   Node* control = NodeProperties::GetControlInput(node);
    2155             : 
    2156             :   FieldAccess continuation_field =
    2157        1523 :       AccessBuilder::ForJSGeneratorObjectContinuation();
    2158             : 
    2159             :   Node* continuation = effect = graph()->NewNode(
    2160        1523 :       simplified()->LoadField(continuation_field), generator, effect, control);
    2161        1523 :   Node* executing = jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting);
    2162             :   effect = graph()->NewNode(simplified()->StoreField(continuation_field),
    2163        1523 :                             generator, executing, effect, control);
    2164             : 
    2165        1523 :   ReplaceWithValue(node, continuation, effect, control);
    2166        1523 :   return Changed(continuation);
    2167             : }
    2168             : 
    2169       71530 : Reduction JSTypedLowering::ReduceJSGeneratorRestoreRegister(Node* node) {
    2170             :   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreRegister, node->opcode());
    2171       35765 :   Node* generator = NodeProperties::GetValueInput(node, 0);
    2172       35765 :   Node* effect = NodeProperties::GetEffectInput(node);
    2173       35765 :   Node* control = NodeProperties::GetControlInput(node);
    2174       35765 :   int index = OpParameter<int>(node);
    2175             : 
    2176       35765 :   FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectRegisterFile();
    2177       35765 :   FieldAccess element_field = AccessBuilder::ForFixedArraySlot(index);
    2178             : 
    2179             :   Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
    2180       35765 :                                           generator, effect, control);
    2181             :   Node* element = effect = graph()->NewNode(
    2182       35765 :       simplified()->LoadField(element_field), array, effect, control);
    2183       35765 :   Node* stale = jsgraph()->StaleRegisterConstant();
    2184             :   effect = graph()->NewNode(simplified()->StoreField(element_field), array,
    2185       35765 :                             stale, effect, control);
    2186             : 
    2187       35765 :   ReplaceWithValue(node, element, effect, control);
    2188       35765 :   return Changed(element);
    2189             : }
    2190             : 
    2191    30003479 : Reduction JSTypedLowering::Reduce(Node* node) {
    2192    30003479 :   switch (node->opcode()) {
    2193             :     case IrOpcode::kJSEqual:
    2194       13709 :       return ReduceJSEqual(node);
    2195             :     case IrOpcode::kJSStrictEqual:
    2196      153372 :       return ReduceJSStrictEqual(node);
    2197             :     case IrOpcode::kJSLessThan:         // fall through
    2198             :     case IrOpcode::kJSGreaterThan:      // fall through
    2199             :     case IrOpcode::kJSLessThanOrEqual:  // fall through
    2200             :     case IrOpcode::kJSGreaterThanOrEqual:
    2201       37351 :       return ReduceJSComparison(node);
    2202             :     case IrOpcode::kJSBitwiseOr:
    2203             :     case IrOpcode::kJSBitwiseXor:
    2204             :     case IrOpcode::kJSBitwiseAnd:
    2205       23797 :       return ReduceInt32Binop(node);
    2206             :     case IrOpcode::kJSShiftLeft:
    2207             :     case IrOpcode::kJSShiftRight:
    2208        8257 :       return ReduceUI32Shift(node, kSigned);
    2209             :     case IrOpcode::kJSShiftRightLogical:
    2210        4119 :       return ReduceUI32Shift(node, kUnsigned);
    2211             :     case IrOpcode::kJSAdd:
    2212       90137 :       return ReduceJSAdd(node);
    2213             :     case IrOpcode::kJSSubtract:
    2214             :     case IrOpcode::kJSMultiply:
    2215             :     case IrOpcode::kJSDivide:
    2216             :     case IrOpcode::kJSModulus:
    2217       56427 :       return ReduceNumberBinop(node);
    2218             :     case IrOpcode::kJSHasInPrototypeChain:
    2219        1288 :       return ReduceJSHasInPrototypeChain(node);
    2220             :     case IrOpcode::kJSOrdinaryHasInstance:
    2221          75 :       return ReduceJSOrdinaryHasInstance(node);
    2222             :     case IrOpcode::kJSToInteger:
    2223         175 :       return ReduceJSToInteger(node);
    2224             :     case IrOpcode::kJSToLength:
    2225         867 :       return ReduceJSToLength(node);
    2226             :     case IrOpcode::kJSToName:
    2227        1086 :       return ReduceJSToName(node);
    2228             :     case IrOpcode::kJSToNumber:
    2229       11549 :       return ReduceJSToNumber(node);
    2230             :     case IrOpcode::kJSToString:
    2231        2866 :       return ReduceJSToString(node);
    2232             :     case IrOpcode::kJSToObject:
    2233        3096 :       return ReduceJSToObject(node);
    2234             :     case IrOpcode::kJSLoadNamed:
    2235      465663 :       return ReduceJSLoadNamed(node);
    2236             :     case IrOpcode::kJSLoadContext:
    2237      687400 :       return ReduceJSLoadContext(node);
    2238             :     case IrOpcode::kJSStoreContext:
    2239      345503 :       return ReduceJSStoreContext(node);
    2240             :     case IrOpcode::kJSLoadModule:
    2241         280 :       return ReduceJSLoadModule(node);
    2242             :     case IrOpcode::kJSStoreModule:
    2243        6883 :       return ReduceJSStoreModule(node);
    2244             :     case IrOpcode::kJSConvertReceiver:
    2245      128052 :       return ReduceJSConvertReceiver(node);
    2246             :     case IrOpcode::kJSConstructForwardVarargs:
    2247         453 :       return ReduceJSConstructForwardVarargs(node);
    2248             :     case IrOpcode::kJSConstruct:
    2249       28064 :       return ReduceJSConstruct(node);
    2250             :     case IrOpcode::kJSCallForwardVarargs:
    2251         384 :       return ReduceJSCallForwardVarargs(node);
    2252             :     case IrOpcode::kJSCall:
    2253      480810 :       return ReduceJSCall(node);
    2254             :     case IrOpcode::kJSForInPrepare:
    2255        1507 :       return ReduceJSForInPrepare(node);
    2256             :     case IrOpcode::kJSForInNext:
    2257        1691 :       return ReduceJSForInNext(node);
    2258             :     case IrOpcode::kJSLoadMessage:
    2259       26293 :       return ReduceJSLoadMessage(node);
    2260             :     case IrOpcode::kJSStoreMessage:
    2261       26293 :       return ReduceJSStoreMessage(node);
    2262             :     case IrOpcode::kJSGeneratorStore:
    2263        4946 :       return ReduceJSGeneratorStore(node);
    2264             :     case IrOpcode::kJSGeneratorRestoreContinuation:
    2265        1523 :       return ReduceJSGeneratorRestoreContinuation(node);
    2266             :     case IrOpcode::kJSGeneratorRestoreRegister:
    2267       35765 :       return ReduceJSGeneratorRestoreRegister(node);
    2268             :     // TODO(mstarzinger): Simplified operations hiding in JS-level reducer not
    2269             :     // fooling anyone. Consider moving this into a separate reducer.
    2270             :     case IrOpcode::kSpeculativeNumberAdd:
    2271       52554 :       return ReduceSpeculativeNumberAdd(node);
    2272             :     case IrOpcode::kSpeculativeNumberSubtract:
    2273             :     case IrOpcode::kSpeculativeNumberMultiply:
    2274             :     case IrOpcode::kSpeculativeNumberDivide:
    2275             :     case IrOpcode::kSpeculativeNumberModulus:
    2276       42274 :       return ReduceSpeculativeNumberBinop(node);
    2277             :     case IrOpcode::kSpeculativeNumberEqual:
    2278             :     case IrOpcode::kSpeculativeNumberLessThan:
    2279             :     case IrOpcode::kSpeculativeNumberLessThanOrEqual:
    2280       67587 :       return ReduceSpeculativeNumberComparison(node);
    2281             :     default:
    2282             :       break;
    2283             :   }
    2284             :   return NoChange();
    2285             : }
    2286             : 
    2287             : 
    2288      473209 : Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
    2289             : 
    2290             : 
    2291     3917885 : Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); }
    2292             : 
    2293             : 
    2294      634354 : Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); }
    2295             : 
    2296             : 
    2297      240209 : JSOperatorBuilder* JSTypedLowering::javascript() const {
    2298      240209 :   return jsgraph()->javascript();
    2299             : }
    2300             : 
    2301             : 
    2302      341205 : CommonOperatorBuilder* JSTypedLowering::common() const {
    2303      341205 :   return jsgraph()->common();
    2304             : }
    2305             : 
    2306     1814812 : SimplifiedOperatorBuilder* JSTypedLowering::simplified() const {
    2307     1816319 :   return jsgraph()->simplified();
    2308             : }
    2309             : 
    2310             : }  // namespace compiler
    2311             : }  // namespace internal
    2312             : }  // namespace v8

Generated by: LCOV version 1.10