LCOV - code coverage report
Current view: top level - src/compiler - js-typed-lowering.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1035 1045 99.0 %
Date: 2019-01-20 Functions: 78 84 92.9 %

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

Generated by: LCOV version 1.10