LCOV - code coverage report
Current view: top level - src/compiler - js-typed-lowering.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1081 1101 98.2 %
Date: 2019-04-17 Functions: 79 85 92.9 %

          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             : #include "src/objects/js-generator.h"
      21             : #include "src/objects/module-inl.h"
      22             : 
      23             : namespace v8 {
      24             : namespace internal {
      25             : namespace compiler {
      26             : 
      27             : // A helper class to simplify the process of reducing a single binop node with a
      28             : // JSOperator. This class manages the rewriting of context, control, and effect
      29             : // dependencies during lowering of a binop and contains numerous helper
      30             : // functions for matching the types of inputs to an operation.
      31             : class JSBinopReduction final {
      32             :  public:
      33             :   JSBinopReduction(JSTypedLowering* lowering, Node* node)
      34      345004 :       : lowering_(lowering), node_(node) {}
      35             : 
      36      116448 :   bool GetCompareNumberOperationHint(NumberOperationHint* hint) {
      37             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      38      116448 :     switch (CompareOperationHintOf(node_->op())) {
      39             :       case CompareOperationHint::kSignedSmall:
      40        6706 :         *hint = NumberOperationHint::kSignedSmall;
      41             :         return true;
      42             :       case CompareOperationHint::kNumber:
      43        8331 :         *hint = NumberOperationHint::kNumber;
      44             :         return true;
      45             :       case CompareOperationHint::kNumberOrOddball:
      46           0 :         *hint = NumberOperationHint::kNumberOrOddball;
      47             :         return true;
      48             :       case CompareOperationHint::kAny:
      49             :       case CompareOperationHint::kNone:
      50             :       case CompareOperationHint::kString:
      51             :       case CompareOperationHint::kSymbol:
      52             :       case CompareOperationHint::kBigInt:
      53             :       case CompareOperationHint::kReceiver:
      54             :       case CompareOperationHint::kReceiverOrNullOrUndefined:
      55             :       case CompareOperationHint::kInternalizedString:
      56             :         break;
      57             :     }
      58             :     return false;
      59             :   }
      60             : 
      61      140777 :   bool IsInternalizedStringCompareOperation() {
      62             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      63      140777 :     return (CompareOperationHintOf(node_->op()) ==
      64      144577 :             CompareOperationHint::kInternalizedString) &&
      65      144577 :            BothInputsMaybe(Type::InternalizedString());
      66             :   }
      67             : 
      68      103141 :   bool IsReceiverCompareOperation() {
      69             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      70      103141 :     return (CompareOperationHintOf(node_->op()) ==
      71      103929 :             CompareOperationHint::kReceiver) &&
      72      103929 :            BothInputsMaybe(Type::Receiver());
      73             :   }
      74             : 
      75      102353 :   bool IsReceiverOrNullOrUndefinedCompareOperation() {
      76             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      77      102353 :     return (CompareOperationHintOf(node_->op()) ==
      78      102404 :             CompareOperationHint::kReceiverOrNullOrUndefined) &&
      79      102404 :            BothInputsMaybe(Type::ReceiverOrNullOrUndefined());
      80             :   }
      81             : 
      82      127925 :   bool IsStringCompareOperation() {
      83             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      84      127925 :     return (CompareOperationHintOf(node_->op()) ==
      85      135071 :             CompareOperationHint::kString) &&
      86      135071 :            BothInputsMaybe(Type::String());
      87             :   }
      88             : 
      89       95397 :   bool IsSymbolCompareOperation() {
      90             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
      91       95397 :     return (CompareOperationHintOf(node_->op()) ==
      92       95421 :             CompareOperationHint::kSymbol) &&
      93       95421 :            BothInputsMaybe(Type::Symbol());
      94             :   }
      95             : 
      96             :   // Inserts a CheckReceiver for the left input.
      97         788 :   void CheckLeftInputToReceiver() {
      98         788 :     Node* left_input = graph()->NewNode(simplified()->CheckReceiver(), left(),
      99             :                                         effect(), control());
     100         788 :     node_->ReplaceInput(0, left_input);
     101             :     update_effect(left_input);
     102         788 :   }
     103             : 
     104             :   // Inserts a CheckReceiverOrNullOrUndefined for the left input.
     105          46 :   void CheckLeftInputToReceiverOrNullOrUndefined() {
     106             :     Node* left_input =
     107          46 :         graph()->NewNode(simplified()->CheckReceiverOrNullOrUndefined(), left(),
     108             :                          effect(), control());
     109          46 :     node_->ReplaceInput(0, left_input);
     110             :     update_effect(left_input);
     111          46 :   }
     112             : 
     113             :   // Checks that both inputs are Receiver, and if we don't know
     114             :   // statically that one side is already a Receiver, insert a
     115             :   // CheckReceiver node.
     116          96 :   void CheckInputsToReceiver() {
     117         192 :     if (!left_type().Is(Type::Receiver())) {
     118          96 :       CheckLeftInputToReceiver();
     119             :     }
     120         192 :     if (!right_type().Is(Type::Receiver())) {
     121          85 :       Node* right_input = graph()->NewNode(simplified()->CheckReceiver(),
     122             :                                            right(), effect(), control());
     123          85 :       node_->ReplaceInput(1, right_input);
     124             :       update_effect(right_input);
     125             :     }
     126          96 :   }
     127             : 
     128             :   // Checks that both inputs are Receiver, Null or Undefined and if
     129             :   // we don't know statically that one side is already a Receiver,
     130             :   // Null or Undefined, insert CheckReceiverOrNullOrUndefined nodes.
     131          38 :   void CheckInputsToReceiverOrNullOrUndefined() {
     132          76 :     if (!left_type().Is(Type::ReceiverOrNullOrUndefined())) {
     133          34 :       CheckLeftInputToReceiverOrNullOrUndefined();
     134             :     }
     135          76 :     if (!right_type().Is(Type::ReceiverOrNullOrUndefined())) {
     136             :       Node* right_input =
     137          26 :           graph()->NewNode(simplified()->CheckReceiverOrNullOrUndefined(),
     138             :                            right(), effect(), control());
     139          26 :       node_->ReplaceInput(1, right_input);
     140             :       update_effect(right_input);
     141             :     }
     142          38 :   }
     143             : 
     144             :   // Inserts a CheckSymbol for the left input.
     145          24 :   void CheckLeftInputToSymbol() {
     146          24 :     Node* left_input = graph()->NewNode(simplified()->CheckSymbol(), left(),
     147             :                                         effect(), control());
     148          24 :     node_->ReplaceInput(0, left_input);
     149             :     update_effect(left_input);
     150          24 :   }
     151             : 
     152             :   // Checks that both inputs are Symbol, and if we don't know
     153             :   // statically that one side is already a Symbol, insert a
     154             :   // CheckSymbol node.
     155          16 :   void CheckInputsToSymbol() {
     156          32 :     if (!left_type().Is(Type::Symbol())) {
     157          16 :       CheckLeftInputToSymbol();
     158             :     }
     159          32 :     if (!right_type().Is(Type::Symbol())) {
     160           8 :       Node* right_input = graph()->NewNode(simplified()->CheckSymbol(), right(),
     161             :                                            effect(), control());
     162           8 :       node_->ReplaceInput(1, right_input);
     163             :       update_effect(right_input);
     164             :     }
     165          16 :   }
     166             : 
     167             :   // Checks that both inputs are NonEmptyOneByteString, and if we don't know
     168             :   // statically that one side is already a NonEmptyOneByteString, insert a
     169             :   // CheckNonEmptyOneByteString node.
     170        1814 :   void CheckInputsToNonEmptyOneByteString() {
     171        3628 :     if (!left_type().Is(Type::NonEmptyOneByteString())) {
     172             :       Node* left_input =
     173         998 :           graph()->NewNode(simplified()->CheckNonEmptyOneByteString(), left(),
     174             :                            effect(), control());
     175         998 :       node_->ReplaceInput(0, left_input);
     176             :       update_effect(left_input);
     177             :     }
     178        3628 :     if (!right_type().Is(Type::NonEmptyOneByteString())) {
     179             :       Node* right_input =
     180         522 :           graph()->NewNode(simplified()->CheckNonEmptyOneByteString(), right(),
     181             :                            effect(), control());
     182         522 :       node_->ReplaceInput(1, right_input);
     183             :       update_effect(right_input);
     184             :     }
     185        1814 :   }
     186             : 
     187             :   // Checks that both inputs are NonEmptyTwoByteString, and if we don't know
     188             :   // statically that one side is already a NonEmptyTwoByteString, insert a
     189             :   // CheckNonEmptyTwoByteString node.
     190         136 :   void CheckInputsToNonEmptyTwoByteString() {
     191         272 :     if (!left_type().Is(Type::NonEmptyTwoByteString())) {
     192             :       Node* left_input =
     193          98 :           graph()->NewNode(simplified()->CheckNonEmptyTwoByteString(), left(),
     194             :                            effect(), control());
     195          98 :       node_->ReplaceInput(0, left_input);
     196             :       update_effect(left_input);
     197             :     }
     198         272 :     if (!right_type().Is(Type::NonEmptyTwoByteString())) {
     199             :       Node* right_input =
     200         128 :           graph()->NewNode(simplified()->CheckNonEmptyTwoByteString(), right(),
     201             :                            effect(), control());
     202         128 :       node_->ReplaceInput(1, right_input);
     203             :       update_effect(right_input);
     204             :     }
     205         136 :   }
     206             : 
     207             :   // Checks that both inputs are NonEmptyString, and if we don't know
     208             :   // statically that one side is already a NonEmptyString, insert a
     209             :   // CheckNonEmptyString node.
     210          18 :   void CheckInputsToNonEmptyString() {
     211          36 :     if (!left_type().Is(Type::NonEmptyString())) {
     212          18 :       Node* left_input = graph()->NewNode(simplified()->CheckNonEmptyString(),
     213             :                                           left(), effect(), control());
     214          18 :       node_->ReplaceInput(0, left_input);
     215             :       update_effect(left_input);
     216             :     }
     217          36 :     if (!right_type().Is(Type::NonEmptyString())) {
     218           0 :       Node* right_input = graph()->NewNode(simplified()->CheckNonEmptyString(),
     219             :                                            right(), effect(), control());
     220           0 :       node_->ReplaceInput(1, right_input);
     221             :       update_effect(right_input);
     222             :     }
     223          18 :   }
     224             : 
     225             :   // Checks that both inputs are String, and if we don't know
     226             :   // statically that one side is already a String, insert a
     227             :   // CheckString node.
     228       10810 :   void CheckInputsToString() {
     229       21620 :     if (!left_type().Is(Type::String())) {
     230             :       Node* left_input =
     231       15382 :           graph()->NewNode(simplified()->CheckString(VectorSlotPair()), left(),
     232             :                            effect(), control());
     233        7691 :       node_->ReplaceInput(0, left_input);
     234             :       update_effect(left_input);
     235             :     }
     236       21620 :     if (!right_type().Is(Type::String())) {
     237             :       Node* right_input =
     238        4108 :           graph()->NewNode(simplified()->CheckString(VectorSlotPair()), right(),
     239             :                            effect(), control());
     240        2054 :       node_->ReplaceInput(1, right_input);
     241             :       update_effect(right_input);
     242             :     }
     243       10810 :   }
     244             : 
     245             :   // Checks that both inputs are InternalizedString, and if we don't know
     246             :   // statically that one side is already an InternalizedString, insert a
     247             :   // CheckInternalizedString node.
     248        3520 :   void CheckInputsToInternalizedString() {
     249        7040 :     if (!left_type().Is(Type::UniqueName())) {
     250        3520 :       Node* left_input = graph()->NewNode(
     251             :           simplified()->CheckInternalizedString(), left(), effect(), control());
     252        3520 :       node_->ReplaceInput(0, left_input);
     253             :       update_effect(left_input);
     254             :     }
     255        7040 :     if (!right_type().Is(Type::UniqueName())) {
     256             :       Node* right_input =
     257          50 :           graph()->NewNode(simplified()->CheckInternalizedString(), right(),
     258             :                            effect(), control());
     259          50 :       node_->ReplaceInput(1, right_input);
     260             :       update_effect(right_input);
     261             :     }
     262        3520 :   }
     263             : 
     264       33835 :   void ConvertInputsToNumber() {
     265             :     DCHECK(left_type().Is(Type::PlainPrimitive()));
     266             :     DCHECK(right_type().Is(Type::PlainPrimitive()));
     267       33835 :     node_->ReplaceInput(0, ConvertPlainPrimitiveToNumber(left()));
     268       33835 :     node_->ReplaceInput(1, ConvertPlainPrimitiveToNumber(right()));
     269       33835 :   }
     270             : 
     271        9827 :   void ConvertInputsToUI32(Signedness left_signedness,
     272             :                            Signedness right_signedness) {
     273        9827 :     node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
     274        9827 :     node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness));
     275        9827 :   }
     276             : 
     277        3215 :   void SwapInputs() {
     278             :     Node* l = left();
     279             :     Node* r = right();
     280        3215 :     node_->ReplaceInput(0, r);
     281        3215 :     node_->ReplaceInput(1, l);
     282        3215 :   }
     283             : 
     284             :   // Remove all effect and control inputs and outputs to this node and change
     285             :   // to the pure operator {op}.
     286       90459 :   Reduction ChangeToPureOperator(const Operator* op, Type type = Type::Any()) {
     287             :     DCHECK_EQ(0, op->EffectInputCount());
     288             :     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
     289             :     DCHECK_EQ(0, op->ControlInputCount());
     290             :     DCHECK_EQ(2, op->ValueInputCount());
     291             : 
     292             :     // Remove the effects from the node, and update its effect/control usages.
     293      180918 :     if (node_->op()->EffectInputCount() > 0) {
     294       90459 :       lowering_->RelaxEffectsAndControls(node_);
     295             :     }
     296             :     // Remove the inputs corresponding to context, effect, and control.
     297       90459 :     NodeProperties::RemoveNonValueInputs(node_);
     298             :     // Finally, update the operator to the new one.
     299       90459 :     NodeProperties::ChangeOp(node_, op);
     300             : 
     301             :     // TODO(jarin): Replace the explicit typing hack with a call to some method
     302             :     // that encapsulates changing the operator and re-typing.
     303       90459 :     Type node_type = NodeProperties::GetType(node_);
     304       90459 :     NodeProperties::SetType(node_, Type::Intersect(node_type, type, zone()));
     305             : 
     306       90459 :     return lowering_->Changed(node_);
     307             :   }
     308             : 
     309       15037 :   Reduction ChangeToSpeculativeOperator(const Operator* op, Type upper_bound) {
     310             :     DCHECK_EQ(1, op->EffectInputCount());
     311             :     DCHECK_EQ(1, op->EffectOutputCount());
     312             :     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
     313             :     DCHECK_EQ(1, op->ControlInputCount());
     314             :     DCHECK_EQ(0, op->ControlOutputCount());
     315             :     DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
     316             :     DCHECK_EQ(2, op->ValueInputCount());
     317             : 
     318             :     DCHECK_EQ(1, node_->op()->EffectInputCount());
     319             :     DCHECK_EQ(1, node_->op()->EffectOutputCount());
     320             :     DCHECK_EQ(1, node_->op()->ControlInputCount());
     321             :     DCHECK_EQ(2, node_->op()->ValueInputCount());
     322             : 
     323             :     // Reconnect the control output to bypass the IfSuccess node and
     324             :     // possibly disconnect from the IfException node.
     325       15037 :     lowering_->RelaxControls(node_);
     326             : 
     327             :     // Remove the frame state and the context.
     328       15037 :     if (OperatorProperties::HasFrameStateInput(node_->op())) {
     329           0 :       node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
     330             :     }
     331       30074 :     node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
     332             : 
     333       15037 :     NodeProperties::ChangeOp(node_, op);
     334             : 
     335             :     // Update the type to number.
     336       15037 :     Type node_type = NodeProperties::GetType(node_);
     337       15037 :     NodeProperties::SetType(node_,
     338             :                             Type::Intersect(node_type, upper_bound, zone()));
     339             : 
     340       15037 :     return lowering_->Changed(node_);
     341             :   }
     342             : 
     343       27094 :   const Operator* NumberOp() {
     344       27094 :     switch (node_->opcode()) {
     345             :       case IrOpcode::kJSAdd:
     346       11661 :         return simplified()->NumberAdd();
     347             :       case IrOpcode::kJSSubtract:
     348        1761 :         return simplified()->NumberSubtract();
     349             :       case IrOpcode::kJSMultiply:
     350        1486 :         return simplified()->NumberMultiply();
     351             :       case IrOpcode::kJSDivide:
     352        1504 :         return simplified()->NumberDivide();
     353             :       case IrOpcode::kJSModulus:
     354         822 :         return simplified()->NumberModulus();
     355             :       case IrOpcode::kJSExponentiate:
     356          33 :         return simplified()->NumberPow();
     357             :       case IrOpcode::kJSBitwiseAnd:
     358        1421 :         return simplified()->NumberBitwiseAnd();
     359             :       case IrOpcode::kJSBitwiseOr:
     360        1638 :         return simplified()->NumberBitwiseOr();
     361             :       case IrOpcode::kJSBitwiseXor:
     362        1433 :         return simplified()->NumberBitwiseXor();
     363             :       case IrOpcode::kJSShiftLeft:
     364        1821 :         return simplified()->NumberShiftLeft();
     365             :       case IrOpcode::kJSShiftRight:
     366        1750 :         return simplified()->NumberShiftRight();
     367             :       case IrOpcode::kJSShiftRightLogical:
     368        1764 :         return simplified()->NumberShiftRightLogical();
     369             :       default:
     370             :         break;
     371             :     }
     372           0 :     UNREACHABLE();
     373             :   }
     374             : 
     375     4506624 :   bool LeftInputIs(Type t) { return left_type().Is(t); }
     376             : 
     377     1457034 :   bool RightInputIs(Type t) { return right_type().Is(t); }
     378             : 
     379      192487 :   bool OneInputIs(Type t) { return LeftInputIs(t) || RightInputIs(t); }
     380             : 
     381     1178760 :   bool BothInputsAre(Type t) { return LeftInputIs(t) && RightInputIs(t); }
     382             : 
     383       11809 :   bool BothInputsMaybe(Type t) {
     384       23618 :     return left_type().Maybe(t) && right_type().Maybe(t);
     385             :   }
     386             : 
     387      172575 :   bool OneInputCannotBe(Type t) {
     388      326860 :     return !left_type().Maybe(t) || !right_type().Maybe(t);
     389             :   }
     390             : 
     391       48782 :   bool NeitherInputCanBe(Type t) {
     392       69195 :     return !left_type().Maybe(t) && !right_type().Maybe(t);
     393             :   }
     394             : 
     395       16078 :   Node* effect() { return NodeProperties::GetEffectInput(node_); }
     396       16078 :   Node* control() { return NodeProperties::GetControlInput(node_); }
     397             :   Node* context() { return NodeProperties::GetContextInput(node_); }
     398      265788 :   Node* left() { return NodeProperties::GetValueInput(node_, 0); }
     399      286588 :   Node* right() { return NodeProperties::GetValueInput(node_, 1); }
     400             :   Type left_type() { return NodeProperties::GetType(node_->InputAt(0)); }
     401             :   Type right_type() { return NodeProperties::GetType(node_->InputAt(1)); }
     402             :   Type type() { return NodeProperties::GetType(node_); }
     403             : 
     404             :   SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
     405             :   Graph* graph() const { return lowering_->graph(); }
     406             :   JSGraph* jsgraph() { return lowering_->jsgraph(); }
     407             :   Isolate* isolate() { return jsgraph()->isolate(); }
     408             :   JSOperatorBuilder* javascript() { return lowering_->javascript(); }
     409             :   CommonOperatorBuilder* common() { return jsgraph()->common(); }
     410             :   Zone* zone() const { return graph()->zone(); }
     411             : 
     412             :  private:
     413             :   JSTypedLowering* lowering_;  // The containing lowering instance.
     414             :   Node* node_;                 // The original node.
     415             : 
     416       67670 :   Node* ConvertPlainPrimitiveToNumber(Node* node) {
     417             :     DCHECK(NodeProperties::GetType(node).Is(Type::PlainPrimitive()));
     418             :     // Avoid inserting too many eager ToNumber() operations.
     419       67670 :     Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
     420       67670 :     if (reduction.Changed()) return reduction.replacement();
     421        3680 :     if (NodeProperties::GetType(node).Is(Type::Number())) {
     422             :       return node;
     423             :     }
     424        3680 :     return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
     425             :   }
     426             : 
     427       19654 :   Node* ConvertToUI32(Node* node, Signedness signedness) {
     428             :     // Avoid introducing too many eager NumberToXXnt32() operations.
     429       19654 :     Type type = NodeProperties::GetType(node);
     430       19654 :     if (signedness == kSigned) {
     431       12555 :       if (!type.Is(Type::Signed32())) {
     432        6535 :         node = graph()->NewNode(simplified()->NumberToInt32(), node);
     433             :       }
     434             :     } else {
     435             :       DCHECK_EQ(kUnsigned, signedness);
     436        7099 :       if (!type.Is(Type::Unsigned32())) {
     437        3829 :         node = graph()->NewNode(simplified()->NumberToUint32(), node);
     438             :       }
     439             :     }
     440       19654 :     return node;
     441             :   }
     442             : 
     443             :   void update_effect(Node* effect) {
     444       16056 :     NodeProperties::ReplaceEffectInput(node_, effect);
     445             :   }
     446             : };
     447             : 
     448             : 
     449             : // TODO(turbofan): js-typed-lowering improvements possible
     450             : // - immediately put in type bounds for all new nodes
     451             : // - relax effects from generic but not-side-effecting operations
     452             : 
     453      480406 : JSTypedLowering::JSTypedLowering(Editor* editor, JSGraph* jsgraph,
     454             :                                  JSHeapBroker* broker, Zone* zone)
     455             :     : AdvancedReducer(editor),
     456             :       jsgraph_(jsgraph),
     457             :       broker_(broker),
     458             :       pointer_comparable_type_(
     459             :           Type::Union(Type::Oddball(),
     460             :                       Type::Union(Type::SymbolOrReceiver(), Type::EmptyString(),
     461             :                                   graph()->zone()),
     462      480406 :                       graph()->zone())),
     463      960813 :       type_cache_(TypeCache::Get()) {}
     464             : 
     465         164 : Reduction JSTypedLowering::ReduceJSBitwiseNot(Node* node) {
     466         164 :   Node* input = NodeProperties::GetValueInput(node, 0);
     467         164 :   Type input_type = NodeProperties::GetType(input);
     468         164 :   if (input_type.Is(Type::PlainPrimitive())) {
     469             :     // JSBitwiseNot(x) => NumberBitwiseXor(ToInt32(x), -1)
     470          34 :     node->InsertInput(graph()->zone(), 1, jsgraph()->SmiConstant(-1));
     471          34 :     NodeProperties::ChangeOp(node, javascript()->BitwiseXor());
     472             :     JSBinopReduction r(this, node);
     473          34 :     r.ConvertInputsToNumber();
     474          34 :     r.ConvertInputsToUI32(kSigned, kSigned);
     475          34 :     return r.ChangeToPureOperator(r.NumberOp(), Type::Signed32());
     476             :   }
     477             :   return NoChange();
     478             : }
     479             : 
     480        2173 : Reduction JSTypedLowering::ReduceJSDecrement(Node* node) {
     481        2173 :   Node* input = NodeProperties::GetValueInput(node, 0);
     482        2173 :   Type input_type = NodeProperties::GetType(input);
     483        2173 :   if (input_type.Is(Type::PlainPrimitive())) {
     484             :     // JSDecrement(x) => NumberSubtract(ToNumber(x), 1)
     485         307 :     node->InsertInput(graph()->zone(), 1, jsgraph()->OneConstant());
     486         307 :     NodeProperties::ChangeOp(node, javascript()->Subtract());
     487             :     JSBinopReduction r(this, node);
     488         307 :     r.ConvertInputsToNumber();
     489             :     DCHECK_EQ(simplified()->NumberSubtract(), r.NumberOp());
     490         307 :     return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
     491             :   }
     492             :   return NoChange();
     493             : }
     494             : 
     495       19160 : Reduction JSTypedLowering::ReduceJSIncrement(Node* node) {
     496       19160 :   Node* input = NodeProperties::GetValueInput(node, 0);
     497       19160 :   Type input_type = NodeProperties::GetType(input);
     498       19160 :   if (input_type.Is(Type::PlainPrimitive())) {
     499             :     // JSIncrement(x) => NumberAdd(ToNumber(x), 1)
     500       11661 :     node->InsertInput(graph()->zone(), 1, jsgraph()->OneConstant());
     501             :     BinaryOperationHint hint = BinaryOperationHint::kAny;  // Dummy.
     502       11661 :     NodeProperties::ChangeOp(node, javascript()->Add(hint));
     503             :     JSBinopReduction r(this, node);
     504       11661 :     r.ConvertInputsToNumber();
     505             :     DCHECK_EQ(simplified()->NumberAdd(), r.NumberOp());
     506       11661 :     return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
     507             :   }
     508             :   return NoChange();
     509             : }
     510             : 
     511        4035 : Reduction JSTypedLowering::ReduceJSNegate(Node* node) {
     512        4035 :   Node* input = NodeProperties::GetValueInput(node, 0);
     513        4035 :   Type input_type = NodeProperties::GetType(input);
     514        4035 :   if (input_type.Is(Type::PlainPrimitive())) {
     515             :     // JSNegate(x) => NumberMultiply(ToNumber(x), -1)
     516         235 :     node->InsertInput(graph()->zone(), 1, jsgraph()->SmiConstant(-1));
     517         235 :     NodeProperties::ChangeOp(node, javascript()->Multiply());
     518             :     JSBinopReduction r(this, node);
     519         235 :     r.ConvertInputsToNumber();
     520         235 :     return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
     521             :   }
     522             :   return NoChange();
     523             : }
     524             : 
     525       86368 : Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
     526             :   JSBinopReduction r(this, node);
     527       86368 :   if (r.BothInputsAre(Type::Number())) {
     528             :     // JSAdd(x:number, y:number) => NumberAdd(x, y)
     529       11939 :     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
     530             :   }
     531       96495 :   if (r.BothInputsAre(Type::PlainPrimitive()) &&
     532       22066 :       r.NeitherInputCanBe(Type::StringOrReceiver())) {
     533             :     // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
     534          17 :     r.ConvertInputsToNumber();
     535          17 :     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
     536             :   }
     537             : 
     538             :   // Strength-reduce if one input is already known to be a string.
     539       74412 :   if (r.LeftInputIs(Type::String())) {
     540             :     // JSAdd(x:string, y) => JSAdd(x, JSToString(y))
     541       43281 :     Reduction const reduction = ReduceJSToStringInput(r.right());
     542       43281 :     if (reduction.Changed()) {
     543       21779 :       NodeProperties::ReplaceValueInput(node, reduction.replacement(), 1);
     544             :     }
     545       31131 :   } else if (r.RightInputIs(Type::String())) {
     546             :     // JSAdd(x, y:string) => JSAdd(JSToString(x), y)
     547        7752 :     Reduction const reduction = ReduceJSToStringInput(r.left());
     548        7752 :     if (reduction.Changed()) {
     549         183 :       NodeProperties::ReplaceValueInput(node, reduction.replacement(), 0);
     550             :     }
     551             :   }
     552             : 
     553             :   // Always bake in String feedback into the graph.
     554       74412 :   BinaryOperationHint const hint = BinaryOperationHintOf(node->op());
     555       74412 :   if (hint == BinaryOperationHint::kConsOneByteString) {
     556        1814 :     r.CheckInputsToNonEmptyOneByteString();
     557       72598 :   } else if (hint == BinaryOperationHint::kConsTwoByteString) {
     558         136 :     r.CheckInputsToNonEmptyTwoByteString();
     559       72462 :   } else if (hint == BinaryOperationHint::kConsString) {
     560          18 :     r.CheckInputsToNonEmptyString();
     561       72444 :   } else if (hint == BinaryOperationHint::kString) {
     562        3668 :     r.CheckInputsToString();
     563             :   }
     564             : 
     565             :   // Strength-reduce concatenation of empty strings if both sides are
     566             :   // primitives, as in that case the ToPrimitive on the other side is
     567             :   // definitely going to be a no-op.
     568             :   // TODO(bmeurer): Put this empty string magic into the StringConcat
     569             :   // optimization, and instead go with just doing the input ToString()
     570             :   // magic here.
     571       74412 :   if (r.BothInputsAre(Type::Primitive())) {
     572       29785 :     if (r.LeftInputIs(Type::EmptyString())) {
     573             :       // JSAdd("", x:primitive) => JSToString(x)
     574         161 :       NodeProperties::ReplaceValueInputs(node, r.right());
     575         161 :       NodeProperties::ChangeOp(node, javascript()->ToString());
     576         161 :       NodeProperties::SetType(
     577             :           node, Type::Intersect(r.type(), Type::String(), graph()->zone()));
     578         161 :       Reduction const reduction = ReduceJSToString(node);
     579         161 :       return reduction.Changed() ? reduction : Changed(node);
     580       29624 :     } else if (r.RightInputIs(Type::EmptyString())) {
     581             :       // JSAdd(x:primitive, "") => JSToString(x)
     582         109 :       NodeProperties::ReplaceValueInputs(node, r.left());
     583         109 :       NodeProperties::ChangeOp(node, javascript()->ToString());
     584         109 :       NodeProperties::SetType(
     585             :           node, Type::Intersect(r.type(), Type::String(), graph()->zone()));
     586         109 :       Reduction const reduction = ReduceJSToString(node);
     587         109 :       return reduction.Changed() ? reduction : Changed(node);
     588             :     }
     589             :   }
     590             : 
     591             :   // Lower to string addition if both inputs are known to be strings.
     592       74142 :   if (r.BothInputsAre(Type::String())) {
     593       24337 :     Node* context = NodeProperties::GetContextInput(node);
     594       24337 :     Node* frame_state = NodeProperties::GetFrameStateInput(node);
     595       24337 :     Node* effect = NodeProperties::GetEffectInput(node);
     596       24337 :     Node* control = NodeProperties::GetControlInput(node);
     597             : 
     598             :     // Compute the resulting length.
     599             :     Node* left_length =
     600       24337 :         graph()->NewNode(simplified()->StringLength(), r.left());
     601             :     Node* right_length =
     602       24337 :         graph()->NewNode(simplified()->StringLength(), r.right());
     603             :     Node* length =
     604       24337 :         graph()->NewNode(simplified()->NumberAdd(), left_length, right_length);
     605             : 
     606             :     CellRef string_length_protector(broker(),
     607             :                                     factory()->string_length_protector());
     608       24337 :     if (string_length_protector.value().AsSmi() == Isolate::kProtectorValid) {
     609             :       // We can just deoptimize if the {length} is out-of-bounds. Besides
     610             :       // generating a shorter code sequence than the version below, this
     611             :       // has the additional benefit of not holding on to the lazy {frame_state}
     612             :       // and thus potentially reduces the number of live ranges and allows for
     613             :       // more truncations.
     614       48286 :       length = effect = graph()->NewNode(
     615             :           simplified()->CheckBounds(VectorSlotPair()), length,
     616             :           jsgraph()->Constant(String::kMaxLength + 1), effect, control);
     617             :     } else {
     618             :       // Check if we would overflow the allowed maximum string length.
     619             :       Node* check =
     620         194 :           graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
     621             :                            jsgraph()->Constant(String::kMaxLength));
     622             :       Node* branch =
     623         194 :           graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
     624         194 :       Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
     625             :       Node* efalse = effect;
     626             :       {
     627             :         // Throw a RangeError in case of overflow.
     628         194 :         Node* vfalse = efalse = if_false = graph()->NewNode(
     629             :             javascript()->CallRuntime(Runtime::kThrowInvalidStringLength),
     630             :             context, frame_state, efalse, if_false);
     631             : 
     632             :         // Update potential {IfException} uses of {node} to point to the
     633             :         // %ThrowInvalidStringLength runtime call node instead.
     634         194 :         Node* on_exception = nullptr;
     635         194 :         if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
     636          28 :           NodeProperties::ReplaceControlInput(on_exception, vfalse);
     637          28 :           NodeProperties::ReplaceEffectInput(on_exception, efalse);
     638          28 :           if_false = graph()->NewNode(common()->IfSuccess(), vfalse);
     639          28 :           Revisit(on_exception);
     640             :         }
     641             : 
     642             :         // The above %ThrowInvalidStringLength runtime call is an unconditional
     643             :         // throw, making it impossible to return a successful completion in this
     644             :         // case. We simply connect the successful completion to the graph end.
     645         194 :         if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
     646             :         // TODO(bmeurer): This should be on the AdvancedReducer somehow.
     647         194 :         NodeProperties::MergeControlToEnd(graph(), common(), if_false);
     648             :         Revisit(graph()->end());
     649             :       }
     650         194 :       control = graph()->NewNode(common()->IfTrue(), branch);
     651             :       length = effect =
     652         194 :           graph()->NewNode(common()->TypeGuard(type_cache_->kStringLengthType),
     653             :                            length, effect, control);
     654             :     }
     655             : 
     656       48674 :     if (hint == BinaryOperationHint::kConsString ||
     657       46842 :         hint == BinaryOperationHint::kConsOneByteString ||
     658             :         hint == BinaryOperationHint::kConsTwoByteString) {
     659        1892 :       Node* check = graph()->NewNode(
     660             :           simplified()->NumberLessThan(),
     661             :           jsgraph()->Constant(ConsString::kMinLength - 1), length);
     662        3784 :       effect = graph()->NewNode(
     663             :           simplified()->CheckIf(DeoptimizeReason::kWrongLength), check, effect,
     664             :           control);
     665        1892 :       length = effect = graph()->NewNode(
     666        1892 :           common()->TypeGuard(type_cache_->kConsStringLengthType), length,
     667             :           effect, control);
     668             :     }
     669             : 
     670       24337 :     Operator const* const op = simplified()->StringConcat();
     671             :     Node* value = graph()->NewNode(op, length, r.left(), r.right());
     672             :     ReplaceWithValue(node, value, effect, control);
     673             :     return Replace(value);
     674             :   }
     675             : 
     676             :   // We never get here when we had String feedback.
     677             :   DCHECK_NE(BinaryOperationHint::kConsString, hint);
     678             :   DCHECK_NE(BinaryOperationHint::kConsOneByteString, hint);
     679             :   DCHECK_NE(BinaryOperationHint::kConsTwoByteString, hint);
     680             :   DCHECK_NE(BinaryOperationHint::kString, hint);
     681       49805 :   if (r.OneInputIs(Type::String())) {
     682             :     StringAddFlags flags = STRING_ADD_CHECK_NONE;
     683       26716 :     if (!r.LeftInputIs(Type::String())) {
     684             :       flags = STRING_ADD_CONVERT_LEFT;
     685       20163 :     } else if (!r.RightInputIs(Type::String())) {
     686             :       flags = STRING_ADD_CONVERT_RIGHT;
     687             :     }
     688       26716 :     Operator::Properties properties = node->op()->properties();
     689       26716 :     if (r.NeitherInputCanBe(Type::Receiver())) {
     690             :       // Both sides are already strings, so we know that the
     691             :       // string addition will not cause any observable side
     692             :       // effects; it can still throw obviously.
     693         177 :       properties = Operator::kNoWrite | Operator::kNoDeopt;
     694             :     }
     695             : 
     696             :     // JSAdd(x:string, y) => CallStub[StringAdd](x, y)
     697             :     // JSAdd(x, y:string) => CallStub[StringAdd](x, y)
     698       26716 :     Callable const callable = CodeFactory::StringAdd(isolate(), flags);
     699       26716 :     auto call_descriptor = Linkage::GetStubCallDescriptor(
     700       26716 :         graph()->zone(), callable.descriptor(),
     701             :         callable.descriptor().GetStackParameterCount(),
     702       26716 :         CallDescriptor::kNeedsFrameState, properties);
     703             :     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
     704       53432 :     node->InsertInput(graph()->zone(), 0,
     705       26716 :                       jsgraph()->HeapConstant(callable.code()));
     706       26716 :     NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
     707             :     return Changed(node);
     708             :   }
     709             :   return NoChange();
     710             : }
     711             : 
     712       26279 : Reduction JSTypedLowering::ReduceNumberBinop(Node* node) {
     713             :   JSBinopReduction r(this, node);
     714       26279 :   if (r.BothInputsAre(Type::PlainPrimitive())) {
     715        5064 :     r.ConvertInputsToNumber();
     716        5064 :     return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
     717             :   }
     718             :   return NoChange();
     719             : }
     720             : 
     721       19453 : Reduction JSTypedLowering::ReduceInt32Binop(Node* node) {
     722             :   JSBinopReduction r(this, node);
     723       19453 :   if (r.BothInputsAre(Type::PlainPrimitive())) {
     724        4458 :     r.ConvertInputsToNumber();
     725        4458 :     r.ConvertInputsToUI32(kSigned, kSigned);
     726        4458 :     return r.ChangeToPureOperator(r.NumberOp(), Type::Signed32());
     727             :   }
     728             :   return NoChange();
     729             : }
     730             : 
     731        7960 : Reduction JSTypedLowering::ReduceUI32Shift(Node* node, Signedness signedness) {
     732             :   JSBinopReduction r(this, node);
     733        7960 :   if (r.BothInputsAre(Type::PlainPrimitive())) {
     734        5335 :     r.ConvertInputsToNumber();
     735        5335 :     r.ConvertInputsToUI32(signedness, kUnsigned);
     736             :     return r.ChangeToPureOperator(r.NumberOp(), signedness == kUnsigned
     737             :                                                     ? Type::Unsigned32()
     738        5335 :                                                     : Type::Signed32());
     739             :   }
     740             :   return NoChange();
     741             : }
     742             : 
     743       34553 : Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
     744             :   JSBinopReduction r(this, node);
     745       34553 :   if (r.BothInputsAre(Type::String())) {
     746             :     // If both inputs are definitely strings, perform a string comparison.
     747             :     const Operator* stringOp;
     748         873 :     switch (node->opcode()) {
     749             :       case IrOpcode::kJSLessThan:
     750         132 :         stringOp = simplified()->StringLessThan();
     751         132 :         break;
     752             :       case IrOpcode::kJSGreaterThan:
     753         116 :         stringOp = simplified()->StringLessThan();
     754         116 :         r.SwapInputs();  // a > b => b < a
     755         116 :         break;
     756             :       case IrOpcode::kJSLessThanOrEqual:
     757         312 :         stringOp = simplified()->StringLessThanOrEqual();
     758         312 :         break;
     759             :       case IrOpcode::kJSGreaterThanOrEqual:
     760         313 :         stringOp = simplified()->StringLessThanOrEqual();
     761         313 :         r.SwapInputs();  // a >= b => b <= a
     762         313 :         break;
     763             :       default:
     764             :         return NoChange();
     765             :     }
     766         873 :     r.ChangeToPureOperator(stringOp);
     767             :     return Changed(node);
     768             :   }
     769             : 
     770             :   const Operator* less_than;
     771             :   const Operator* less_than_or_equal;
     772       66168 :   if (r.BothInputsAre(Type::Signed32()) ||
     773       32488 :       r.BothInputsAre(Type::Unsigned32())) {
     774        1334 :     less_than = simplified()->NumberLessThan();
     775        1334 :     less_than_or_equal = simplified()->NumberLessThanOrEqual();
     776       62649 :   } else if (r.OneInputCannotBe(Type::StringOrReceiver()) &&
     777       30303 :              r.BothInputsAre(Type::PlainPrimitive())) {
     778        6724 :     r.ConvertInputsToNumber();
     779        6724 :     less_than = simplified()->NumberLessThan();
     780        6724 :     less_than_or_equal = simplified()->NumberLessThanOrEqual();
     781       25622 :   } else if (r.IsStringCompareOperation()) {
     782         236 :     r.CheckInputsToString();
     783         236 :     less_than = simplified()->StringLessThan();
     784         236 :     less_than_or_equal = simplified()->StringLessThanOrEqual();
     785             :   } else {
     786             :     return NoChange();
     787             :   }
     788             :   const Operator* comparison;
     789        8294 :   switch (node->opcode()) {
     790             :     case IrOpcode::kJSLessThan:
     791             :       comparison = less_than;
     792             :       break;
     793             :     case IrOpcode::kJSGreaterThan:
     794             :       comparison = less_than;
     795        1458 :       r.SwapInputs();  // a > b => b < a
     796        1458 :       break;
     797             :     case IrOpcode::kJSLessThanOrEqual:
     798             :       comparison = less_than_or_equal;
     799        1369 :       break;
     800             :     case IrOpcode::kJSGreaterThanOrEqual:
     801             :       comparison = less_than_or_equal;
     802        1328 :       r.SwapInputs();  // a >= b => b <= a
     803        1328 :       break;
     804             :     default:
     805             :       return NoChange();
     806             :   }
     807        8294 :   return r.ChangeToPureOperator(comparison);
     808             : }
     809             : 
     810       13454 : Reduction JSTypedLowering::ReduceJSEqual(Node* node) {
     811             :   JSBinopReduction r(this, node);
     812             : 
     813       13454 :   if (r.BothInputsAre(Type::UniqueName())) {
     814         900 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     815             :   }
     816       12554 :   if (r.IsInternalizedStringCompareOperation()) {
     817          49 :     r.CheckInputsToInternalizedString();
     818          49 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     819             :   }
     820       12505 :   if (r.BothInputsAre(Type::String())) {
     821          78 :     return r.ChangeToPureOperator(simplified()->StringEqual());
     822             :   }
     823       12427 :   if (r.BothInputsAre(Type::Boolean())) {
     824          38 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     825             :   }
     826       12389 :   if (r.BothInputsAre(Type::Receiver())) {
     827          21 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     828             :   }
     829       12368 :   if (r.OneInputIs(Type::Undetectable())) {
     830             :     RelaxEffectsAndControls(node);
     831          49 :     node->RemoveInput(r.LeftInputIs(Type::Undetectable()) ? 0 : 1);
     832          49 :     node->TrimInputCount(1);
     833          49 :     NodeProperties::ChangeOp(node, simplified()->ObjectIsUndetectable());
     834             :     return Changed(node);
     835             :   }
     836             : 
     837       21463 :   if (r.BothInputsAre(Type::Signed32()) ||
     838        9144 :       r.BothInputsAre(Type::Unsigned32())) {
     839        3221 :     return r.ChangeToPureOperator(simplified()->NumberEqual());
     840        9098 :   } else if (r.BothInputsAre(Type::Number())) {
     841         585 :     return r.ChangeToPureOperator(simplified()->NumberEqual());
     842        8513 :   } else if (r.IsReceiverCompareOperation()) {
     843          96 :     r.CheckInputsToReceiver();
     844          96 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     845        8417 :   } else if (r.IsReceiverOrNullOrUndefinedCompareOperation()) {
     846             :     // Check that both inputs are Receiver, Null or Undefined.
     847          38 :     r.CheckInputsToReceiverOrNullOrUndefined();
     848             : 
     849             :     // If one side is known to be a detectable receiver now, we
     850             :     // can simply perform reference equality here, since this
     851             :     // known detectable receiver is going to only match itself.
     852          38 :     if (r.OneInputIs(Type::DetectableReceiver())) {
     853          16 :       return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     854             :     }
     855             : 
     856             :     // Known that both sides are Receiver, Null or Undefined, the
     857             :     // abstract equality operation can be performed like this:
     858             :     //
     859             :     //   if ObjectIsUndetectable(left)
     860             :     //     then ObjectIsUndetectable(right)
     861             :     //     else ReferenceEqual(left, right)
     862             :     //
     863             :     Node* left = r.left();
     864             :     Node* right = r.right();
     865             :     Node* effect = r.effect();
     866             :     Node* control = r.control();
     867             : 
     868          22 :     Node* check = graph()->NewNode(simplified()->ObjectIsUndetectable(), left);
     869             :     Node* branch =
     870          22 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
     871             : 
     872          22 :     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
     873          22 :     Node* vtrue = graph()->NewNode(simplified()->ObjectIsUndetectable(), right);
     874             : 
     875          22 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
     876             :     Node* vfalse =
     877          22 :         graph()->NewNode(simplified()->ReferenceEqual(), left, right);
     878             : 
     879          22 :     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
     880             :     Node* value =
     881          22 :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     882             :                          vtrue, vfalse, control);
     883             :     ReplaceWithValue(node, value, effect, control);
     884             :     return Replace(value);
     885        8379 :   } else if (r.IsStringCompareOperation()) {
     886          36 :     r.CheckInputsToString();
     887          36 :     return r.ChangeToPureOperator(simplified()->StringEqual());
     888        8343 :   } else if (r.IsSymbolCompareOperation()) {
     889          16 :     r.CheckInputsToSymbol();
     890          16 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     891             :   }
     892             :   return NoChange();
     893             : }
     894             : 
     895      144700 : Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node) {
     896             :   JSBinopReduction r(this, node);
     897      144700 :   if (r.left() == r.right()) {
     898             :     // x === x is always true if x != NaN
     899        8942 :     Node* replacement = graph()->NewNode(
     900             :         simplified()->BooleanNot(),
     901             :         graph()->NewNode(simplified()->ObjectIsNaN(), r.left()));
     902             :     ReplaceWithValue(node, replacement);
     903             :     return Replace(replacement);
     904             :   }
     905      140229 :   if (r.OneInputCannotBe(Type::NumericOrString())) {
     906             :     // For values with canonical representation (i.e. neither String nor
     907             :     // Numeric) an empty type intersection means the values cannot be strictly
     908             :     // equal.
     909        5859 :     if (!r.left_type().Maybe(r.right_type())) {
     910         960 :       Node* replacement = jsgraph()->FalseConstant();
     911             :       ReplaceWithValue(node, replacement);
     912             :       return Replace(replacement);
     913             :     }
     914             :   }
     915             : 
     916      139269 :   if (r.BothInputsAre(Type::Unique())) {
     917        8993 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     918             :   }
     919      130276 :   if (r.OneInputIs(pointer_comparable_type_)) {
     920        2053 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     921             :   }
     922      128223 :   if (r.IsInternalizedStringCompareOperation()) {
     923        3471 :     r.CheckInputsToInternalizedString();
     924        3471 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     925             :   }
     926      124752 :   if (r.BothInputsAre(Type::String())) {
     927        3485 :     return r.ChangeToPureOperator(simplified()->StringEqual());
     928             :   }
     929             : 
     930             :   NumberOperationHint hint;
     931      237925 :   if (r.BothInputsAre(Type::Signed32()) ||
     932      116658 :       r.BothInputsAre(Type::Unsigned32())) {
     933        4819 :     return r.ChangeToPureOperator(simplified()->NumberEqual());
     934      116448 :   } else if (r.GetCompareNumberOperationHint(&hint)) {
     935             :     return r.ChangeToSpeculativeOperator(
     936       15037 :         simplified()->SpeculativeNumberEqual(hint), Type::Boolean());
     937      101411 :   } else if (r.BothInputsAre(Type::Number())) {
     938        6783 :     return r.ChangeToPureOperator(simplified()->NumberEqual());
     939       94628 :   } else if (r.IsReceiverCompareOperation()) {
     940             :     // For strict equality, it's enough to know that one input is a Receiver,
     941             :     // as a strict equality comparison with a Receiver can only yield true if
     942             :     // both sides refer to the same Receiver.
     943         692 :     r.CheckLeftInputToReceiver();
     944         692 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     945       93936 :   } else if (r.IsReceiverOrNullOrUndefinedCompareOperation()) {
     946             :     // For strict equality, it's enough to know that one input is a Receiver,
     947             :     // Null or Undefined, as a strict equality comparison with a Receiver,
     948             :     // Null or Undefined can only yield true if both sides refer to the same
     949             :     // instance.
     950          12 :     r.CheckLeftInputToReceiverOrNullOrUndefined();
     951          12 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     952       93924 :   } else if (r.IsStringCompareOperation()) {
     953        6870 :     r.CheckInputsToString();
     954        6870 :     return r.ChangeToPureOperator(simplified()->StringEqual());
     955       87054 :   } else if (r.IsSymbolCompareOperation()) {
     956             :     // For strict equality, it's enough to know that one input is a Symbol,
     957             :     // as a strict equality comparison with a Symbol can only yield true if
     958             :     // both sides refer to the same Symbol.
     959           8 :     r.CheckLeftInputToSymbol();
     960           8 :     return r.ChangeToPureOperator(simplified()->ReferenceEqual());
     961             :   }
     962             :   return NoChange();
     963             : }
     964             : 
     965        1148 : Reduction JSTypedLowering::ReduceJSToName(Node* node) {
     966        1148 :   Node* const input = NodeProperties::GetValueInput(node, 0);
     967        1148 :   Type const input_type = NodeProperties::GetType(input);
     968        1148 :   if (input_type.Is(Type::Name())) {
     969             :     // JSToName(x:name) => x
     970             :     ReplaceWithValue(node, input);
     971             :     return Replace(input);
     972             :   }
     973             :   return NoChange();
     974             : }
     975             : 
     976          36 : Reduction JSTypedLowering::ReduceJSToLength(Node* node) {
     977          36 :   Node* input = NodeProperties::GetValueInput(node, 0);
     978          36 :   Type input_type = NodeProperties::GetType(input);
     979          72 :   if (input_type.Is(type_cache_->kIntegerOrMinusZero)) {
     980           9 :     if (input_type.IsNone() || input_type.Max() <= 0.0) {
     981           1 :       input = jsgraph()->ZeroConstant();
     982           8 :     } else if (input_type.Min() >= kMaxSafeInteger) {
     983           1 :       input = jsgraph()->Constant(kMaxSafeInteger);
     984             :     } else {
     985           7 :       if (input_type.Min() <= 0.0) {
     986           7 :         input = graph()->NewNode(simplified()->NumberMax(),
     987             :                                  jsgraph()->ZeroConstant(), input);
     988             :       }
     989           7 :       if (input_type.Max() > kMaxSafeInteger) {
     990           0 :         input = graph()->NewNode(simplified()->NumberMin(),
     991             :                                  jsgraph()->Constant(kMaxSafeInteger), input);
     992             :       }
     993             :     }
     994             :     ReplaceWithValue(node, input);
     995             :     return Replace(input);
     996             :   }
     997             :   return NoChange();
     998             : }
     999             : 
    1000       79695 : Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
    1001             :   // Try constant-folding of JSToNumber with constant inputs.
    1002       79695 :   Type input_type = NodeProperties::GetType(input);
    1003             : 
    1004       79695 :   if (input_type.Is(Type::String())) {
    1005             :     HeapObjectMatcher m(input);
    1006        2828 :     if (m.HasValue() && m.Ref(broker()).IsString()) {
    1007         841 :       StringRef input_value = m.Ref(broker()).AsString();
    1008             :       double number;
    1009         841 :       ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(number, input_value.ToNumber());
    1010         841 :       return Replace(jsgraph()->Constant(number));
    1011             :     }
    1012             :   }
    1013       78854 :   if (input_type.IsHeapConstant()) {
    1014         842 :     HeapObjectRef input_value = input_type.AsHeapConstant()->Ref();
    1015             :     double value;
    1016        1684 :     if (input_value.OddballToNumber().To(&value)) {
    1017         806 :       return Replace(jsgraph()->Constant(value));
    1018             :     }
    1019             :   }
    1020       78048 :   if (input_type.Is(Type::Number())) {
    1021             :     // JSToNumber(x:number) => x
    1022             :     return Changed(input);
    1023             :   }
    1024       13011 :   if (input_type.Is(Type::Undefined())) {
    1025             :     // JSToNumber(undefined) => #NaN
    1026         820 :     return Replace(jsgraph()->NaNConstant());
    1027             :   }
    1028       12191 :   if (input_type.Is(Type::Null())) {
    1029             :     // JSToNumber(null) => #0
    1030         820 :     return Replace(jsgraph()->ZeroConstant());
    1031             :   }
    1032             :   return NoChange();
    1033             : }
    1034             : 
    1035       12025 : Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
    1036             :   // Try to reduce the input first.
    1037             :   Node* const input = node->InputAt(0);
    1038       12025 :   Reduction reduction = ReduceJSToNumberInput(input);
    1039       12025 :   if (reduction.Changed()) {
    1040             :     ReplaceWithValue(node, reduction.replacement());
    1041        2494 :     return reduction;
    1042             :   }
    1043        9531 :   Type const input_type = NodeProperties::GetType(input);
    1044        9531 :   if (input_type.Is(Type::PlainPrimitive())) {
    1045             :     RelaxEffectsAndControls(node);
    1046         358 :     node->TrimInputCount(1);
    1047             :     // For a PlainPrimitive, ToNumeric is the same as ToNumber.
    1048         358 :     Type node_type = NodeProperties::GetType(node);
    1049         358 :     NodeProperties::SetType(
    1050             :         node, Type::Intersect(node_type, Type::Number(), graph()->zone()));
    1051         358 :     NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber());
    1052             :     return Changed(node);
    1053             :   }
    1054             :   return NoChange();
    1055             : }
    1056             : 
    1057        4568 : Reduction JSTypedLowering::ReduceJSToNumeric(Node* node) {
    1058        4568 :   Node* const input = NodeProperties::GetValueInput(node, 0);
    1059        4568 :   Type const input_type = NodeProperties::GetType(input);
    1060        4568 :   if (input_type.Is(Type::NonBigIntPrimitive())) {
    1061             :     // ToNumeric(x:primitive\bigint) => ToNumber(x)
    1062        2219 :     NodeProperties::ChangeOp(node, javascript()->ToNumber());
    1063        2219 :     Reduction const reduction = ReduceJSToNumber(node);
    1064        2219 :     return reduction.Changed() ? reduction : Changed(node);
    1065             :   }
    1066             :   return NoChange();
    1067             : }
    1068             : 
    1069       54955 : Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
    1070       54955 :   if (input->opcode() == IrOpcode::kJSToString) {
    1071             :     // Recursively try to reduce the input first.
    1072        1486 :     Reduction result = ReduceJSToString(input);
    1073        1486 :     if (result.Changed()) return result;
    1074             :     return Changed(input);  // JSToString(JSToString(x)) => JSToString(x)
    1075             :   }
    1076       53469 :   Type input_type = NodeProperties::GetType(input);
    1077       53469 :   if (input_type.Is(Type::String())) {
    1078             :     return Changed(input);  // JSToString(x:string) => x
    1079             :   }
    1080       33930 :   if (input_type.Is(Type::Boolean())) {
    1081             :     return Replace(graph()->NewNode(
    1082             :         common()->Select(MachineRepresentation::kTagged), input,
    1083             :         jsgraph()->HeapConstant(factory()->true_string()),
    1084         222 :         jsgraph()->HeapConstant(factory()->false_string())));
    1085             :   }
    1086       33856 :   if (input_type.Is(Type::Undefined())) {
    1087          69 :     return Replace(jsgraph()->HeapConstant(factory()->undefined_string()));
    1088             :   }
    1089       33787 :   if (input_type.Is(Type::Null())) {
    1090          14 :     return Replace(jsgraph()->HeapConstant(factory()->null_string()));
    1091             :   }
    1092       33773 :   if (input_type.Is(Type::NaN())) {
    1093           2 :     return Replace(jsgraph()->HeapConstant(factory()->NaN_string()));
    1094             :   }
    1095       33771 :   if (input_type.Is(Type::Number())) {
    1096        1141 :     return Replace(graph()->NewNode(simplified()->NumberToString(), input));
    1097             :   }
    1098             :   return NoChange();
    1099             : }
    1100             : 
    1101        3922 : Reduction JSTypedLowering::ReduceJSToString(Node* node) {
    1102             :   DCHECK_EQ(IrOpcode::kJSToString, node->opcode());
    1103             :   // Try to reduce the input first.
    1104             :   Node* const input = node->InputAt(0);
    1105        3922 :   Reduction reduction = ReduceJSToStringInput(input);
    1106        3922 :   if (reduction.Changed()) {
    1107             :     ReplaceWithValue(node, reduction.replacement());
    1108         363 :     return reduction;
    1109             :   }
    1110             :   return NoChange();
    1111             : }
    1112             : 
    1113        1935 : Reduction JSTypedLowering::ReduceJSToObject(Node* node) {
    1114             :   DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
    1115        1935 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1116        1935 :   Type receiver_type = NodeProperties::GetType(receiver);
    1117        1935 :   Node* context = NodeProperties::GetContextInput(node);
    1118        1935 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    1119        1935 :   Node* effect = NodeProperties::GetEffectInput(node);
    1120        1935 :   Node* control = NodeProperties::GetControlInput(node);
    1121        1935 :   if (receiver_type.Is(Type::Receiver())) {
    1122             :     ReplaceWithValue(node, receiver, effect, control);
    1123             :     return Replace(receiver);
    1124             :   }
    1125             : 
    1126             :   // Check whether {receiver} is a spec object.
    1127        1479 :   Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
    1128             :   Node* branch =
    1129        1479 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    1130             : 
    1131        1479 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1132             :   Node* etrue = effect;
    1133             :   Node* rtrue = receiver;
    1134             : 
    1135        1479 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    1136             :   Node* efalse = effect;
    1137             :   Node* rfalse;
    1138             :   {
    1139             :     // Convert {receiver} using the ToObjectStub.
    1140        1479 :     Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject);
    1141        1479 :     auto call_descriptor = Linkage::GetStubCallDescriptor(
    1142        1479 :         graph()->zone(), callable.descriptor(),
    1143             :         callable.descriptor().GetStackParameterCount(),
    1144        1479 :         CallDescriptor::kNeedsFrameState, node->op()->properties());
    1145             :     rfalse = efalse = if_false =
    1146        2958 :         graph()->NewNode(common()->Call(call_descriptor),
    1147             :                          jsgraph()->HeapConstant(callable.code()), receiver,
    1148             :                          context, frame_state, efalse, if_false);
    1149             :   }
    1150             : 
    1151             :   // Update potential {IfException} uses of {node} to point to the above
    1152             :   // ToObject stub call node instead. Note that the stub can only throw on
    1153             :   // receivers that can be null or undefined.
    1154        1479 :   Node* on_exception = nullptr;
    1155        2875 :   if (receiver_type.Maybe(Type::NullOrUndefined()) &&
    1156        1396 :       NodeProperties::IsExceptionalCall(node, &on_exception)) {
    1157         207 :     NodeProperties::ReplaceControlInput(on_exception, if_false);
    1158         207 :     NodeProperties::ReplaceEffectInput(on_exception, efalse);
    1159         207 :     if_false = graph()->NewNode(common()->IfSuccess(), if_false);
    1160         207 :     Revisit(on_exception);
    1161             :   }
    1162             : 
    1163        1479 :   control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    1164        1479 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    1165             : 
    1166             :   // Morph the {node} into an appropriate Phi.
    1167             :   ReplaceWithValue(node, node, effect, control);
    1168        1479 :   node->ReplaceInput(0, rtrue);
    1169        1479 :   node->ReplaceInput(1, rfalse);
    1170        1479 :   node->ReplaceInput(2, control);
    1171        1479 :   node->TrimInputCount(3);
    1172        1479 :   NodeProperties::ChangeOp(node,
    1173        1479 :                            common()->Phi(MachineRepresentation::kTagged, 2));
    1174             :   return Changed(node);
    1175             : }
    1176             : 
    1177      423882 : Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
    1178             :   DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
    1179      423882 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1180      423882 :   Type receiver_type = NodeProperties::GetType(receiver);
    1181      423882 :   NameRef name(broker(), NamedAccessOf(node->op()).name());
    1182             :   NameRef length_str(broker(), factory()->length_string());
    1183             :   // Optimize "length" property of strings.
    1184      458771 :   if (name.equals(length_str) && receiver_type.Is(Type::String())) {
    1185          19 :     Node* value = graph()->NewNode(simplified()->StringLength(), receiver);
    1186             :     ReplaceWithValue(node, value);
    1187             :     return Replace(value);
    1188             :   }
    1189             :   return NoChange();
    1190             : }
    1191             : 
    1192         833 : Reduction JSTypedLowering::ReduceJSHasInPrototypeChain(Node* node) {
    1193             :   DCHECK_EQ(IrOpcode::kJSHasInPrototypeChain, node->opcode());
    1194         833 :   Node* value = NodeProperties::GetValueInput(node, 0);
    1195         833 :   Type value_type = NodeProperties::GetType(value);
    1196         833 :   Node* prototype = NodeProperties::GetValueInput(node, 1);
    1197         833 :   Node* context = NodeProperties::GetContextInput(node);
    1198         833 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    1199         833 :   Node* effect = NodeProperties::GetEffectInput(node);
    1200         833 :   Node* control = NodeProperties::GetControlInput(node);
    1201             : 
    1202             :   // If {value} cannot be a receiver, then it cannot have {prototype} in
    1203             :   // it's prototype chain (all Primitive values have a null prototype).
    1204         833 :   if (value_type.Is(Type::Primitive())) {
    1205         159 :     Node* value = jsgraph()->FalseConstant();
    1206             :     ReplaceWithValue(node, value, effect, control);
    1207             :     return Replace(value);
    1208             :   }
    1209             : 
    1210         674 :   Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
    1211             :   Node* branch0 =
    1212         674 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
    1213             : 
    1214         674 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    1215             :   Node* etrue0 = effect;
    1216         674 :   Node* vtrue0 = jsgraph()->FalseConstant();
    1217             : 
    1218         674 :   control = graph()->NewNode(common()->IfFalse(), branch0);
    1219             : 
    1220             :   // Loop through the {value}s prototype chain looking for the {prototype}.
    1221         674 :   Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
    1222             :   Node* eloop = effect =
    1223         674 :       graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    1224         674 :   Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
    1225         674 :   NodeProperties::MergeControlToEnd(graph(), common(), terminate);
    1226         674 :   Node* vloop = value = graph()->NewNode(
    1227             :       common()->Phi(MachineRepresentation::kTagged, 2), value, value, loop);
    1228             :   NodeProperties::SetType(vloop, Type::NonInternal());
    1229             : 
    1230             :   // Load the {value} map and instance type.
    1231         674 :   Node* value_map = effect = graph()->NewNode(
    1232        1348 :       simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
    1233         674 :   Node* value_instance_type = effect = graph()->NewNode(
    1234        1348 :       simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
    1235             :       effect, control);
    1236             : 
    1237             :   // Check if the {value} is a special receiver, because for special
    1238             :   // receivers, i.e. proxies or API values that need access checks,
    1239             :   // we have to use the %HasInPrototypeChain runtime function instead.
    1240         674 :   Node* check1 = graph()->NewNode(
    1241             :       simplified()->NumberLessThanOrEqual(), value_instance_type,
    1242             :       jsgraph()->Constant(LAST_SPECIAL_RECEIVER_TYPE));
    1243             :   Node* branch1 =
    1244         674 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
    1245             : 
    1246         674 :   control = graph()->NewNode(common()->IfFalse(), branch1);
    1247             : 
    1248         674 :   Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    1249             :   Node* etrue1 = effect;
    1250             :   Node* vtrue1;
    1251             : 
    1252             :   // Check if the {value} is not a receiver at all.
    1253             :   Node* check10 =
    1254         674 :       graph()->NewNode(simplified()->NumberLessThan(), value_instance_type,
    1255             :                        jsgraph()->Constant(FIRST_JS_RECEIVER_TYPE));
    1256             :   Node* branch10 =
    1257         674 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check10, if_true1);
    1258             : 
    1259             :   // A primitive value cannot match the {prototype} we're looking for.
    1260         674 :   if_true1 = graph()->NewNode(common()->IfTrue(), branch10);
    1261         674 :   vtrue1 = jsgraph()->FalseConstant();
    1262             : 
    1263         674 :   Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10);
    1264             :   Node* efalse1 = etrue1;
    1265             :   Node* vfalse1;
    1266             :   {
    1267             :     // Slow path, need to call the %HasInPrototypeChain runtime function.
    1268         674 :     vfalse1 = efalse1 = if_false1 = graph()->NewNode(
    1269             :         javascript()->CallRuntime(Runtime::kHasInPrototypeChain), value,
    1270             :         prototype, context, frame_state, efalse1, if_false1);
    1271             : 
    1272             :     // Replace any potential {IfException} uses of {node} to catch
    1273             :     // exceptions from this %HasInPrototypeChain runtime call instead.
    1274         674 :     Node* on_exception = nullptr;
    1275         674 :     if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    1276          28 :       NodeProperties::ReplaceControlInput(on_exception, vfalse1);
    1277          28 :       NodeProperties::ReplaceEffectInput(on_exception, efalse1);
    1278          28 :       if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1);
    1279          28 :       Revisit(on_exception);
    1280             :     }
    1281             :   }
    1282             : 
    1283             :   // Load the {value} prototype.
    1284         674 :   Node* value_prototype = effect = graph()->NewNode(
    1285        1348 :       simplified()->LoadField(AccessBuilder::ForMapPrototype()), value_map,
    1286             :       effect, control);
    1287             : 
    1288             :   // Check if we reached the end of {value}s prototype chain.
    1289         674 :   Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(),
    1290             :                                   value_prototype, jsgraph()->NullConstant());
    1291         674 :   Node* branch2 = graph()->NewNode(common()->Branch(), check2, control);
    1292             : 
    1293         674 :   Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
    1294             :   Node* etrue2 = effect;
    1295         674 :   Node* vtrue2 = jsgraph()->FalseConstant();
    1296             : 
    1297         674 :   control = graph()->NewNode(common()->IfFalse(), branch2);
    1298             : 
    1299             :   // Check if we reached the {prototype}.
    1300         674 :   Node* check3 = graph()->NewNode(simplified()->ReferenceEqual(),
    1301             :                                   value_prototype, prototype);
    1302         674 :   Node* branch3 = graph()->NewNode(common()->Branch(), check3, control);
    1303             : 
    1304         674 :   Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
    1305             :   Node* etrue3 = effect;
    1306         674 :   Node* vtrue3 = jsgraph()->TrueConstant();
    1307             : 
    1308         674 :   control = graph()->NewNode(common()->IfFalse(), branch3);
    1309             : 
    1310             :   // Close the loop.
    1311         674 :   vloop->ReplaceInput(1, value_prototype);
    1312         674 :   eloop->ReplaceInput(1, effect);
    1313         674 :   loop->ReplaceInput(1, control);
    1314             : 
    1315         674 :   control = graph()->NewNode(common()->Merge(5), if_true0, if_true1, if_true2,
    1316             :                              if_true3, if_false1);
    1317         674 :   effect = graph()->NewNode(common()->EffectPhi(5), etrue0, etrue1, etrue2,
    1318             :                             etrue3, efalse1, control);
    1319             : 
    1320             :   // Morph the {node} into an appropriate Phi.
    1321             :   ReplaceWithValue(node, node, effect, control);
    1322         674 :   node->ReplaceInput(0, vtrue0);
    1323         674 :   node->ReplaceInput(1, vtrue1);
    1324         674 :   node->ReplaceInput(2, vtrue2);
    1325         674 :   node->ReplaceInput(3, vtrue3);
    1326         674 :   node->ReplaceInput(4, vfalse1);
    1327         674 :   node->ReplaceInput(5, control);
    1328         674 :   node->TrimInputCount(6);
    1329         674 :   NodeProperties::ChangeOp(node,
    1330         674 :                            common()->Phi(MachineRepresentation::kTagged, 5));
    1331             :   return Changed(node);
    1332             : }
    1333             : 
    1334         110 : Reduction JSTypedLowering::ReduceJSOrdinaryHasInstance(Node* node) {
    1335             :   DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
    1336         110 :   Node* constructor = NodeProperties::GetValueInput(node, 0);
    1337         110 :   Type constructor_type = NodeProperties::GetType(constructor);
    1338         110 :   Node* object = NodeProperties::GetValueInput(node, 1);
    1339         110 :   Type object_type = NodeProperties::GetType(object);
    1340             : 
    1341             :   // Check if the {constructor} cannot be callable.
    1342             :   // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 1.
    1343         110 :   if (!constructor_type.Maybe(Type::Callable())) {
    1344           7 :     Node* value = jsgraph()->FalseConstant();
    1345             :     ReplaceWithValue(node, value);
    1346             :     return Replace(value);
    1347             :   }
    1348             : 
    1349             :   // If the {constructor} cannot be a JSBoundFunction and then {object}
    1350             :   // cannot be a JSReceiver, then this can be constant-folded to false.
    1351             :   // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 2 and 3.
    1352         124 :   if (!object_type.Maybe(Type::Receiver()) &&
    1353          21 :       !constructor_type.Maybe(Type::BoundFunction())) {
    1354          14 :     Node* value = jsgraph()->FalseConstant();
    1355             :     ReplaceWithValue(node, value);
    1356             :     return Replace(value);
    1357             :   }
    1358             : 
    1359             :   return NoChange();
    1360             : }
    1361             : 
    1362      302264 : Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
    1363             :   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
    1364      302264 :   ContextAccess const& access = ContextAccessOf(node->op());
    1365      302264 :   Node* effect = NodeProperties::GetEffectInput(node);
    1366      302264 :   Node* context = NodeProperties::GetContextInput(node);
    1367             :   Node* control = graph()->start();
    1368      317844 :   for (size_t i = 0; i < access.depth(); ++i) {
    1369        7790 :     context = effect = graph()->NewNode(
    1370             :         simplified()->LoadField(
    1371       15580 :             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
    1372             :         context, effect, control);
    1373             :   }
    1374      302264 :   node->ReplaceInput(0, context);
    1375      302264 :   node->ReplaceInput(1, effect);
    1376      302264 :   node->AppendInput(jsgraph()->zone(), control);
    1377      302264 :   NodeProperties::ChangeOp(
    1378             :       node,
    1379      604528 :       simplified()->LoadField(AccessBuilder::ForContextSlot(access.index())));
    1380      302264 :   return Changed(node);
    1381             : }
    1382             : 
    1383      450771 : Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
    1384             :   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
    1385      450771 :   ContextAccess const& access = ContextAccessOf(node->op());
    1386      450771 :   Node* effect = NodeProperties::GetEffectInput(node);
    1387      450771 :   Node* context = NodeProperties::GetContextInput(node);
    1388             :   Node* control = graph()->start();
    1389      450771 :   Node* value = NodeProperties::GetValueInput(node, 0);
    1390      451187 :   for (size_t i = 0; i < access.depth(); ++i) {
    1391         208 :     context = effect = graph()->NewNode(
    1392             :         simplified()->LoadField(
    1393         416 :             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
    1394             :         context, effect, control);
    1395             :   }
    1396      450771 :   node->ReplaceInput(0, context);
    1397      450771 :   node->ReplaceInput(1, value);
    1398      450771 :   node->ReplaceInput(2, effect);
    1399      450771 :   NodeProperties::ChangeOp(
    1400             :       node,
    1401      901542 :       simplified()->StoreField(AccessBuilder::ForContextSlot(access.index())));
    1402      450771 :   return Changed(node);
    1403             : }
    1404             : 
    1405        7242 : Node* JSTypedLowering::BuildGetModuleCell(Node* node) {
    1406             :   DCHECK(node->opcode() == IrOpcode::kJSLoadModule ||
    1407             :          node->opcode() == IrOpcode::kJSStoreModule);
    1408        7242 :   Node* effect = NodeProperties::GetEffectInput(node);
    1409        7242 :   Node* control = NodeProperties::GetControlInput(node);
    1410             : 
    1411        7242 :   int32_t cell_index = OpParameter<int32_t>(node->op());
    1412        7242 :   Node* module = NodeProperties::GetValueInput(node, 0);
    1413        7242 :   Type module_type = NodeProperties::GetType(module);
    1414             : 
    1415        7242 :   if (module_type.IsHeapConstant()) {
    1416         138 :     ModuleRef module_constant = module_type.AsHeapConstant()->Ref().AsModule();
    1417         138 :     CellRef cell_constant = module_constant.GetCell(cell_index);
    1418         138 :     return jsgraph()->Constant(cell_constant);
    1419             :   }
    1420             : 
    1421             :   FieldAccess field_access;
    1422             :   int index;
    1423        7104 :   if (ModuleDescriptor::GetCellIndexKind(cell_index) ==
    1424             :       ModuleDescriptor::kExport) {
    1425        7001 :     field_access = AccessBuilder::ForModuleRegularExports();
    1426        7001 :     index = cell_index - 1;
    1427             :   } else {
    1428             :     DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
    1429             :               ModuleDescriptor::kImport);
    1430         103 :     field_access = AccessBuilder::ForModuleRegularImports();
    1431         103 :     index = -cell_index - 1;
    1432             :   }
    1433        7104 :   Node* array = effect = graph()->NewNode(simplified()->LoadField(field_access),
    1434             :                                           module, effect, control);
    1435        7104 :   return graph()->NewNode(
    1436       14208 :       simplified()->LoadField(AccessBuilder::ForFixedArraySlot(index)), array,
    1437             :       effect, control);
    1438             : }
    1439             : 
    1440         294 : Reduction JSTypedLowering::ReduceJSLoadModule(Node* node) {
    1441             :   DCHECK_EQ(IrOpcode::kJSLoadModule, node->opcode());
    1442         294 :   Node* effect = NodeProperties::GetEffectInput(node);
    1443         294 :   Node* control = NodeProperties::GetControlInput(node);
    1444             : 
    1445         294 :   Node* cell = BuildGetModuleCell(node);
    1446         294 :   if (cell->op()->EffectOutputCount() > 0) effect = cell;
    1447             :   Node* value = effect =
    1448         588 :       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForCellValue()),
    1449             :                        cell, effect, control);
    1450             : 
    1451             :   ReplaceWithValue(node, value, effect, control);
    1452         294 :   return Changed(value);
    1453             : }
    1454             : 
    1455        6948 : Reduction JSTypedLowering::ReduceJSStoreModule(Node* node) {
    1456             :   DCHECK_EQ(IrOpcode::kJSStoreModule, node->opcode());
    1457        6948 :   Node* effect = NodeProperties::GetEffectInput(node);
    1458        6948 :   Node* control = NodeProperties::GetControlInput(node);
    1459        6948 :   Node* value = NodeProperties::GetValueInput(node, 1);
    1460             :   DCHECK_EQ(
    1461             :       ModuleDescriptor::GetCellIndexKind(OpParameter<int32_t>(node->op())),
    1462             :       ModuleDescriptor::kExport);
    1463             : 
    1464        6948 :   Node* cell = BuildGetModuleCell(node);
    1465        6948 :   if (cell->op()->EffectOutputCount() > 0) effect = cell;
    1466             :   effect =
    1467       13896 :       graph()->NewNode(simplified()->StoreField(AccessBuilder::ForCellValue()),
    1468             :                        cell, value, effect, control);
    1469             : 
    1470             :   ReplaceWithValue(node, effect, effect, control);
    1471        6948 :   return Changed(value);
    1472             : }
    1473             : 
    1474             : namespace {
    1475             : 
    1476        2739 : void ReduceBuiltin(JSGraph* jsgraph, Node* node, int builtin_index, int arity,
    1477             :                    CallDescriptor::Flags flags) {
    1478             :   // Patch {node} to a direct CEntry call.
    1479             :   //
    1480             :   // ----------- A r g u m e n t s -----------
    1481             :   // -- 0: CEntry
    1482             :   // --- Stack args ---
    1483             :   // -- 1: receiver
    1484             :   // -- [2, 2 + n[: the n actual arguments passed to the builtin
    1485             :   // -- 2 + n: argc, including the receiver and implicit args (Smi)
    1486             :   // -- 2 + n + 1: target
    1487             :   // -- 2 + n + 2: new_target
    1488             :   // --- Register args ---
    1489             :   // -- 2 + n + 3: the C entry point
    1490             :   // -- 2 + n + 4: argc (Int32)
    1491             :   // -----------------------------------
    1492             : 
    1493             :   // The logic contained here is mirrored in Builtins::Generate_Adaptor.
    1494             :   // Keep these in sync.
    1495             : 
    1496             :   const bool is_construct = (node->opcode() == IrOpcode::kJSConstruct);
    1497             : 
    1498             :   DCHECK(Builtins::HasCppImplementation(builtin_index));
    1499             : 
    1500        2739 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1501             :   Node* new_target = is_construct
    1502           0 :                          ? NodeProperties::GetValueInput(node, arity + 1)
    1503        2739 :                          : jsgraph->UndefinedConstant();
    1504             : 
    1505             :   // API and CPP builtins are implemented in C++, and we can inline both.
    1506             :   // CPP builtins create a builtin exit frame, API builtins don't.
    1507        2739 :   const bool has_builtin_exit_frame = Builtins::IsCpp(builtin_index);
    1508             : 
    1509        2739 :   Node* stub = jsgraph->CEntryStubConstant(1, kDontSaveFPRegs, kArgvOnStack,
    1510        2739 :                                            has_builtin_exit_frame);
    1511        2739 :   node->ReplaceInput(0, stub);
    1512             : 
    1513             :   Zone* zone = jsgraph->zone();
    1514        2739 :   if (is_construct) {
    1515             :     // Unify representations between construct and call nodes.
    1516             :     // Remove new target and add receiver as a stack parameter.
    1517           0 :     Node* receiver = jsgraph->UndefinedConstant();
    1518           0 :     node->RemoveInput(arity + 1);
    1519           0 :     node->InsertInput(zone, 1, receiver);
    1520             :   }
    1521             : 
    1522        2739 :   const int argc = arity + BuiltinArguments::kNumExtraArgsWithReceiver;
    1523        2739 :   Node* argc_node = jsgraph->Constant(argc);
    1524             : 
    1525             :   static const int kStubAndReceiver = 2;
    1526        2739 :   int cursor = arity + kStubAndReceiver;
    1527        2739 :   node->InsertInput(zone, cursor++, jsgraph->PaddingConstant());
    1528        2739 :   node->InsertInput(zone, cursor++, argc_node);
    1529        2739 :   node->InsertInput(zone, cursor++, target);
    1530        2739 :   node->InsertInput(zone, cursor++, new_target);
    1531             : 
    1532        2739 :   Address entry = Builtins::CppEntryOf(builtin_index);
    1533        2739 :   ExternalReference entry_ref = ExternalReference::Create(entry);
    1534        2739 :   Node* entry_node = jsgraph->ExternalConstant(entry_ref);
    1535             : 
    1536        2739 :   node->InsertInput(zone, cursor++, entry_node);
    1537        2739 :   node->InsertInput(zone, cursor++, argc_node);
    1538             : 
    1539             :   static const int kReturnCount = 1;
    1540        2739 :   const char* debug_name = Builtins::name(builtin_index);
    1541        2739 :   Operator::Properties properties = node->op()->properties();
    1542             :   auto call_descriptor = Linkage::GetCEntryStubCallDescriptor(
    1543        2739 :       zone, kReturnCount, argc, debug_name, properties, flags);
    1544             : 
    1545        2739 :   NodeProperties::ChangeOp(node, jsgraph->common()->Call(call_descriptor));
    1546        2739 : }
    1547             : 
    1548             : bool NeedsArgumentAdaptorFrame(SharedFunctionInfoRef shared, int arity) {
    1549             :   static const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
    1550       28070 :   const int num_decl_parms = shared.internal_formal_parameter_count();
    1551       28070 :   return (num_decl_parms != arity && num_decl_parms != sentinel);
    1552             : }
    1553             : 
    1554             : }  // namespace
    1555             : 
    1556         469 : Reduction JSTypedLowering::ReduceJSConstructForwardVarargs(Node* node) {
    1557             :   DCHECK_EQ(IrOpcode::kJSConstructForwardVarargs, node->opcode());
    1558             :   ConstructForwardVarargsParameters p =
    1559         469 :       ConstructForwardVarargsParametersOf(node->op());
    1560             :   DCHECK_LE(2u, p.arity());
    1561         469 :   int const arity = static_cast<int>(p.arity() - 2);
    1562         469 :   int const start_index = static_cast<int>(p.start_index());
    1563         469 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1564         469 :   Type target_type = NodeProperties::GetType(target);
    1565         469 :   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
    1566             : 
    1567             :   // Check if {target} is a JSFunction.
    1568         899 :   if (target_type.IsHeapConstant() &&
    1569         430 :       target_type.AsHeapConstant()->Ref().IsJSFunction()) {
    1570             :     // Only optimize [[Construct]] here if {function} is a Constructor.
    1571         429 :     JSFunctionRef function = target_type.AsHeapConstant()->Ref().AsJSFunction();
    1572         429 :     if (!function.map().is_constructor()) return NoChange();
    1573             :     // Patch {node} to an indirect call via ConstructFunctionForwardVarargs.
    1574         429 :     Callable callable = CodeFactory::ConstructFunctionForwardVarargs(isolate());
    1575         429 :     node->RemoveInput(arity + 1);
    1576         858 :     node->InsertInput(graph()->zone(), 0,
    1577         429 :                       jsgraph()->HeapConstant(callable.code()));
    1578         429 :     node->InsertInput(graph()->zone(), 2, new_target);
    1579         429 :     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
    1580         429 :     node->InsertInput(graph()->zone(), 4, jsgraph()->Constant(start_index));
    1581         429 :     node->InsertInput(graph()->zone(), 5, jsgraph()->UndefinedConstant());
    1582         429 :     NodeProperties::ChangeOp(
    1583         858 :         node, common()->Call(Linkage::GetStubCallDescriptor(
    1584         429 :                   graph()->zone(), callable.descriptor(), arity + 1,
    1585         429 :                   CallDescriptor::kNeedsFrameState)));
    1586             :     return Changed(node);
    1587             :   }
    1588             : 
    1589             :   return NoChange();
    1590             : }
    1591             : 
    1592       35545 : Reduction JSTypedLowering::ReduceJSConstruct(Node* node) {
    1593             :   DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
    1594       35545 :   ConstructParameters const& p = ConstructParametersOf(node->op());
    1595             :   DCHECK_LE(2u, p.arity());
    1596       35545 :   int const arity = static_cast<int>(p.arity() - 2);
    1597       35545 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1598       35545 :   Type target_type = NodeProperties::GetType(target);
    1599       35545 :   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
    1600             : 
    1601             :   // Check if {target} is a known JSFunction.
    1602       39402 :   if (target_type.IsHeapConstant() &&
    1603        3857 :       target_type.AsHeapConstant()->Ref().IsJSFunction()) {
    1604        3101 :     JSFunctionRef function = target_type.AsHeapConstant()->Ref().AsJSFunction();
    1605        3101 :     SharedFunctionInfoRef shared = function.shared();
    1606             : 
    1607             :     // Only optimize [[Construct]] here if {function} is a Constructor.
    1608        3101 :     if (!function.map().is_constructor()) return NoChange();
    1609             : 
    1610             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    1611             : 
    1612             :     // Patch {node} to an indirect call via the {function}s construct stub.
    1613        3100 :     bool use_builtin_construct_stub = shared.construct_as_builtin();
    1614             : 
    1615             :     CodeRef code(broker(),
    1616             :                  use_builtin_construct_stub
    1617             :                      ? BUILTIN_CODE(isolate(), JSBuiltinsConstructStub)
    1618        6200 :                      : BUILTIN_CODE(isolate(), JSConstructStubGeneric));
    1619             : 
    1620        3100 :     node->RemoveInput(arity + 1);
    1621        3100 :     node->InsertInput(graph()->zone(), 0, jsgraph()->Constant(code));
    1622        3100 :     node->InsertInput(graph()->zone(), 2, new_target);
    1623        3100 :     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
    1624        3100 :     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
    1625        3100 :     node->InsertInput(graph()->zone(), 5, jsgraph()->UndefinedConstant());
    1626        3100 :     NodeProperties::ChangeOp(
    1627             :         node,
    1628        6200 :         common()->Call(Linkage::GetStubCallDescriptor(
    1629        3100 :             graph()->zone(), ConstructStubDescriptor{}, 1 + arity, flags)));
    1630             : 
    1631             :     return Changed(node);
    1632             :   }
    1633             : 
    1634             :   return NoChange();
    1635             : }
    1636             : 
    1637         374 : Reduction JSTypedLowering::ReduceJSCallForwardVarargs(Node* node) {
    1638             :   DCHECK_EQ(IrOpcode::kJSCallForwardVarargs, node->opcode());
    1639         374 :   CallForwardVarargsParameters p = CallForwardVarargsParametersOf(node->op());
    1640             :   DCHECK_LE(2u, p.arity());
    1641         374 :   int const arity = static_cast<int>(p.arity() - 2);
    1642         374 :   int const start_index = static_cast<int>(p.start_index());
    1643         374 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1644         374 :   Type target_type = NodeProperties::GetType(target);
    1645             : 
    1646             :   // Check if {target} is a JSFunction.
    1647         374 :   if (target_type.Is(Type::Function())) {
    1648             :     // Compute flags for the call.
    1649             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    1650             :     // Patch {node} to an indirect call via CallFunctionForwardVarargs.
    1651         299 :     Callable callable = CodeFactory::CallFunctionForwardVarargs(isolate());
    1652         598 :     node->InsertInput(graph()->zone(), 0,
    1653         299 :                       jsgraph()->HeapConstant(callable.code()));
    1654         299 :     node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(arity));
    1655         299 :     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(start_index));
    1656         299 :     NodeProperties::ChangeOp(
    1657         897 :         node, common()->Call(Linkage::GetStubCallDescriptor(
    1658         598 :                   graph()->zone(), callable.descriptor(), arity + 1, flags)));
    1659             :     return Changed(node);
    1660             :   }
    1661             : 
    1662             :   return NoChange();
    1663             : }
    1664             : 
    1665      489464 : Reduction JSTypedLowering::ReduceJSCall(Node* node) {
    1666             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1667      489464 :   CallParameters const& p = CallParametersOf(node->op());
    1668      489465 :   int arity = static_cast<int>(p.arity() - 2);
    1669             :   ConvertReceiverMode convert_mode = p.convert_mode();
    1670      489465 :   Node* target = NodeProperties::GetValueInput(node, 0);
    1671      489465 :   Type target_type = NodeProperties::GetType(target);
    1672      489465 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1673      489465 :   Type receiver_type = NodeProperties::GetType(receiver);
    1674      489465 :   Node* effect = NodeProperties::GetEffectInput(node);
    1675      489464 :   Node* control = NodeProperties::GetControlInput(node);
    1676             : 
    1677             :   // Try to infer receiver {convert_mode} from {receiver} type.
    1678      489464 :   if (receiver_type.Is(Type::NullOrUndefined())) {
    1679             :     convert_mode = ConvertReceiverMode::kNullOrUndefined;
    1680      159557 :   } else if (!receiver_type.Maybe(Type::NullOrUndefined())) {
    1681             :     convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
    1682             :   }
    1683             : 
    1684             :   // Check if {target} is a known JSFunction.
    1685      517780 :   if (target_type.IsHeapConstant() &&
    1686       28316 :       target_type.AsHeapConstant()->Ref().IsJSFunction()) {
    1687       28089 :     JSFunctionRef function = target_type.AsHeapConstant()->Ref().AsJSFunction();
    1688       28089 :     SharedFunctionInfoRef shared = function.shared();
    1689             : 
    1690       28089 :     if (shared.HasBreakInfo()) {
    1691             :       // Do not inline the call if we need to check whether to break at entry.
    1692             :       return NoChange();
    1693             :     }
    1694             : 
    1695             :     // Class constructors are callable, but [[Call]] will raise an exception.
    1696             :     // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
    1697       56142 :     if (IsClassConstructor(shared.kind())) return NoChange();
    1698             : 
    1699             :     // Check if we need to convert the {receiver}, but bailout if it would
    1700             :     // require data from a foreign native context.
    1701       73566 :     if (is_sloppy(shared.language_mode()) && !shared.native() &&
    1702             :         !receiver_type.Is(Type::Receiver())) {
    1703       17374 :       if (!function.native_context().equals(broker()->native_context())) {
    1704             :         return NoChange();
    1705             :       }
    1706             :       Node* global_proxy =
    1707       17374 :           jsgraph()->Constant(function.native_context().global_proxy_object());
    1708             :       receiver = effect =
    1709       17374 :           graph()->NewNode(simplified()->ConvertReceiver(convert_mode),
    1710             :                            receiver, global_proxy, effect, control);
    1711       17374 :       NodeProperties::ReplaceValueInput(node, receiver, 1);
    1712             :     }
    1713             : 
    1714             :     // Load the context from the {target}.
    1715       28070 :     Node* context = effect = graph()->NewNode(
    1716       56140 :         simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
    1717             :         effect, control);
    1718       28070 :     NodeProperties::ReplaceContextInput(node, context);
    1719             : 
    1720             :     // Update the effect dependency for the {node}.
    1721       28070 :     NodeProperties::ReplaceEffectInput(node, effect);
    1722             : 
    1723             :     // Compute flags for the call.
    1724             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    1725       28070 :     Node* new_target = jsgraph()->UndefinedConstant();
    1726             : 
    1727       28070 :     if (NeedsArgumentAdaptorFrame(shared, arity)) {
    1728             :       // Check if it's safe to skip the arguments adaptor for {shared},
    1729             :       // that is whether the target function anyways cannot observe the
    1730             :       // actual arguments. Details can be found in this document at
    1731             :       // https://bit.ly/v8-faster-calls-with-arguments-mismatch and
    1732             :       // on the tracking bug at https://crbug.com/v8/8895
    1733        4073 :       if (shared.is_safe_to_skip_arguments_adaptor()) {
    1734             :         // Currently we only support skipping arguments adaptor frames
    1735             :         // for strict mode functions, since there's Function.arguments
    1736             :         // legacy accessor, which is still available in sloppy mode.
    1737             :         DCHECK_EQ(LanguageMode::kStrict, shared.language_mode());
    1738             : 
    1739             :         // Massage the arguments to match the expected number of arguments.
    1740          52 :         int expected_argument_count = shared.internal_formal_parameter_count();
    1741         150 :         for (; arity > expected_argument_count; --arity) {
    1742          49 :           node->RemoveInput(arity + 1);
    1743             :         }
    1744          58 :         for (; arity < expected_argument_count; ++arity) {
    1745           3 :           node->InsertInput(graph()->zone(), arity + 2,
    1746           3 :                             jsgraph()->UndefinedConstant());
    1747             :         }
    1748             : 
    1749             :         // Patch {node} to a direct call.
    1750          52 :         node->InsertInput(graph()->zone(), arity + 2, new_target);
    1751          52 :         node->InsertInput(graph()->zone(), arity + 3,
    1752          52 :                           jsgraph()->Constant(arity));
    1753          52 :         NodeProperties::ChangeOp(node,
    1754          52 :                                  common()->Call(Linkage::GetJSCallDescriptor(
    1755             :                                      graph()->zone(), false, 1 + arity,
    1756          52 :                                      flags | CallDescriptor::kCanUseRoots)));
    1757             :       } else {
    1758             :         // Patch {node} to an indirect call via the ArgumentsAdaptorTrampoline.
    1759        4021 :         Callable callable = CodeFactory::ArgumentAdaptor(isolate());
    1760        8042 :         node->InsertInput(graph()->zone(), 0,
    1761        4021 :                           jsgraph()->HeapConstant(callable.code()));
    1762        4021 :         node->InsertInput(graph()->zone(), 2, new_target);
    1763        4021 :         node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
    1764        4021 :         node->InsertInput(
    1765             :             graph()->zone(), 4,
    1766        8042 :             jsgraph()->Constant(shared.internal_formal_parameter_count()));
    1767        4021 :         NodeProperties::ChangeOp(
    1768             :             node,
    1769       12063 :             common()->Call(Linkage::GetStubCallDescriptor(
    1770        8042 :                 graph()->zone(), callable.descriptor(), 1 + arity, flags)));
    1771             :       }
    1772       33061 :     } else if (shared.HasBuiltinId() &&
    1773        9064 :                Builtins::HasCppImplementation(shared.builtin_id())) {
    1774             :       // Patch {node} to a direct CEntry call.
    1775        2739 :       ReduceBuiltin(jsgraph(), node, shared.builtin_id(), arity, flags);
    1776       27583 :     } else if (shared.HasBuiltinId() &&
    1777        6325 :                Builtins::KindOf(shared.builtin_id()) == Builtins::TFJ) {
    1778             :       // Patch {node} to a direct code object call.
    1779             :       Callable callable = Builtins::CallableFor(
    1780        6325 :           isolate(), static_cast<Builtins::Name>(shared.builtin_id()));
    1781             :       CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    1782             : 
    1783             :       const CallInterfaceDescriptor& descriptor = callable.descriptor();
    1784       12650 :       auto call_descriptor = Linkage::GetStubCallDescriptor(
    1785        6325 :           graph()->zone(), descriptor, 1 + arity, flags);
    1786        6325 :       Node* stub_code = jsgraph()->HeapConstant(callable.code());
    1787        6325 :       node->InsertInput(graph()->zone(), 0, stub_code);  // Code object.
    1788        6325 :       node->InsertInput(graph()->zone(), 2, new_target);
    1789        6325 :       node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
    1790        6325 :       NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
    1791             :     } else {
    1792             :       // Patch {node} to a direct call.
    1793       14933 :       node->InsertInput(graph()->zone(), arity + 2, new_target);
    1794       14933 :       node->InsertInput(graph()->zone(), arity + 3, jsgraph()->Constant(arity));
    1795       14933 :       NodeProperties::ChangeOp(node,
    1796       14933 :                                common()->Call(Linkage::GetJSCallDescriptor(
    1797             :                                    graph()->zone(), false, 1 + arity,
    1798       14933 :                                    flags | CallDescriptor::kCanUseRoots)));
    1799             :     }
    1800             :     return Changed(node);
    1801             :   }
    1802             : 
    1803             :   // Check if {target} is a JSFunction.
    1804      461375 :   if (target_type.Is(Type::Function())) {
    1805             :     // Compute flags for the call.
    1806             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    1807             :     // Patch {node} to an indirect call via the CallFunction builtin.
    1808       22847 :     Callable callable = CodeFactory::CallFunction(isolate(), convert_mode);
    1809       45696 :     node->InsertInput(graph()->zone(), 0,
    1810       22848 :                       jsgraph()->HeapConstant(callable.code()));
    1811       22848 :     node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(arity));
    1812       22847 :     NodeProperties::ChangeOp(
    1813       68542 :         node, common()->Call(Linkage::GetStubCallDescriptor(
    1814       45693 :                   graph()->zone(), callable.descriptor(), 1 + arity, flags)));
    1815             :     return Changed(node);
    1816             :   }
    1817             : 
    1818             :   // Maybe we did at least learn something about the {receiver}.
    1819      438528 :   if (p.convert_mode() != convert_mode) {
    1820      133568 :     NodeProperties::ChangeOp(
    1821             :         node, javascript()->Call(p.arity(), p.frequency(), p.feedback(),
    1822      133568 :                                  convert_mode, p.speculation_mode()));
    1823             :     return Changed(node);
    1824             :   }
    1825             : 
    1826             :   return NoChange();
    1827             : }
    1828             : 
    1829        1548 : Reduction JSTypedLowering::ReduceJSForInNext(Node* node) {
    1830             :   DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode());
    1831        1548 :   ForInMode const mode = ForInModeOf(node->op());
    1832        1548 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1833        1548 :   Node* cache_array = NodeProperties::GetValueInput(node, 1);
    1834        1548 :   Node* cache_type = NodeProperties::GetValueInput(node, 2);
    1835        1548 :   Node* index = NodeProperties::GetValueInput(node, 3);
    1836        1548 :   Node* context = NodeProperties::GetContextInput(node);
    1837        1548 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    1838        1548 :   Node* effect = NodeProperties::GetEffectInput(node);
    1839        1548 :   Node* control = NodeProperties::GetControlInput(node);
    1840             : 
    1841             :   // Load the map of the {receiver}.
    1842             :   Node* receiver_map = effect =
    1843        3096 :       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
    1844             :                        receiver, effect, control);
    1845             : 
    1846        1548 :   switch (mode) {
    1847             :     case ForInMode::kUseEnumCacheKeys:
    1848             :     case ForInMode::kUseEnumCacheKeysAndIndices: {
    1849             :       // Ensure that the expected map still matches that of the {receiver}.
    1850         983 :       Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
    1851             :                                      receiver_map, cache_type);
    1852             :       effect =
    1853        1966 :           graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongMap),
    1854             :                            check, effect, control);
    1855             : 
    1856             :       // Since the change to LoadElement() below is effectful, we connect
    1857             :       // node to all effect uses.
    1858             :       ReplaceWithValue(node, node, node, control);
    1859             : 
    1860             :       // Morph the {node} into a LoadElement.
    1861         983 :       node->ReplaceInput(0, cache_array);
    1862         983 :       node->ReplaceInput(1, index);
    1863         983 :       node->ReplaceInput(2, effect);
    1864         983 :       node->ReplaceInput(3, control);
    1865         983 :       node->TrimInputCount(4);
    1866         983 :       NodeProperties::ChangeOp(
    1867             :           node,
    1868        1966 :           simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()));
    1869             :       NodeProperties::SetType(node, Type::InternalizedString());
    1870             :       break;
    1871             :     }
    1872             :     case ForInMode::kGeneric: {
    1873             :       // Load the next {key} from the {cache_array}.
    1874         565 :       Node* key = effect = graph()->NewNode(
    1875        1130 :           simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
    1876             :           cache_array, index, effect, control);
    1877             : 
    1878             :       // Check if the expected map still matches that of the {receiver}.
    1879         565 :       Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
    1880             :                                      receiver_map, cache_type);
    1881             :       Node* branch =
    1882         565 :           graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    1883             : 
    1884         565 :       Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1885             :       Node* etrue;
    1886             :       Node* vtrue;
    1887             :       {
    1888             :         // Don't need filtering since expected map still matches that of the
    1889             :         // {receiver}.
    1890             :         etrue = effect;
    1891             :         vtrue = key;
    1892             :       }
    1893             : 
    1894         565 :       Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    1895             :       Node* efalse;
    1896             :       Node* vfalse;
    1897             :       {
    1898             :         // Filter the {key} to check if it's still a valid property of the
    1899             :         // {receiver} (does the ToName conversion implicitly).
    1900             :         Callable const callable =
    1901         565 :             Builtins::CallableFor(isolate(), Builtins::kForInFilter);
    1902         565 :         auto call_descriptor = Linkage::GetStubCallDescriptor(
    1903         565 :             graph()->zone(), callable.descriptor(),
    1904             :             callable.descriptor().GetStackParameterCount(),
    1905         565 :             CallDescriptor::kNeedsFrameState);
    1906             :         vfalse = efalse = if_false =
    1907        1130 :             graph()->NewNode(common()->Call(call_descriptor),
    1908             :                              jsgraph()->HeapConstant(callable.code()), key,
    1909             :                              receiver, context, frame_state, effect, if_false);
    1910             : 
    1911             :         // Update potential {IfException} uses of {node} to point to the above
    1912             :         // ForInFilter stub call node instead.
    1913         565 :         Node* if_exception = nullptr;
    1914         565 :         if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
    1915         162 :           if_false = graph()->NewNode(common()->IfSuccess(), vfalse);
    1916         162 :           NodeProperties::ReplaceControlInput(if_exception, vfalse);
    1917         162 :           NodeProperties::ReplaceEffectInput(if_exception, efalse);
    1918         162 :           Revisit(if_exception);
    1919             :         }
    1920             :       }
    1921             : 
    1922         565 :       control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    1923         565 :       effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    1924             :       ReplaceWithValue(node, node, effect, control);
    1925             : 
    1926             :       // Morph the {node} into a Phi.
    1927         565 :       node->ReplaceInput(0, vtrue);
    1928         565 :       node->ReplaceInput(1, vfalse);
    1929         565 :       node->ReplaceInput(2, control);
    1930         565 :       node->TrimInputCount(3);
    1931         565 :       NodeProperties::ChangeOp(
    1932         565 :           node, common()->Phi(MachineRepresentation::kTagged, 2));
    1933             :     }
    1934             :   }
    1935             : 
    1936        1548 :   return Changed(node);
    1937             : }
    1938             : 
    1939        1371 : Reduction JSTypedLowering::ReduceJSForInPrepare(Node* node) {
    1940             :   DCHECK_EQ(IrOpcode::kJSForInPrepare, node->opcode());
    1941        1371 :   ForInMode const mode = ForInModeOf(node->op());
    1942        1371 :   Node* enumerator = NodeProperties::GetValueInput(node, 0);
    1943        1371 :   Node* effect = NodeProperties::GetEffectInput(node);
    1944        1371 :   Node* control = NodeProperties::GetControlInput(node);
    1945             :   Node* cache_type = enumerator;
    1946             :   Node* cache_array = nullptr;
    1947             :   Node* cache_length = nullptr;
    1948             : 
    1949        1371 :   switch (mode) {
    1950             :     case ForInMode::kUseEnumCacheKeys:
    1951             :     case ForInMode::kUseEnumCacheKeysAndIndices: {
    1952             :       // Check that the {enumerator} is a Map.
    1953        2844 :       effect = graph()->NewNode(
    1954             :           simplified()->CheckMaps(CheckMapsFlag::kNone,
    1955             :                                   ZoneHandleSet<Map>(factory()->meta_map())),
    1956             :           enumerator, effect, control);
    1957             : 
    1958             :       // Load the enum cache from the {enumerator} map.
    1959         948 :       Node* descriptor_array = effect = graph()->NewNode(
    1960        1896 :           simplified()->LoadField(AccessBuilder::ForMapDescriptors()),
    1961             :           enumerator, effect, control);
    1962         948 :       Node* enum_cache = effect = graph()->NewNode(
    1963        1896 :           simplified()->LoadField(AccessBuilder::ForDescriptorArrayEnumCache()),
    1964             :           descriptor_array, effect, control);
    1965         948 :       cache_array = effect = graph()->NewNode(
    1966        1896 :           simplified()->LoadField(AccessBuilder::ForEnumCacheKeys()),
    1967             :           enum_cache, effect, control);
    1968             : 
    1969             :       // Load the enum length of the {enumerator} map.
    1970         948 :       Node* bit_field3 = effect = graph()->NewNode(
    1971        1896 :           simplified()->LoadField(AccessBuilder::ForMapBitField3()), enumerator,
    1972             :           effect, control);
    1973             :       STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
    1974             :       cache_length =
    1975         948 :           graph()->NewNode(simplified()->NumberBitwiseAnd(), bit_field3,
    1976             :                            jsgraph()->Constant(Map::EnumLengthBits::kMask));
    1977         948 :       break;
    1978             :     }
    1979             :     case ForInMode::kGeneric: {
    1980             :       // Check if the {enumerator} is a Map or a FixedArray.
    1981         846 :       Node* check = effect = graph()->NewNode(
    1982             :           simplified()->CompareMaps(ZoneHandleSet<Map>(factory()->meta_map())),
    1983             :           enumerator, effect, control);
    1984             :       Node* branch =
    1985         423 :           graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    1986             : 
    1987         423 :       Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1988             :       Node* etrue = effect;
    1989             :       Node* cache_array_true;
    1990             :       Node* cache_length_true;
    1991             :       {
    1992             :         // Load the enum cache from the {enumerator} map.
    1993         423 :         Node* descriptor_array = etrue = graph()->NewNode(
    1994         846 :             simplified()->LoadField(AccessBuilder::ForMapDescriptors()),
    1995             :             enumerator, etrue, if_true);
    1996             :         Node* enum_cache = etrue =
    1997         423 :             graph()->NewNode(simplified()->LoadField(
    1998         846 :                                  AccessBuilder::ForDescriptorArrayEnumCache()),
    1999             :                              descriptor_array, etrue, if_true);
    2000         423 :         cache_array_true = etrue = graph()->NewNode(
    2001         846 :             simplified()->LoadField(AccessBuilder::ForEnumCacheKeys()),
    2002             :             enum_cache, etrue, if_true);
    2003             : 
    2004             :         // Load the enum length of the {enumerator} map.
    2005         423 :         Node* bit_field3 = etrue = graph()->NewNode(
    2006         846 :             simplified()->LoadField(AccessBuilder::ForMapBitField3()),
    2007             :             enumerator, etrue, if_true);
    2008             :         STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
    2009             :         cache_length_true =
    2010         423 :             graph()->NewNode(simplified()->NumberBitwiseAnd(), bit_field3,
    2011             :                              jsgraph()->Constant(Map::EnumLengthBits::kMask));
    2012             :       }
    2013             : 
    2014         423 :       Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    2015             :       Node* efalse = effect;
    2016             :       Node* cache_array_false;
    2017             :       Node* cache_length_false;
    2018             :       {
    2019             :         // The {enumerator} is the FixedArray with the keys to iterate.
    2020             :         cache_array_false = enumerator;
    2021         423 :         cache_length_false = efalse = graph()->NewNode(
    2022         846 :             simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
    2023             :             cache_array_false, efalse, if_false);
    2024             :       }
    2025             : 
    2026             :       // Rewrite the uses of the {node}.
    2027         423 :       control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    2028         423 :       effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    2029             :       cache_array =
    2030         423 :           graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2031             :                            cache_array_true, cache_array_false, control);
    2032             :       cache_length =
    2033         423 :           graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2034             :                            cache_length_true, cache_length_false, control);
    2035         423 :       break;
    2036             :     }
    2037             :   }
    2038             : 
    2039             :   // Update the uses of {node}.
    2040       23307 :   for (Edge edge : node->use_edges()) {
    2041             :     Node* const user = edge.from();
    2042       10968 :     if (NodeProperties::IsEffectEdge(edge)) {
    2043        1371 :       edge.UpdateTo(effect);
    2044             :       Revisit(user);
    2045        9597 :     } else if (NodeProperties::IsControlEdge(edge)) {
    2046        5484 :       edge.UpdateTo(control);
    2047             :       Revisit(user);
    2048             :     } else {
    2049             :       DCHECK(NodeProperties::IsValueEdge(edge));
    2050        4113 :       switch (ProjectionIndexOf(user->op())) {
    2051             :         case 0:
    2052             :           Replace(user, cache_type);
    2053             :           break;
    2054             :         case 1:
    2055             :           Replace(user, cache_array);
    2056             :           break;
    2057             :         case 2:
    2058             :           Replace(user, cache_length);
    2059             :           break;
    2060             :         default:
    2061           0 :           UNREACHABLE();
    2062             :       }
    2063             :     }
    2064             :   }
    2065        1371 :   node->Kill();
    2066        1371 :   return Replace(effect);
    2067             : }
    2068             : 
    2069       29935 : Reduction JSTypedLowering::ReduceJSLoadMessage(Node* node) {
    2070             :   DCHECK_EQ(IrOpcode::kJSLoadMessage, node->opcode());
    2071             :   ExternalReference const ref =
    2072       29935 :       ExternalReference::address_of_pending_message_obj(isolate());
    2073       29935 :   node->ReplaceInput(0, jsgraph()->ExternalConstant(ref));
    2074       29935 :   NodeProperties::ChangeOp(node, simplified()->LoadMessage());
    2075       29935 :   return Changed(node);
    2076             : }
    2077             : 
    2078       29937 : Reduction JSTypedLowering::ReduceJSStoreMessage(Node* node) {
    2079             :   DCHECK_EQ(IrOpcode::kJSStoreMessage, node->opcode());
    2080             :   ExternalReference const ref =
    2081       29937 :       ExternalReference::address_of_pending_message_obj(isolate());
    2082       29937 :   Node* value = NodeProperties::GetValueInput(node, 0);
    2083       29937 :   node->ReplaceInput(0, jsgraph()->ExternalConstant(ref));
    2084       29937 :   node->ReplaceInput(1, value);
    2085       29937 :   NodeProperties::ChangeOp(node, simplified()->StoreMessage());
    2086       29937 :   return Changed(node);
    2087             : }
    2088             : 
    2089        6150 : Reduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
    2090             :   DCHECK_EQ(IrOpcode::kJSGeneratorStore, node->opcode());
    2091        6150 :   Node* generator = NodeProperties::GetValueInput(node, 0);
    2092        6150 :   Node* continuation = NodeProperties::GetValueInput(node, 1);
    2093        6150 :   Node* offset = NodeProperties::GetValueInput(node, 2);
    2094        6150 :   Node* context = NodeProperties::GetContextInput(node);
    2095        6150 :   Node* effect = NodeProperties::GetEffectInput(node);
    2096        6150 :   Node* control = NodeProperties::GetControlInput(node);
    2097        6150 :   int value_count = GeneratorStoreValueCountOf(node->op());
    2098             : 
    2099             :   FieldAccess array_field =
    2100        6150 :       AccessBuilder::ForJSGeneratorObjectParametersAndRegisters();
    2101        6150 :   FieldAccess context_field = AccessBuilder::ForJSGeneratorObjectContext();
    2102             :   FieldAccess continuation_field =
    2103        6150 :       AccessBuilder::ForJSGeneratorObjectContinuation();
    2104             :   FieldAccess input_or_debug_pos_field =
    2105        6150 :       AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
    2106             : 
    2107        6150 :   Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
    2108             :                                           generator, effect, control);
    2109             : 
    2110       55906 :   for (int i = 0; i < value_count; ++i) {
    2111       24878 :     Node* value = NodeProperties::GetValueInput(node, 3 + i);
    2112       24878 :     if (value != jsgraph()->OptimizedOutConstant()) {
    2113       16312 :       effect = graph()->NewNode(
    2114       32624 :           simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), array,
    2115             :           value, effect, control);
    2116             :     }
    2117             :   }
    2118             : 
    2119        6150 :   effect = graph()->NewNode(simplified()->StoreField(context_field), generator,
    2120             :                             context, effect, control);
    2121        6150 :   effect = graph()->NewNode(simplified()->StoreField(continuation_field),
    2122             :                             generator, continuation, effect, control);
    2123        6150 :   effect = graph()->NewNode(simplified()->StoreField(input_or_debug_pos_field),
    2124             :                             generator, offset, effect, control);
    2125             : 
    2126             :   ReplaceWithValue(node, effect, effect, control);
    2127        6150 :   return Changed(effect);
    2128             : }
    2129             : 
    2130        2004 : Reduction JSTypedLowering::ReduceJSGeneratorRestoreContinuation(Node* node) {
    2131             :   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreContinuation, node->opcode());
    2132        2004 :   Node* generator = NodeProperties::GetValueInput(node, 0);
    2133        2004 :   Node* effect = NodeProperties::GetEffectInput(node);
    2134        2004 :   Node* control = NodeProperties::GetControlInput(node);
    2135             : 
    2136             :   FieldAccess continuation_field =
    2137        2004 :       AccessBuilder::ForJSGeneratorObjectContinuation();
    2138             : 
    2139        2004 :   Node* continuation = effect = graph()->NewNode(
    2140             :       simplified()->LoadField(continuation_field), generator, effect, control);
    2141        2004 :   Node* executing = jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting);
    2142        2004 :   effect = graph()->NewNode(simplified()->StoreField(continuation_field),
    2143             :                             generator, executing, effect, control);
    2144             : 
    2145             :   ReplaceWithValue(node, continuation, effect, control);
    2146        2004 :   return Changed(continuation);
    2147             : }
    2148             : 
    2149        2004 : Reduction JSTypedLowering::ReduceJSGeneratorRestoreContext(Node* node) {
    2150             :   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreContext, node->opcode());
    2151             : 
    2152             :   const Operator* new_op =
    2153        2004 :       simplified()->LoadField(AccessBuilder::ForJSGeneratorObjectContext());
    2154             : 
    2155             :   // Mutate the node in-place.
    2156             :   DCHECK(OperatorProperties::HasContextInput(node->op()));
    2157             :   DCHECK(!OperatorProperties::HasContextInput(new_op));
    2158        2004 :   node->RemoveInput(NodeProperties::FirstContextIndex(node));
    2159             : 
    2160        2004 :   NodeProperties::ChangeOp(node, new_op);
    2161        2004 :   return Changed(node);
    2162             : }
    2163             : 
    2164       15314 : Reduction JSTypedLowering::ReduceJSGeneratorRestoreRegister(Node* node) {
    2165             :   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreRegister, node->opcode());
    2166       15314 :   Node* generator = NodeProperties::GetValueInput(node, 0);
    2167       15314 :   Node* effect = NodeProperties::GetEffectInput(node);
    2168       15314 :   Node* control = NodeProperties::GetControlInput(node);
    2169       15314 :   int index = RestoreRegisterIndexOf(node->op());
    2170             : 
    2171             :   FieldAccess array_field =
    2172       15314 :       AccessBuilder::ForJSGeneratorObjectParametersAndRegisters();
    2173       15314 :   FieldAccess element_field = AccessBuilder::ForFixedArraySlot(index);
    2174             : 
    2175       15314 :   Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
    2176             :                                           generator, effect, control);
    2177       15314 :   Node* element = effect = graph()->NewNode(
    2178             :       simplified()->LoadField(element_field), array, effect, control);
    2179       15314 :   Node* stale = jsgraph()->StaleRegisterConstant();
    2180       15314 :   effect = graph()->NewNode(simplified()->StoreField(element_field), array,
    2181             :                             stale, effect, control);
    2182             : 
    2183             :   ReplaceWithValue(node, element, effect, control);
    2184       15314 :   return Changed(element);
    2185             : }
    2186             : 
    2187        6025 : Reduction JSTypedLowering::ReduceJSGeneratorRestoreInputOrDebugPos(Node* node) {
    2188             :   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreInputOrDebugPos, node->opcode());
    2189             : 
    2190             :   FieldAccess input_or_debug_pos_field =
    2191        6025 :       AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
    2192        6025 :   const Operator* new_op = simplified()->LoadField(input_or_debug_pos_field);
    2193             : 
    2194             :   // Mutate the node in-place.
    2195             :   DCHECK(OperatorProperties::HasContextInput(node->op()));
    2196             :   DCHECK(!OperatorProperties::HasContextInput(new_op));
    2197        6025 :   node->RemoveInput(NodeProperties::FirstContextIndex(node));
    2198             : 
    2199        6025 :   NodeProperties::ChangeOp(node, new_op);
    2200        6025 :   return Changed(node);
    2201             : }
    2202             : 
    2203          87 : Reduction JSTypedLowering::ReduceObjectIsArray(Node* node) {
    2204          87 :   Node* value = NodeProperties::GetValueInput(node, 0);
    2205          87 :   Type value_type = NodeProperties::GetType(value);
    2206          87 :   Node* context = NodeProperties::GetContextInput(node);
    2207          87 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    2208          87 :   Node* effect = NodeProperties::GetEffectInput(node);
    2209          87 :   Node* control = NodeProperties::GetControlInput(node);
    2210             : 
    2211             :   // Constant-fold based on {value} type.
    2212          87 :   if (value_type.Is(Type::Array())) {
    2213          15 :     Node* value = jsgraph()->TrueConstant();
    2214             :     ReplaceWithValue(node, value);
    2215             :     return Replace(value);
    2216          72 :   } else if (!value_type.Maybe(Type::ArrayOrProxy())) {
    2217           8 :     Node* value = jsgraph()->FalseConstant();
    2218             :     ReplaceWithValue(node, value);
    2219             :     return Replace(value);
    2220             :   }
    2221             : 
    2222             :   int count = 0;
    2223             :   Node* values[5];
    2224             :   Node* effects[5];
    2225             :   Node* controls[4];
    2226             : 
    2227             :   // Check if the {value} is a Smi.
    2228          64 :   Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
    2229             :   control =
    2230          64 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    2231             : 
    2232             :   // The {value} is a Smi.
    2233         128 :   controls[count] = graph()->NewNode(common()->IfTrue(), control);
    2234          64 :   effects[count] = effect;
    2235          64 :   values[count] = jsgraph()->FalseConstant();
    2236             :   count++;
    2237             : 
    2238          64 :   control = graph()->NewNode(common()->IfFalse(), control);
    2239             : 
    2240             :   // Load the {value}s instance type.
    2241          64 :   Node* value_map = effect = graph()->NewNode(
    2242         128 :       simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
    2243          64 :   Node* value_instance_type = effect = graph()->NewNode(
    2244         128 :       simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
    2245             :       effect, control);
    2246             : 
    2247             :   // Check if the {value} is a JSArray.
    2248          64 :   check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type,
    2249             :                            jsgraph()->Constant(JS_ARRAY_TYPE));
    2250          64 :   control = graph()->NewNode(common()->Branch(), check, control);
    2251             : 
    2252             :   // The {value} is a JSArray.
    2253         128 :   controls[count] = graph()->NewNode(common()->IfTrue(), control);
    2254          64 :   effects[count] = effect;
    2255          64 :   values[count] = jsgraph()->TrueConstant();
    2256             :   count++;
    2257             : 
    2258          64 :   control = graph()->NewNode(common()->IfFalse(), control);
    2259             : 
    2260             :   // Check if the {value} is a JSProxy.
    2261          64 :   check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type,
    2262             :                            jsgraph()->Constant(JS_PROXY_TYPE));
    2263             :   control =
    2264          64 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    2265             : 
    2266             :   // The {value} is neither a JSArray nor a JSProxy.
    2267         128 :   controls[count] = graph()->NewNode(common()->IfFalse(), control);
    2268          64 :   effects[count] = effect;
    2269          64 :   values[count] = jsgraph()->FalseConstant();
    2270             :   count++;
    2271             : 
    2272          64 :   control = graph()->NewNode(common()->IfTrue(), control);
    2273             : 
    2274             :   // Let the %ArrayIsArray runtime function deal with the JSProxy {value}.
    2275             :   value = effect = control =
    2276          64 :       graph()->NewNode(javascript()->CallRuntime(Runtime::kArrayIsArray), value,
    2277             :                        context, frame_state, effect, control);
    2278             :   NodeProperties::SetType(value, Type::Boolean());
    2279             : 
    2280             :   // Update potential {IfException} uses of {node} to point to the above
    2281             :   // %ArrayIsArray runtime call node instead.
    2282          64 :   Node* on_exception = nullptr;
    2283          64 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    2284           8 :     NodeProperties::ReplaceControlInput(on_exception, control);
    2285           8 :     NodeProperties::ReplaceEffectInput(on_exception, effect);
    2286           8 :     control = graph()->NewNode(common()->IfSuccess(), control);
    2287           8 :     Revisit(on_exception);
    2288             :   }
    2289             : 
    2290             :   // The {value} is neither a JSArray nor a JSProxy.
    2291          64 :   controls[count] = control;
    2292          64 :   effects[count] = effect;
    2293          64 :   values[count] = value;
    2294             :   count++;
    2295             : 
    2296          64 :   control = graph()->NewNode(common()->Merge(count), count, controls);
    2297          64 :   effects[count] = control;
    2298          64 :   values[count] = control;
    2299          64 :   effect = graph()->NewNode(common()->EffectPhi(count), count + 1, effects);
    2300          64 :   value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
    2301          64 :                            count + 1, values);
    2302             :   ReplaceWithValue(node, value, effect, control);
    2303             :   return Replace(value);
    2304             : }
    2305             : 
    2306         193 : Reduction JSTypedLowering::ReduceJSParseInt(Node* node) {
    2307         193 :   Node* value = NodeProperties::GetValueInput(node, 0);
    2308         193 :   Type value_type = NodeProperties::GetType(value);
    2309         193 :   Node* radix = NodeProperties::GetValueInput(node, 1);
    2310         193 :   Type radix_type = NodeProperties::GetType(radix);
    2311             :   // We need kTenOrUndefined and kZeroOrUndefined because
    2312             :   // the type representing {0,10} would become the range 1-10.
    2313         618 :   if (value_type.Is(type_cache_->kSafeInteger) &&
    2314          54 :       (radix_type.Is(type_cache_->kTenOrUndefined) ||
    2315          15 :        radix_type.Is(type_cache_->kZeroOrUndefined))) {
    2316             :     // Number.parseInt(a:safe-integer) -> a
    2317             :     // Number.parseInt(a:safe-integer,b:#0\/undefined) -> a
    2318             :     // Number.parseInt(a:safe-integer,b:#10\/undefined) -> a
    2319             :     ReplaceWithValue(node, value);
    2320             :     return Replace(value);
    2321             :   }
    2322             :   return NoChange();
    2323             : }
    2324             : 
    2325        1004 : Reduction JSTypedLowering::ReduceJSResolvePromise(Node* node) {
    2326             :   DCHECK_EQ(IrOpcode::kJSResolvePromise, node->opcode());
    2327        1004 :   Node* resolution = NodeProperties::GetValueInput(node, 1);
    2328        1004 :   Type resolution_type = NodeProperties::GetType(resolution);
    2329             :   // We can strength-reduce JSResolvePromise to JSFulfillPromise
    2330             :   // if the {resolution} is known to be a primitive, as in that
    2331             :   // case we don't perform the implicit chaining (via "then").
    2332        1004 :   if (resolution_type.Is(Type::Primitive())) {
    2333             :     // JSResolvePromise(p,v:primitive) -> JSFulfillPromise(p,v)
    2334         721 :     node->RemoveInput(3);  // frame state
    2335         721 :     NodeProperties::ChangeOp(node, javascript()->FulfillPromise());
    2336             :     return Changed(node);
    2337             :   }
    2338             :   return NoChange();
    2339             : }
    2340             : 
    2341    32515730 : Reduction JSTypedLowering::Reduce(Node* node) {
    2342             :   DisallowHeapAccess no_heap_access;
    2343             : 
    2344    32515730 :   switch (node->opcode()) {
    2345             :     case IrOpcode::kJSEqual:
    2346       13454 :       return ReduceJSEqual(node);
    2347             :     case IrOpcode::kJSStrictEqual:
    2348      144700 :       return ReduceJSStrictEqual(node);
    2349             :     case IrOpcode::kJSLessThan:         // fall through
    2350             :     case IrOpcode::kJSGreaterThan:      // fall through
    2351             :     case IrOpcode::kJSLessThanOrEqual:  // fall through
    2352             :     case IrOpcode::kJSGreaterThanOrEqual:
    2353       34553 :       return ReduceJSComparison(node);
    2354             :     case IrOpcode::kJSBitwiseOr:
    2355             :     case IrOpcode::kJSBitwiseXor:
    2356             :     case IrOpcode::kJSBitwiseAnd:
    2357       19453 :       return ReduceInt32Binop(node);
    2358             :     case IrOpcode::kJSShiftLeft:
    2359             :     case IrOpcode::kJSShiftRight:
    2360        5537 :       return ReduceUI32Shift(node, kSigned);
    2361             :     case IrOpcode::kJSShiftRightLogical:
    2362        2423 :       return ReduceUI32Shift(node, kUnsigned);
    2363             :     case IrOpcode::kJSAdd:
    2364       86368 :       return ReduceJSAdd(node);
    2365             :     case IrOpcode::kJSSubtract:
    2366             :     case IrOpcode::kJSMultiply:
    2367             :     case IrOpcode::kJSDivide:
    2368             :     case IrOpcode::kJSModulus:
    2369             :     case IrOpcode::kJSExponentiate:
    2370       26279 :       return ReduceNumberBinop(node);
    2371             :     case IrOpcode::kJSBitwiseNot:
    2372         164 :       return ReduceJSBitwiseNot(node);
    2373             :     case IrOpcode::kJSDecrement:
    2374        2173 :       return ReduceJSDecrement(node);
    2375             :     case IrOpcode::kJSIncrement:
    2376       19160 :       return ReduceJSIncrement(node);
    2377             :     case IrOpcode::kJSNegate:
    2378        4035 :       return ReduceJSNegate(node);
    2379             :     case IrOpcode::kJSHasInPrototypeChain:
    2380         833 :       return ReduceJSHasInPrototypeChain(node);
    2381             :     case IrOpcode::kJSOrdinaryHasInstance:
    2382         110 :       return ReduceJSOrdinaryHasInstance(node);
    2383             :     case IrOpcode::kJSToLength:
    2384          36 :       return ReduceJSToLength(node);
    2385             :     case IrOpcode::kJSToName:
    2386        1148 :       return ReduceJSToName(node);
    2387             :     case IrOpcode::kJSToNumber:
    2388             :     case IrOpcode::kJSToNumberConvertBigInt:
    2389        9806 :       return ReduceJSToNumber(node);
    2390             :     case IrOpcode::kJSToNumeric:
    2391        4568 :       return ReduceJSToNumeric(node);
    2392             :     case IrOpcode::kJSToString:
    2393        2166 :       return ReduceJSToString(node);
    2394             :     case IrOpcode::kJSToObject:
    2395        1935 :       return ReduceJSToObject(node);
    2396             :     case IrOpcode::kJSLoadNamed:
    2397      423882 :       return ReduceJSLoadNamed(node);
    2398             :     case IrOpcode::kJSLoadContext:
    2399      302264 :       return ReduceJSLoadContext(node);
    2400             :     case IrOpcode::kJSStoreContext:
    2401      450771 :       return ReduceJSStoreContext(node);
    2402             :     case IrOpcode::kJSLoadModule:
    2403         294 :       return ReduceJSLoadModule(node);
    2404             :     case IrOpcode::kJSStoreModule:
    2405        6948 :       return ReduceJSStoreModule(node);
    2406             :     case IrOpcode::kJSConstructForwardVarargs:
    2407         469 :       return ReduceJSConstructForwardVarargs(node);
    2408             :     case IrOpcode::kJSConstruct:
    2409       35545 :       return ReduceJSConstruct(node);
    2410             :     case IrOpcode::kJSCallForwardVarargs:
    2411         374 :       return ReduceJSCallForwardVarargs(node);
    2412             :     case IrOpcode::kJSCall:
    2413      489463 :       return ReduceJSCall(node);
    2414             :     case IrOpcode::kJSForInPrepare:
    2415        1371 :       return ReduceJSForInPrepare(node);
    2416             :     case IrOpcode::kJSForInNext:
    2417        1548 :       return ReduceJSForInNext(node);
    2418             :     case IrOpcode::kJSLoadMessage:
    2419       29935 :       return ReduceJSLoadMessage(node);
    2420             :     case IrOpcode::kJSStoreMessage:
    2421       29937 :       return ReduceJSStoreMessage(node);
    2422             :     case IrOpcode::kJSGeneratorStore:
    2423        6150 :       return ReduceJSGeneratorStore(node);
    2424             :     case IrOpcode::kJSGeneratorRestoreContinuation:
    2425        2004 :       return ReduceJSGeneratorRestoreContinuation(node);
    2426             :     case IrOpcode::kJSGeneratorRestoreContext:
    2427        2004 :       return ReduceJSGeneratorRestoreContext(node);
    2428             :     case IrOpcode::kJSGeneratorRestoreRegister:
    2429       15314 :       return ReduceJSGeneratorRestoreRegister(node);
    2430             :     case IrOpcode::kJSGeneratorRestoreInputOrDebugPos:
    2431        6025 :       return ReduceJSGeneratorRestoreInputOrDebugPos(node);
    2432             :     case IrOpcode::kJSObjectIsArray:
    2433          87 :       return ReduceObjectIsArray(node);
    2434             :     case IrOpcode::kJSParseInt:
    2435         193 :       return ReduceJSParseInt(node);
    2436             :     case IrOpcode::kJSResolvePromise:
    2437        1004 :       return ReduceJSResolvePromise(node);
    2438             :     default:
    2439             :       break;
    2440             :   }
    2441             :   return NoChange();
    2442             : }
    2443             : 
    2444             : 
    2445           0 : Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
    2446             : 
    2447             : 
    2448           0 : Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); }
    2449             : 
    2450             : 
    2451           0 : Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); }
    2452             : 
    2453             : 
    2454           0 : JSOperatorBuilder* JSTypedLowering::javascript() const {
    2455           0 :   return jsgraph()->javascript();
    2456             : }
    2457             : 
    2458             : 
    2459           0 : CommonOperatorBuilder* JSTypedLowering::common() const {
    2460           0 :   return jsgraph()->common();
    2461             : }
    2462             : 
    2463           0 : SimplifiedOperatorBuilder* JSTypedLowering::simplified() const {
    2464           0 :   return jsgraph()->simplified();
    2465             : }
    2466             : 
    2467             : }  // namespace compiler
    2468             : }  // namespace internal
    2469      122004 : }  // namespace v8

Generated by: LCOV version 1.10