LCOV - code coverage report
Current view: top level - src/compiler - js-typed-lowering.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1059 1078 98.2 %
Date: 2019-04-19 Functions: 77 83 92.8 %

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

Generated by: LCOV version 1.10