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

Generated by: LCOV version 1.10