LCOV - code coverage report
Current view: top level - src/compiler - js-call-reducer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2743 2834 96.8 %
Date: 2019-01-20 Functions: 112 120 93.3 %

          Line data    Source code
       1             : // Copyright 2015 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-call-reducer.h"
       6             : 
       7             : #include "src/api-inl.h"
       8             : #include "src/builtins/builtins-promise.h"
       9             : #include "src/builtins/builtins-utils.h"
      10             : #include "src/code-factory.h"
      11             : #include "src/compiler/access-builder.h"
      12             : #include "src/compiler/access-info.h"
      13             : #include "src/compiler/allocation-builder.h"
      14             : #include "src/compiler/compilation-dependencies.h"
      15             : #include "src/compiler/js-graph.h"
      16             : #include "src/compiler/linkage.h"
      17             : #include "src/compiler/node-matchers.h"
      18             : #include "src/compiler/property-access-builder.h"
      19             : #include "src/compiler/simplified-operator.h"
      20             : #include "src/compiler/type-cache.h"
      21             : #include "src/feedback-vector-inl.h"
      22             : #include "src/ic/call-optimization.h"
      23             : #include "src/objects-inl.h"
      24             : #include "src/objects/arguments-inl.h"
      25             : #include "src/objects/js-array-buffer-inl.h"
      26             : #include "src/objects/js-array-inl.h"
      27             : #include "src/objects/js-objects.h"
      28             : #include "src/vector-slot-pair.h"
      29             : 
      30             : namespace v8 {
      31             : namespace internal {
      32             : namespace compiler {
      33             : 
      34       91618 : Reduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) {
      35       45818 :   CallParameters const& p = CallParametersOf(node->op());
      36       45818 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
      37             :     return NoChange();
      38             :   }
      39       91596 :   if (node->op()->ValueInputCount() < 3) {
      40           2 :     Node* value = jsgraph()->NaNConstant();
      41       45798 :     ReplaceWithValue(node, value);
      42             :     return Replace(value);
      43             :   }
      44             : 
      45       45796 :   Node* effect = NodeProperties::GetEffectInput(node);
      46       45796 :   Node* control = NodeProperties::GetControlInput(node);
      47       45796 :   Node* input = NodeProperties::GetValueInput(node, 2);
      48             : 
      49             :   input = effect =
      50             :       graph()->NewNode(simplified()->SpeculativeToNumber(
      51       45796 :                            NumberOperationHint::kNumberOrOddball, p.feedback()),
      52       45796 :                        input, effect, control);
      53             :   Node* value = graph()->NewNode(op, input);
      54             :   ReplaceWithValue(node, value, effect);
      55             :   return Replace(value);
      56             : }
      57             : 
      58        3048 : Reduction JSCallReducer::ReduceMathBinary(Node* node, const Operator* op) {
      59        1021 :   CallParameters const& p = CallParametersOf(node->op());
      60        1021 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
      61             :     return NoChange();
      62             :   }
      63        2022 :   if (node->op()->ValueInputCount() < 3) {
      64           7 :     Node* value = jsgraph()->NaNConstant();
      65        1011 :     ReplaceWithValue(node, value);
      66             :     return Replace(value);
      67             :   }
      68        1004 :   Node* effect = NodeProperties::GetEffectInput(node);
      69        1004 :   Node* control = NodeProperties::GetControlInput(node);
      70             : 
      71        1004 :   Node* left = NodeProperties::GetValueInput(node, 2);
      72        1004 :   Node* right = node->op()->ValueInputCount() > 3
      73             :                     ? NodeProperties::GetValueInput(node, 3)
      74        1009 :                     : jsgraph()->NaNConstant();
      75             :   left = effect =
      76             :       graph()->NewNode(simplified()->SpeculativeToNumber(
      77        1004 :                            NumberOperationHint::kNumberOrOddball, p.feedback()),
      78        1004 :                        left, effect, control);
      79             :   right = effect =
      80             :       graph()->NewNode(simplified()->SpeculativeToNumber(
      81             :                            NumberOperationHint::kNumberOrOddball, p.feedback()),
      82        1004 :                        right, effect, control);
      83             :   Node* value = graph()->NewNode(op, left, right);
      84             :   ReplaceWithValue(node, value, effect);
      85             :   return Replace(value);
      86             : }
      87             : 
      88             : // ES6 section 20.2.2.19 Math.imul ( x, y )
      89        2598 : Reduction JSCallReducer::ReduceMathImul(Node* node) {
      90         870 :   CallParameters const& p = CallParametersOf(node->op());
      91         870 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
      92             :     return NoChange();
      93             :   }
      94        1720 :   if (node->op()->ValueInputCount() < 3) {
      95           8 :     Node* value = jsgraph()->ZeroConstant();
      96         860 :     ReplaceWithValue(node, value);
      97             :     return Replace(value);
      98             :   }
      99         852 :   Node* left = NodeProperties::GetValueInput(node, 2);
     100         852 :   Node* right = node->op()->ValueInputCount() > 3
     101             :                     ? NodeProperties::GetValueInput(node, 3)
     102         860 :                     : jsgraph()->ZeroConstant();
     103         852 :   Node* effect = NodeProperties::GetEffectInput(node);
     104         852 :   Node* control = NodeProperties::GetControlInput(node);
     105             : 
     106             :   left = effect =
     107             :       graph()->NewNode(simplified()->SpeculativeToNumber(
     108         852 :                            NumberOperationHint::kNumberOrOddball, p.feedback()),
     109         852 :                        left, effect, control);
     110             :   right = effect =
     111             :       graph()->NewNode(simplified()->SpeculativeToNumber(
     112             :                            NumberOperationHint::kNumberOrOddball, p.feedback()),
     113         852 :                        right, effect, control);
     114         852 :   left = graph()->NewNode(simplified()->NumberToUint32(), left);
     115         852 :   right = graph()->NewNode(simplified()->NumberToUint32(), right);
     116         852 :   Node* value = graph()->NewNode(simplified()->NumberImul(), left, right);
     117             :   ReplaceWithValue(node, value, effect);
     118             :   return Replace(value);
     119             : }
     120             : 
     121             : // ES6 section 20.2.2.11 Math.clz32 ( x )
     122         118 : Reduction JSCallReducer::ReduceMathClz32(Node* node) {
     123          62 :   CallParameters const& p = CallParametersOf(node->op());
     124          62 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
     125             :     return NoChange();
     126             :   }
     127         110 :   if (node->op()->ValueInputCount() < 3) {
     128           1 :     Node* value = jsgraph()->Constant(32);
     129          55 :     ReplaceWithValue(node, value);
     130             :     return Replace(value);
     131             :   }
     132          54 :   Node* input = NodeProperties::GetValueInput(node, 2);
     133          54 :   Node* effect = NodeProperties::GetEffectInput(node);
     134          54 :   Node* control = NodeProperties::GetControlInput(node);
     135             : 
     136             :   input = effect =
     137             :       graph()->NewNode(simplified()->SpeculativeToNumber(
     138          54 :                            NumberOperationHint::kNumberOrOddball, p.feedback()),
     139          54 :                        input, effect, control);
     140          54 :   input = graph()->NewNode(simplified()->NumberToUint32(), input);
     141          54 :   Node* value = graph()->NewNode(simplified()->NumberClz32(), input);
     142             :   ReplaceWithValue(node, value, effect);
     143             :   return Replace(value);
     144             : }
     145             : 
     146             : // ES6 section 20.2.2.24 Math.max ( value1, value2, ...values )
     147             : // ES6 section 20.2.2.25 Math.min ( value1, value2, ...values )
     148        2829 : Reduction JSCallReducer::ReduceMathMinMax(Node* node, const Operator* op,
     149             :                                           Node* empty_value) {
     150         764 :   CallParameters const& p = CallParametersOf(node->op());
     151         764 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
     152             :     return NoChange();
     153             :   }
     154        1376 :   if (node->op()->ValueInputCount() <= 2) {
     155         688 :     ReplaceWithValue(node, empty_value);
     156             :     return Replace(empty_value);
     157             :   }
     158         686 :   Node* effect = NodeProperties::GetEffectInput(node);
     159         686 :   Node* control = NodeProperties::GetControlInput(node);
     160             : 
     161             :   Node* value = effect =
     162             :       graph()->NewNode(simplified()->SpeculativeToNumber(
     163         686 :                            NumberOperationHint::kNumberOrOddball, p.feedback()),
     164        1372 :                        NodeProperties::GetValueInput(node, 2), effect, control);
     165        4131 :   for (int i = 3; i < node->op()->ValueInputCount(); i++) {
     166             :     Node* input = effect = graph()->NewNode(
     167             :         simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
     168             :                                           p.feedback()),
     169        1382 :         NodeProperties::GetValueInput(node, i), effect, control);
     170             :     value = graph()->NewNode(op, value, input);
     171             :   }
     172             : 
     173             :   ReplaceWithValue(node, value, effect);
     174             :   return Replace(value);
     175             : }
     176             : 
     177    31449779 : Reduction JSCallReducer::Reduce(Node* node) {
     178    31449779 :   switch (node->opcode()) {
     179             :     case IrOpcode::kJSConstruct:
     180       41586 :       return ReduceJSConstruct(node);
     181             :     case IrOpcode::kJSConstructWithArrayLike:
     182           7 :       return ReduceJSConstructWithArrayLike(node);
     183             :     case IrOpcode::kJSConstructWithSpread:
     184         997 :       return ReduceJSConstructWithSpread(node);
     185             :     case IrOpcode::kJSCall:
     186      673103 :       return ReduceJSCall(node);
     187             :     case IrOpcode::kJSCallWithArrayLike:
     188         130 :       return ReduceJSCallWithArrayLike(node);
     189             :     case IrOpcode::kJSCallWithSpread:
     190        1205 :       return ReduceJSCallWithSpread(node);
     191             :     default:
     192             :       break;
     193             :   }
     194             :   return NoChange();
     195             : }
     196             : 
     197      508713 : void JSCallReducer::Finalize() {
     198             :   // TODO(turbofan): This is not the best solution; ideally we would be able
     199             :   // to teach the GraphReducer about arbitrary dependencies between different
     200             :   // nodes, even if they don't show up in the use list of the other node.
     201             :   std::set<Node*> const waitlist = std::move(waitlist_);
     202     1017501 :   for (Node* node : waitlist) {
     203          82 :     if (!node->IsDead()) {
     204          82 :       Reduction const reduction = Reduce(node);
     205          82 :       if (reduction.Changed()) {
     206             :         Node* replacement = reduction.replacement();
     207          45 :         if (replacement != node) {
     208           0 :           Replace(node, replacement);
     209             :         }
     210             :       }
     211             :     }
     212             :   }
     213      508694 : }
     214             : 
     215             : // ES6 section 22.1.1 The Array Constructor
     216         432 : Reduction JSCallReducer::ReduceArrayConstructor(Node* node) {
     217             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     218         216 :   Node* target = NodeProperties::GetValueInput(node, 0);
     219         216 :   CallParameters const& p = CallParametersOf(node->op());
     220             : 
     221             :   // Turn the {node} into a {JSCreateArray} call.
     222             :   DCHECK_LE(2u, p.arity());
     223         216 :   size_t const arity = p.arity() - 2;
     224         216 :   NodeProperties::ReplaceValueInput(node, target, 0);
     225         216 :   NodeProperties::ReplaceValueInput(node, target, 1);
     226             :   NodeProperties::ChangeOp(
     227         432 :       node, javascript()->CreateArray(arity, MaybeHandle<AllocationSite>()));
     228         216 :   return Changed(node);
     229             : }
     230             : 
     231             : // ES6 section 19.3.1.1 Boolean ( value )
     232          12 : Reduction JSCallReducer::ReduceBooleanConstructor(Node* node) {
     233             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     234          12 :   CallParameters const& p = CallParametersOf(node->op());
     235             : 
     236             :   // Replace the {node} with a proper {ToBoolean} operator.
     237             :   DCHECK_LE(2u, p.arity());
     238             :   Node* value = (p.arity() == 2) ? jsgraph()->UndefinedConstant()
     239          12 :                                  : NodeProperties::GetValueInput(node, 2);
     240          12 :   value = graph()->NewNode(simplified()->ToBoolean(), value);
     241          12 :   ReplaceWithValue(node, value);
     242          12 :   return Replace(value);
     243             : }
     244             : 
     245             : // ES section #sec-object-constructor
     246         560 : Reduction JSCallReducer::ReduceObjectConstructor(Node* node) {
     247             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     248         217 :   CallParameters const& p = CallParametersOf(node->op());
     249         217 :   if (p.arity() < 3) return NoChange();
     250             :   Node* value = (p.arity() >= 3) ? NodeProperties::GetValueInput(node, 2)
     251         175 :                                  : jsgraph()->UndefinedConstant();
     252         175 :   Node* effect = NodeProperties::GetEffectInput(node);
     253             : 
     254             :   // We can fold away the Object(x) call if |x| is definitely not a primitive.
     255         175 :   if (NodeProperties::CanBePrimitive(broker(), value, effect)) {
     256         168 :     if (!NodeProperties::CanBeNullOrUndefined(broker(), value, effect)) {
     257             :       // Turn the {node} into a {JSToObject} call if we know that
     258             :       // the {value} cannot be null or undefined.
     259          64 :       NodeProperties::ReplaceValueInputs(node, value);
     260          64 :       NodeProperties::ChangeOp(node, javascript()->ToObject());
     261             :       return Changed(node);
     262             :     }
     263             :   } else {
     264           7 :     ReplaceWithValue(node, value);
     265             :     return Replace(value);
     266             :   }
     267             :   return NoChange();
     268             : }
     269             : 
     270             : // ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
     271        1068 : Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
     272             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     273         491 :   CallParameters const& p = CallParametersOf(node->op());
     274             :   size_t arity = p.arity();
     275             :   DCHECK_LE(2u, arity);
     276             :   ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny;
     277         491 :   if (arity == 2) {
     278             :     // Neither thisArg nor argArray was provided.
     279             :     convert_mode = ConvertReceiverMode::kNullOrUndefined;
     280          14 :     node->ReplaceInput(0, node->InputAt(1));
     281          14 :     node->ReplaceInput(1, jsgraph()->UndefinedConstant());
     282         477 :   } else if (arity == 3) {
     283             :     // The argArray was not provided, just remove the {target}.
     284          10 :     node->RemoveInput(0);
     285          10 :     --arity;
     286             :   } else {
     287         467 :     Node* target = NodeProperties::GetValueInput(node, 1);
     288         467 :     Node* this_argument = NodeProperties::GetValueInput(node, 2);
     289         467 :     Node* arguments_list = NodeProperties::GetValueInput(node, 3);
     290         467 :     Node* context = NodeProperties::GetContextInput(node);
     291         467 :     Node* frame_state = NodeProperties::GetFrameStateInput(node);
     292         467 :     Node* effect = NodeProperties::GetEffectInput(node);
     293         467 :     Node* control = NodeProperties::GetControlInput(node);
     294             : 
     295             :     // If {arguments_list} cannot be null or undefined, we don't need
     296             :     // to expand this {node} to control-flow.
     297         467 :     if (!NodeProperties::CanBeNullOrUndefined(broker(), arguments_list,
     298         467 :                                               effect)) {
     299             :       // Massage the value inputs appropriately.
     300         419 :       node->ReplaceInput(0, target);
     301         419 :       node->ReplaceInput(1, this_argument);
     302         419 :       node->ReplaceInput(2, arguments_list);
     303         419 :       while (arity-- > 3) node->RemoveInput(3);
     304             : 
     305             :       // Morph the {node} to a {JSCallWithArrayLike}.
     306             :       NodeProperties::ChangeOp(node,
     307         838 :                                javascript()->CallWithArrayLike(p.frequency()));
     308         419 :       Reduction const reduction = ReduceJSCallWithArrayLike(node);
     309         419 :       return reduction.Changed() ? reduction : Changed(node);
     310             :     } else {
     311             :       // Check whether {arguments_list} is null.
     312             :       Node* check_null =
     313             :           graph()->NewNode(simplified()->ReferenceEqual(), arguments_list,
     314          96 :                            jsgraph()->NullConstant());
     315             :       control = graph()->NewNode(common()->Branch(BranchHint::kFalse),
     316          48 :                                  check_null, control);
     317          48 :       Node* if_null = graph()->NewNode(common()->IfTrue(), control);
     318          48 :       control = graph()->NewNode(common()->IfFalse(), control);
     319             : 
     320             :       // Check whether {arguments_list} is undefined.
     321             :       Node* check_undefined =
     322             :           graph()->NewNode(simplified()->ReferenceEqual(), arguments_list,
     323          96 :                            jsgraph()->UndefinedConstant());
     324             :       control = graph()->NewNode(common()->Branch(BranchHint::kFalse),
     325          48 :                                  check_undefined, control);
     326          48 :       Node* if_undefined = graph()->NewNode(common()->IfTrue(), control);
     327          48 :       control = graph()->NewNode(common()->IfFalse(), control);
     328             : 
     329             :       // Lower to {JSCallWithArrayLike} if {arguments_list} is neither null
     330             :       // nor undefined.
     331             :       Node* effect0 = effect;
     332             :       Node* control0 = control;
     333             :       Node* value0 = effect0 = control0 = graph()->NewNode(
     334          48 :           javascript()->CallWithArrayLike(p.frequency()), target, this_argument,
     335          48 :           arguments_list, context, frame_state, effect0, control0);
     336             : 
     337             :       // Lower to {JSCall} if {arguments_list} is either null or undefined.
     338             :       Node* effect1 = effect;
     339             :       Node* control1 =
     340          48 :           graph()->NewNode(common()->Merge(2), if_null, if_undefined);
     341             :       Node* value1 = effect1 = control1 =
     342             :           graph()->NewNode(javascript()->Call(2), target, this_argument,
     343         144 :                            context, frame_state, effect1, control1);
     344             : 
     345             :       // Rewire potential exception edges.
     346          48 :       Node* if_exception = nullptr;
     347          48 :       if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
     348             :         // Create appropriate {IfException} and {IfSuccess} nodes.
     349             :         Node* if_exception0 =
     350           7 :             graph()->NewNode(common()->IfException(), control0, effect0);
     351           7 :         control0 = graph()->NewNode(common()->IfSuccess(), control0);
     352             :         Node* if_exception1 =
     353           7 :             graph()->NewNode(common()->IfException(), control1, effect1);
     354           7 :         control1 = graph()->NewNode(common()->IfSuccess(), control1);
     355             : 
     356             :         // Join the exception edges.
     357             :         Node* merge =
     358           7 :             graph()->NewNode(common()->Merge(2), if_exception0, if_exception1);
     359             :         Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception0,
     360           7 :                                       if_exception1, merge);
     361             :         Node* phi =
     362             :             graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     363           7 :                              if_exception0, if_exception1, merge);
     364          55 :         ReplaceWithValue(if_exception, phi, ephi, merge);
     365             :       }
     366             : 
     367             :       // Join control paths.
     368          48 :       control = graph()->NewNode(common()->Merge(2), control0, control1);
     369             :       effect =
     370          48 :           graph()->NewNode(common()->EffectPhi(2), effect0, effect1, control);
     371             :       Node* value =
     372             :           graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     373          48 :                            value0, value1, control);
     374             :       ReplaceWithValue(node, value, effect, control);
     375             :       return Replace(value);
     376             :     }
     377             :   }
     378             :   // Change {node} to the new {JSCall} operator.
     379             :   NodeProperties::ChangeOp(
     380             :       node,
     381          48 :       javascript()->Call(arity, p.frequency(), VectorSlotPair(), convert_mode));
     382             :   // Try to further reduce the JSCall {node}.
     383          24 :   Reduction const reduction = ReduceJSCall(node);
     384          24 :   return reduction.Changed() ? reduction : Changed(node);
     385             : }
     386             : 
     387             : // ES section #sec-function.prototype.bind
     388         811 : Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
     389             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     390             :   // Value inputs to the {node} are as follows:
     391             :   //
     392             :   //  - target, which is Function.prototype.bind JSFunction
     393             :   //  - receiver, which is the [[BoundTargetFunction]]
     394             :   //  - bound_this (optional), which is the [[BoundThis]]
     395             :   //  - and all the remaining value inouts are [[BoundArguments]]
     396         141 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     397         141 :   Node* bound_this = (node->op()->ValueInputCount() < 3)
     398             :                          ? jsgraph()->UndefinedConstant()
     399         170 :                          : NodeProperties::GetValueInput(node, 2);
     400         141 :   Node* context = NodeProperties::GetContextInput(node);
     401         141 :   Node* effect = NodeProperties::GetEffectInput(node);
     402         141 :   Node* control = NodeProperties::GetControlInput(node);
     403             : 
     404             :   // Ensure that the {receiver} is known to be a JSBoundFunction or
     405             :   // a JSFunction with the same [[Prototype]], and all maps we've
     406             :   // seen for the {receiver} so far indicate that {receiver} is
     407             :   // definitely a constructor or not a constructor.
     408             :   ZoneHandleSet<Map> receiver_maps;
     409             :   NodeProperties::InferReceiverMapsResult result =
     410             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
     411         141 :                                         &receiver_maps);
     412         141 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
     413             :   DCHECK_NE(0, receiver_maps.size());
     414             :   MapRef first_receiver_map(broker(), receiver_maps[0]);
     415         127 :   bool const is_constructor = first_receiver_map.is_constructor();
     416         127 :   first_receiver_map.SerializePrototype();
     417         127 :   ObjectRef const prototype = first_receiver_map.prototype();
     418         232 :   for (Handle<Map> const map : receiver_maps) {
     419             :     MapRef receiver_map(broker(), map);
     420             : 
     421             :     // Check for consistency among the {receiver_maps}.
     422             :     STATIC_ASSERT(LAST_TYPE == LAST_FUNCTION_TYPE);
     423         127 :     receiver_map.SerializePrototype();
     424         381 :     if (!receiver_map.prototype().equals(prototype) ||
     425         254 :         receiver_map.is_constructor() != is_constructor ||
     426         127 :         receiver_map.instance_type() < FIRST_FUNCTION_TYPE) {
     427          22 :       return NoChange();
     428             :     }
     429             : 
     430             :     // Disallow binding of slow-mode functions. We need to figure out
     431             :     // whether the length and name property are in the original state.
     432         127 :     if (receiver_map.is_dictionary_map()) return NoChange();
     433             : 
     434             :     // Check whether the length and name properties are still present
     435             :     // as AccessorInfo objects. In that case, their values can be
     436             :     // recomputed even if the actual value of the object changes.
     437             :     // This mirrors the checks done in builtins-function-gen.cc at
     438             :     // runtime otherwise.
     439             :     Handle<DescriptorArray> descriptors(
     440         381 :         receiver_map.object()->instance_descriptors(), isolate());
     441         127 :     if (descriptors->number_of_descriptors() < 2) return NoChange();
     442         240 :     if (descriptors->GetKey(JSFunction::kLengthDescriptorIndex) !=
     443             :         ReadOnlyRoots(isolate()).length_string()) {
     444             :       return NoChange();
     445             :     }
     446         240 :     if (!descriptors->GetStrongValue(JSFunction::kLengthDescriptorIndex)
     447         240 :              ->IsAccessorInfo()) {
     448             :       return NoChange();
     449             :     }
     450         240 :     if (descriptors->GetKey(JSFunction::kNameDescriptorIndex) !=
     451             :         ReadOnlyRoots(isolate()).name_string()) {
     452             :       return NoChange();
     453             :     }
     454         210 :     if (!descriptors->GetStrongValue(JSFunction::kNameDescriptorIndex)
     455         210 :              ->IsAccessorInfo()) {
     456             :       return NoChange();
     457             :     }
     458             :   }
     459             : 
     460             :   // Choose the map for the resulting JSBoundFunction (but bail out in case of a
     461             :   // custom prototype).
     462             :   MapRef map = is_constructor
     463         285 :                    ? native_context().bound_function_with_constructor_map()
     464         225 :                    : native_context().bound_function_without_constructor_map();
     465         105 :   if (!map.prototype().equals(prototype)) return NoChange();
     466             : 
     467             :   // Make sure we can rely on the {receiver_maps}.
     468         105 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
     469             :     effect = graph()->NewNode(
     470             :         simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
     471           3 :         effect, control);
     472             :   }
     473             : 
     474             :   // Replace the {node} with a JSCreateBoundFunction.
     475         315 :   int const arity = std::max(0, node->op()->ValueInputCount() - 3);
     476         105 :   int const input_count = 2 + arity + 3;
     477         210 :   Node** inputs = graph()->zone()->NewArray<Node*>(input_count);
     478         105 :   inputs[0] = receiver;
     479         105 :   inputs[1] = bound_this;
     480         192 :   for (int i = 0; i < arity; ++i) {
     481          87 :     inputs[2 + i] = NodeProperties::GetValueInput(node, 3 + i);
     482             :   }
     483         105 :   inputs[2 + arity + 0] = context;
     484         105 :   inputs[2 + arity + 1] = effect;
     485         105 :   inputs[2 + arity + 2] = control;
     486             :   Node* value = effect =
     487             :       graph()->NewNode(javascript()->CreateBoundFunction(arity, map.object()),
     488         315 :                        input_count, inputs);
     489         105 :   ReplaceWithValue(node, value, effect, control);
     490             :   return Replace(value);
     491             : }
     492             : 
     493             : // ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args)
     494        4695 : Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
     495             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     496        3108 :   CallParameters const& p = CallParametersOf(node->op());
     497        1554 :   Node* target = NodeProperties::GetValueInput(node, 0);
     498        1554 :   Node* effect = NodeProperties::GetEffectInput(node);
     499        1554 :   Node* control = NodeProperties::GetControlInput(node);
     500             : 
     501             :   // Change context of {node} to the Function.prototype.call context,
     502             :   // to ensure any exception is thrown in the correct context.
     503             :   Node* context;
     504             :   HeapObjectMatcher m(target);
     505        1554 :   if (m.HasValue()) {
     506        1554 :     JSFunctionRef function = m.Ref(broker()).AsJSFunction();
     507        3108 :     context = jsgraph()->Constant(function.context());
     508             :   } else {
     509             :     context = effect = graph()->NewNode(
     510             :         simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
     511           0 :         effect, control);
     512             :   }
     513        1554 :   NodeProperties::ReplaceContextInput(node, context);
     514        1554 :   NodeProperties::ReplaceEffectInput(node, effect);
     515             : 
     516             :   // Remove the target from {node} and use the receiver as target instead, and
     517             :   // the thisArg becomes the new target.  If thisArg was not provided, insert
     518             :   // undefined instead.
     519             :   size_t arity = p.arity();
     520             :   DCHECK_LE(2u, arity);
     521             :   ConvertReceiverMode convert_mode;
     522        1554 :   if (arity == 2) {
     523             :     // The thisArg was not provided, use undefined as receiver.
     524             :     convert_mode = ConvertReceiverMode::kNullOrUndefined;
     525          33 :     node->ReplaceInput(0, node->InputAt(1));
     526          33 :     node->ReplaceInput(1, jsgraph()->UndefinedConstant());
     527             :   } else {
     528             :     // Just remove the target, which is the first value input.
     529             :     convert_mode = ConvertReceiverMode::kAny;
     530        1521 :     node->RemoveInput(0);
     531        1521 :     --arity;
     532             :   }
     533             :   NodeProperties::ChangeOp(
     534             :       node,
     535        3108 :       javascript()->Call(arity, p.frequency(), VectorSlotPair(), convert_mode));
     536             :   // Try to further reduce the JSCall {node}.
     537        1554 :   Reduction const reduction = ReduceJSCall(node);
     538        1554 :   return reduction.Changed() ? reduction : Changed(node);
     539             : }
     540             : 
     541             : // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] (V)
     542        3070 : Reduction JSCallReducer::ReduceFunctionPrototypeHasInstance(Node* node) {
     543             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     544        1535 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     545        1535 :   Node* object = (node->op()->ValueInputCount() >= 3)
     546             :                      ? NodeProperties::GetValueInput(node, 2)
     547        1535 :                      : jsgraph()->UndefinedConstant();
     548        1535 :   Node* context = NodeProperties::GetContextInput(node);
     549        1535 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     550        1535 :   Node* effect = NodeProperties::GetEffectInput(node);
     551        1535 :   Node* control = NodeProperties::GetControlInput(node);
     552             : 
     553             :   // TODO(turbofan): If JSOrdinaryToInstance raises an exception, the
     554             :   // stack trace doesn't contain the @@hasInstance call; we have the
     555             :   // corresponding bug in the baseline case. Some massaging of the frame
     556             :   // state would be necessary here.
     557             : 
     558             :   // Morph this {node} into a JSOrdinaryHasInstance node.
     559        1535 :   node->ReplaceInput(0, receiver);
     560        1535 :   node->ReplaceInput(1, object);
     561        1535 :   node->ReplaceInput(2, context);
     562        1535 :   node->ReplaceInput(3, frame_state);
     563        1535 :   node->ReplaceInput(4, effect);
     564        1535 :   node->ReplaceInput(5, control);
     565        1535 :   node->TrimInputCount(6);
     566        1535 :   NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
     567        1535 :   return Changed(node);
     568             : }
     569             : 
     570        2104 : Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) {
     571         789 :   Node* effect = NodeProperties::GetEffectInput(node);
     572             : 
     573             :   // Try to determine the {object} map.
     574             :   ZoneHandleSet<Map> object_maps;
     575             :   NodeProperties::InferReceiverMapsResult result =
     576         789 :       NodeProperties::InferReceiverMaps(broker(), object, effect, &object_maps);
     577         789 :   if (result != NodeProperties::kNoReceiverMaps) {
     578             :     MapRef candidate_map(broker(), object_maps[0]);
     579         177 :     candidate_map.SerializePrototype();
     580         177 :     ObjectRef candidate_prototype = candidate_map.prototype();
     581             : 
     582             :     // Check if we can constant-fold the {candidate_prototype}.
     583         558 :     for (size_t i = 0; i < object_maps.size(); ++i) {
     584             :       MapRef object_map(broker(), object_maps[i]);
     585         184 :       object_map.SerializePrototype();
     586         552 :       if (IsSpecialReceiverInstanceType(object_map.instance_type()) ||
     587         347 :           object_map.has_hidden_prototype() ||
     588         510 :           !object_map.prototype().equals(candidate_prototype)) {
     589             :         // We exclude special receivers, like JSProxy or API objects that
     590             :         // might require access checks here; we also don't want to deal
     591             :         // with hidden prototypes at this point.
     592          82 :         return NoChange();
     593             :       }
     594             :       // The above check also excludes maps for primitive values, which is
     595             :       // important because we are not applying [[ToObject]] here as expected.
     596             :       DCHECK(!object_map.IsPrimitiveMap() && object_map.IsJSReceiverMap());
     597         245 :       if (result == NodeProperties::kUnreliableReceiverMaps &&
     598          89 :           !object_map.is_stable()) {
     599             :         return NoChange();
     600             :       }
     601             :     }
     602          95 :     if (result == NodeProperties::kUnreliableReceiverMaps) {
     603         105 :       for (size_t i = 0; i < object_maps.size(); ++i) {
     604          35 :         dependencies()->DependOnStableMap(MapRef(broker(), object_maps[i]));
     605             :       }
     606             :     }
     607          95 :     Node* value = jsgraph()->Constant(candidate_prototype);
     608          95 :     ReplaceWithValue(node, value);
     609             :     return Replace(value);
     610             :   }
     611             : 
     612             :   return NoChange();
     613             : }
     614             : 
     615             : // ES6 section 19.1.2.11 Object.getPrototypeOf ( O )
     616         687 : Reduction JSCallReducer::ReduceObjectGetPrototypeOf(Node* node) {
     617             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     618         687 :   Node* object = (node->op()->ValueInputCount() >= 3)
     619             :                      ? NodeProperties::GetValueInput(node, 2)
     620         687 :                      : jsgraph()->UndefinedConstant();
     621         687 :   return ReduceObjectGetPrototype(node, object);
     622             : }
     623             : 
     624             : // ES section #sec-object.is
     625         244 : Reduction JSCallReducer::ReduceObjectIs(Node* node) {
     626             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     627         230 :   CallParameters const& params = CallParametersOf(node->op());
     628         230 :   int const argc = static_cast<int>(params.arity() - 2);
     629             :   Node* lhs = (argc >= 1) ? NodeProperties::GetValueInput(node, 2)
     630         237 :                           : jsgraph()->UndefinedConstant();
     631             :   Node* rhs = (argc >= 2) ? NodeProperties::GetValueInput(node, 3)
     632         237 :                           : jsgraph()->UndefinedConstant();
     633         230 :   Node* value = graph()->NewNode(simplified()->SameValue(), lhs, rhs);
     634         230 :   ReplaceWithValue(node, value);
     635         230 :   return Replace(value);
     636             : }
     637             : 
     638             : // ES6 section B.2.2.1.1 get Object.prototype.__proto__
     639          88 : Reduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) {
     640             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     641          88 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     642          88 :   return ReduceObjectGetPrototype(node, receiver);
     643             : }
     644             : 
     645             : // ES #sec-object.prototype.hasownproperty
     646          76 : Reduction JSCallReducer::ReduceObjectPrototypeHasOwnProperty(Node* node) {
     647             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     648          68 :   CallParameters const& params = CallParametersOf(node->op());
     649          68 :   int const argc = static_cast<int>(params.arity() - 2);
     650          68 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     651          68 :   Node* name = (argc >= 1) ? NodeProperties::GetValueInput(node, 2)
     652          76 :                            : jsgraph()->UndefinedConstant();
     653          68 :   Node* effect = NodeProperties::GetEffectInput(node);
     654          68 :   Node* control = NodeProperties::GetControlInput(node);
     655             : 
     656             :   // We can optimize a call to Object.prototype.hasOwnProperty if it's being
     657             :   // used inside a fast-mode for..in, so for code like this:
     658             :   //
     659             :   //   for (name in receiver) {
     660             :   //     if (receiver.hasOwnProperty(name)) {
     661             :   //        ...
     662             :   //     }
     663             :   //   }
     664             :   //
     665             :   // If the for..in is in fast-mode, we know that the {receiver} has {name}
     666             :   // as own property, otherwise the enumeration wouldn't include it. The graph
     667             :   // constructed by the BytecodeGraphBuilder in this case looks like this:
     668             : 
     669             :   // receiver
     670             :   //  ^    ^
     671             :   //  |    |
     672             :   //  |    +-+
     673             :   //  |      |
     674             :   //  |   JSToObject
     675             :   //  |      ^
     676             :   //  |      |
     677             :   //  |   JSForInNext
     678             :   //  |      ^
     679             :   //  +----+ |
     680             :   //       | |
     681             :   //  JSCall[hasOwnProperty]
     682             : 
     683             :   // We can constant-fold the {node} to True in this case, and insert
     684             :   // a (potentially redundant) map check to guard the fact that the
     685             :   // {receiver} map didn't change since the dominating JSForInNext. This
     686             :   // map check is only necessary when TurboFan cannot prove that there
     687             :   // is no observable side effect between the {JSForInNext} and the
     688             :   // {JSCall} to Object.prototype.hasOwnProperty.
     689             :   //
     690             :   // Also note that it's safe to look through the {JSToObject}, since the
     691             :   // Object.prototype.hasOwnProperty does an implicit ToObject anyway, and
     692             :   // these operations are not observable.
     693          68 :   if (name->opcode() == IrOpcode::kJSForInNext) {
     694           7 :     ForInMode const mode = ForInModeOf(name->op());
     695           7 :     if (mode != ForInMode::kGeneric) {
     696          14 :       Node* object = NodeProperties::GetValueInput(name, 0);
     697           7 :       Node* cache_type = NodeProperties::GetValueInput(name, 2);
     698           7 :       if (object->opcode() == IrOpcode::kJSToObject) {
     699           0 :         object = NodeProperties::GetValueInput(object, 0);
     700             :       }
     701           7 :       if (object == receiver) {
     702             :         // No need to repeat the map check if we can prove that there's no
     703             :         // observable side effect between {effect} and {name].
     704           0 :         if (!NodeProperties::NoObservableSideEffectBetween(effect, name)) {
     705             :           Node* receiver_map = effect =
     706             :               graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
     707           0 :                                receiver, effect, control);
     708             :           Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
     709           0 :                                          receiver_map, cache_type);
     710             :           effect = graph()->NewNode(
     711             :               simplified()->CheckIf(DeoptimizeReason::kWrongMap), check, effect,
     712           0 :               control);
     713             :         }
     714           0 :         Node* value = jsgraph()->TrueConstant();
     715           0 :         ReplaceWithValue(node, value, effect, control);
     716             :         return Replace(value);
     717             :       }
     718             :     }
     719             :   }
     720             : 
     721             :   return NoChange();
     722             : }
     723             : 
     724             : // ES #sec-object.prototype.isprototypeof
     725         273 : Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) {
     726             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     727          63 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     728          63 :   Node* value = node->op()->ValueInputCount() > 2
     729             :                     ? NodeProperties::GetValueInput(node, 2)
     730          63 :                     : jsgraph()->UndefinedConstant();
     731          63 :   Node* effect = NodeProperties::GetEffectInput(node);
     732             : 
     733             :   // Ensure that the {receiver} is known to be a JSReceiver (so that
     734             :   // the ToObject step of Object.prototype.isPrototypeOf is a no-op).
     735             :   ZoneHandleSet<Map> receiver_maps;
     736             :   NodeProperties::InferReceiverMapsResult result =
     737             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
     738          63 :                                         &receiver_maps);
     739          63 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
     740          84 :   for (Handle<Map> map : receiver_maps) {
     741             :     MapRef receiver_map(broker(), map);
     742          42 :     if (!receiver_map.IsJSReceiverMap()) return NoChange();
     743             :   }
     744             : 
     745             :   // We don't check whether {value} is a proper JSReceiver here explicitly,
     746             :   // and don't explicitly rule out Primitive {value}s, since all of them
     747             :   // have null as their prototype, so the prototype chain walk inside the
     748             :   // JSHasInPrototypeChain operator immediately aborts and yields false.
     749          42 :   NodeProperties::ReplaceValueInput(node, value, 0);
     750          42 :   NodeProperties::ReplaceValueInput(node, receiver, 1);
     751         168 :   for (int i = node->op()->ValueInputCount(); i-- > 2;) {
     752          42 :     node->RemoveInput(i);
     753             :   }
     754          42 :   NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
     755             :   return Changed(node);
     756             : }
     757             : 
     758             : // ES6 section 26.1.1 Reflect.apply ( target, thisArgument, argumentsList )
     759         275 : Reduction JSCallReducer::ReduceReflectApply(Node* node) {
     760             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     761         254 :   CallParameters const& p = CallParametersOf(node->op());
     762         254 :   int arity = static_cast<int>(p.arity() - 2);
     763             :   DCHECK_LE(0, arity);
     764             :   // Massage value inputs appropriately.
     765         254 :   node->RemoveInput(0);
     766         255 :   node->RemoveInput(0);
     767         530 :   while (arity < 3) {
     768          42 :     node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
     769             :   }
     770         261 :   while (arity-- > 3) {
     771           7 :     node->RemoveInput(arity);
     772             :   }
     773             :   NodeProperties::ChangeOp(node,
     774         508 :                            javascript()->CallWithArrayLike(p.frequency()));
     775         255 :   Reduction const reduction = ReduceJSCallWithArrayLike(node);
     776         255 :   return reduction.Changed() ? reduction : Changed(node);
     777             : }
     778             : 
     779             : // ES6 section 26.1.2 Reflect.construct ( target, argumentsList [, newTarget] )
     780         196 : Reduction JSCallReducer::ReduceReflectConstruct(Node* node) {
     781             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     782         189 :   CallParameters const& p = CallParametersOf(node->op());
     783         189 :   int arity = static_cast<int>(p.arity() - 2);
     784             :   DCHECK_LE(0, arity);
     785             :   // Massage value inputs appropriately.
     786         189 :   node->RemoveInput(0);
     787         189 :   node->RemoveInput(0);
     788         385 :   while (arity < 2) {
     789          14 :     node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
     790             :   }
     791         189 :   if (arity < 3) {
     792          70 :     node->InsertInput(graph()->zone(), arity++, node->InputAt(0));
     793             :   }
     794         196 :   while (arity-- > 3) {
     795           7 :     node->RemoveInput(arity);
     796             :   }
     797             :   NodeProperties::ChangeOp(node,
     798         378 :                            javascript()->ConstructWithArrayLike(p.frequency()));
     799         189 :   Reduction const reduction = ReduceJSConstructWithArrayLike(node);
     800         189 :   return reduction.Changed() ? reduction : Changed(node);
     801             : }
     802             : 
     803             : // ES6 section 26.1.7 Reflect.getPrototypeOf ( target )
     804          14 : Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) {
     805             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     806          14 :   Node* target = (node->op()->ValueInputCount() >= 3)
     807             :                      ? NodeProperties::GetValueInput(node, 2)
     808          14 :                      : jsgraph()->UndefinedConstant();
     809          14 :   return ReduceObjectGetPrototype(node, target);
     810             : }
     811             : 
     812             : // ES6 section #sec-object.create Object.create(proto, properties)
     813         225 : Reduction JSCallReducer::ReduceObjectCreate(Node* node) {
     814          75 :   int arg_count = node->op()->ValueInputCount();
     815             :   Node* properties = arg_count >= 4 ? NodeProperties::GetValueInput(node, 3)
     816         150 :                                     : jsgraph()->UndefinedConstant();
     817          75 :   if (properties != jsgraph()->UndefinedConstant()) return NoChange();
     818             : 
     819          75 :   Node* effect = NodeProperties::GetEffectInput(node);
     820          75 :   Node* control = NodeProperties::GetControlInput(node);
     821          75 :   Node* context = NodeProperties::GetContextInput(node);
     822          75 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     823             :   Node* prototype = arg_count >= 3 ? NodeProperties::GetValueInput(node, 2)
     824          75 :                                    : jsgraph()->UndefinedConstant();
     825          75 :   node->ReplaceInput(0, prototype);
     826          75 :   node->ReplaceInput(1, context);
     827          75 :   node->ReplaceInput(2, frame_state);
     828          75 :   node->ReplaceInput(3, effect);
     829          75 :   node->ReplaceInput(4, control);
     830          75 :   node->TrimInputCount(5);
     831          75 :   NodeProperties::ChangeOp(node, javascript()->CreateObject());
     832             :   return Changed(node);
     833             : }
     834             : 
     835             : // ES section #sec-reflect.get
     836          63 : Reduction JSCallReducer::ReduceReflectGet(Node* node) {
     837             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     838          35 :   CallParameters const& p = CallParametersOf(node->op());
     839             :   int arity = static_cast<int>(p.arity() - 2);
     840          35 :   if (arity != 2) return NoChange();
     841          14 :   Node* target = NodeProperties::GetValueInput(node, 2);
     842          14 :   Node* key = NodeProperties::GetValueInput(node, 3);
     843          14 :   Node* context = NodeProperties::GetContextInput(node);
     844          14 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     845          14 :   Node* effect = NodeProperties::GetEffectInput(node);
     846          14 :   Node* control = NodeProperties::GetControlInput(node);
     847             : 
     848             :   // Check whether {target} is a JSReceiver.
     849          14 :   Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
     850             :   Node* branch =
     851          14 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
     852             : 
     853             :   // Throw an appropriate TypeError if the {target} is not a JSReceiver.
     854          14 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
     855             :   Node* efalse = effect;
     856             :   {
     857             :     if_false = efalse = graph()->NewNode(
     858             :         javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
     859             :         jsgraph()->Constant(
     860             :             static_cast<int>(MessageTemplate::kCalledOnNonObject)),
     861             :         jsgraph()->HeapConstant(factory()->ReflectGet_string()), context,
     862          56 :         frame_state, efalse, if_false);
     863             :   }
     864             : 
     865             :   // Otherwise just use the existing GetPropertyStub.
     866          14 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
     867             :   Node* etrue = effect;
     868             :   Node* vtrue;
     869             :   {
     870             :     Callable callable =
     871          14 :         Builtins::CallableFor(isolate(), Builtins::kGetProperty);
     872             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
     873             :         graph()->zone(), callable.descriptor(),
     874             :         callable.descriptor().GetStackParameterCount(),
     875          28 :         CallDescriptor::kNeedsFrameState, Operator::kNoProperties);
     876          14 :     Node* stub_code = jsgraph()->HeapConstant(callable.code());
     877             :     vtrue = etrue = if_true =
     878             :         graph()->NewNode(common()->Call(call_descriptor), stub_code, target,
     879          14 :                          key, context, frame_state, etrue, if_true);
     880             :   }
     881             : 
     882             :   // Rewire potential exception edges.
     883          14 :   Node* on_exception = nullptr;
     884          14 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
     885             :     // Create appropriate {IfException} and {IfSuccess} nodes.
     886          14 :     Node* extrue = graph()->NewNode(common()->IfException(), etrue, if_true);
     887          14 :     if_true = graph()->NewNode(common()->IfSuccess(), if_true);
     888          14 :     Node* exfalse = graph()->NewNode(common()->IfException(), efalse, if_false);
     889          14 :     if_false = graph()->NewNode(common()->IfSuccess(), if_false);
     890             : 
     891             :     // Join the exception edges.
     892          14 :     Node* merge = graph()->NewNode(common()->Merge(2), extrue, exfalse);
     893             :     Node* ephi =
     894          14 :         graph()->NewNode(common()->EffectPhi(2), extrue, exfalse, merge);
     895             :     Node* phi =
     896             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     897          14 :                          extrue, exfalse, merge);
     898          28 :     ReplaceWithValue(on_exception, phi, ephi, merge);
     899             :   }
     900             : 
     901             :   // Connect the throwing path to end.
     902          14 :   if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
     903          14 :   NodeProperties::MergeControlToEnd(graph(), common(), if_false);
     904             : 
     905             :   // Continue on the regular path.
     906             :   ReplaceWithValue(node, vtrue, etrue, if_true);
     907             :   return Changed(vtrue);
     908             : }
     909             : 
     910             : // ES section #sec-reflect.has
     911         112 : Reduction JSCallReducer::ReduceReflectHas(Node* node) {
     912             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
     913          35 :   CallParameters const& p = CallParametersOf(node->op());
     914          35 :   int arity = static_cast<int>(p.arity() - 2);
     915             :   DCHECK_LE(0, arity);
     916             :   Node* target = (arity >= 1) ? NodeProperties::GetValueInput(node, 2)
     917          49 :                               : jsgraph()->UndefinedConstant();
     918             :   Node* key = (arity >= 2) ? NodeProperties::GetValueInput(node, 3)
     919          63 :                            : jsgraph()->UndefinedConstant();
     920          35 :   Node* context = NodeProperties::GetContextInput(node);
     921          35 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     922          35 :   Node* effect = NodeProperties::GetEffectInput(node);
     923          35 :   Node* control = NodeProperties::GetControlInput(node);
     924             : 
     925             :   // Check whether {target} is a JSReceiver.
     926          35 :   Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
     927             :   Node* branch =
     928          35 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
     929             : 
     930             :   // Throw an appropriate TypeError if the {target} is not a JSReceiver.
     931          35 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
     932             :   Node* efalse = effect;
     933             :   {
     934             :     if_false = efalse = graph()->NewNode(
     935             :         javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
     936             :         jsgraph()->Constant(
     937             :             static_cast<int>(MessageTemplate::kCalledOnNonObject)),
     938             :         jsgraph()->HeapConstant(factory()->ReflectHas_string()), context,
     939         140 :         frame_state, efalse, if_false);
     940             :   }
     941             : 
     942             :   // Otherwise just use the existing {JSHasProperty} logic.
     943          35 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
     944             :   Node* etrue = effect;
     945             :   Node* vtrue;
     946             :   {
     947             :     vtrue = etrue = if_true =
     948             :         graph()->NewNode(javascript()->HasProperty(), target, key, context,
     949          35 :                          frame_state, etrue, if_true);
     950             :   }
     951             : 
     952             :   // Rewire potential exception edges.
     953          35 :   Node* on_exception = nullptr;
     954          35 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
     955             :     // Create appropriate {IfException} and {IfSuccess} nodes.
     956          14 :     Node* extrue = graph()->NewNode(common()->IfException(), etrue, if_true);
     957          14 :     if_true = graph()->NewNode(common()->IfSuccess(), if_true);
     958          14 :     Node* exfalse = graph()->NewNode(common()->IfException(), efalse, if_false);
     959          14 :     if_false = graph()->NewNode(common()->IfSuccess(), if_false);
     960             : 
     961             :     // Join the exception edges.
     962          14 :     Node* merge = graph()->NewNode(common()->Merge(2), extrue, exfalse);
     963             :     Node* ephi =
     964          14 :         graph()->NewNode(common()->EffectPhi(2), extrue, exfalse, merge);
     965             :     Node* phi =
     966             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
     967          14 :                          extrue, exfalse, merge);
     968          49 :     ReplaceWithValue(on_exception, phi, ephi, merge);
     969             :   }
     970             : 
     971             :   // Connect the throwing path to end.
     972          35 :   if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
     973          35 :   NodeProperties::MergeControlToEnd(graph(), common(), if_false);
     974             : 
     975             :   // Continue on the regular path.
     976             :   ReplaceWithValue(node, vtrue, etrue, if_true);
     977          35 :   return Changed(vtrue);
     978             : }
     979             : 
     980        1523 : Node* JSCallReducer::WireInLoopStart(Node* k, Node** control, Node** effect) {
     981             :   Node* loop = *control =
     982        4569 :       graph()->NewNode(common()->Loop(2), *control, *control);
     983             :   Node* eloop = *effect =
     984        4569 :       graph()->NewNode(common()->EffectPhi(2), *effect, *effect, loop);
     985        1523 :   Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
     986        1523 :   NodeProperties::MergeControlToEnd(graph(), common(), terminate);
     987             :   return graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), k,
     988        3046 :                           k, loop);
     989             : }
     990             : 
     991        1523 : void JSCallReducer::WireInLoopEnd(Node* loop, Node* eloop, Node* vloop, Node* k,
     992             :                                   Node* control, Node* effect) {
     993        1523 :   loop->ReplaceInput(1, control);
     994        1523 :   vloop->ReplaceInput(1, k);
     995        1523 :   eloop->ReplaceInput(1, effect);
     996        1523 : }
     997             : 
     998             : namespace {
     999        2978 : bool CanInlineArrayIteratingBuiltin(JSHeapBroker* broker,
    1000             :                                     ZoneHandleSet<Map> receiver_maps,
    1001             :                                     ElementsKind* kind_return) {
    1002             :   DCHECK_NE(0, receiver_maps.size());
    1003        2979 :   *kind_return = MapRef(broker, receiver_maps[0]).elements_kind();
    1004        5697 :   for (auto receiver_map : receiver_maps) {
    1005             :     MapRef map(broker, receiver_map);
    1006        5821 :     if (!map.supports_fast_array_iteration() ||
    1007        2756 :         !UnionElementsKindUptoSize(kind_return, map.elements_kind())) {
    1008         347 :       return false;
    1009             :     }
    1010             :   }
    1011        2632 :   return true;
    1012             : }
    1013             : 
    1014        5495 : bool CanInlineArrayResizingBuiltin(JSHeapBroker* broker,
    1015             :                                    ZoneHandleSet<Map> receiver_maps,
    1016             :                                    ElementsKind* kind_return,
    1017             :                                    bool builtin_is_push = false) {
    1018             :   DCHECK_NE(0, receiver_maps.size());
    1019        5495 :   *kind_return = MapRef(broker, receiver_maps[0]).elements_kind();
    1020        8648 :   for (auto receiver_map : receiver_maps) {
    1021             :     MapRef map(broker, receiver_map);
    1022        9165 :     if (!map.supports_fast_array_resize()) return false;
    1023        3538 :     if (builtin_is_push) {
    1024        2364 :       if (!UnionElementsKindUptoPackedness(kind_return, map.elements_kind())) {
    1025             :         return false;
    1026             :       }
    1027             :     } else {
    1028             :       // TODO(turbofan): We should also handle fast holey double elements once
    1029             :       // we got the hole NaN mess sorted out in TurboFan/V8.
    1030        2221 :       if (map.elements_kind() == HOLEY_DOUBLE_ELEMENTS ||
    1031        1047 :           !UnionElementsKindUptoSize(kind_return, map.elements_kind())) {
    1032             :         return false;
    1033             :       }
    1034             :     }
    1035             :   }
    1036        2489 :   return true;
    1037             : }
    1038             : }  // namespace
    1039             : 
    1040         340 : Reduction JSCallReducer::ReduceArrayForEach(
    1041        4765 :     Node* node, const SharedFunctionInfoRef& shared) {
    1042         340 :   if (!FLAG_turbo_inline_array_builtins) return NoChange();
    1043             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1044         340 :   CallParameters const& p = CallParametersOf(node->op());
    1045         340 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    1046             :     return NoChange();
    1047             :   }
    1048             : 
    1049         324 :   Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
    1050         324 :   Node* effect = NodeProperties::GetEffectInput(node);
    1051         324 :   Node* control = NodeProperties::GetControlInput(node);
    1052         324 :   Node* context = NodeProperties::GetContextInput(node);
    1053             : 
    1054             :   // Try to determine the {receiver} map.
    1055         324 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1056         324 :   Node* fncallback = node->op()->ValueInputCount() > 2
    1057             :                          ? NodeProperties::GetValueInput(node, 2)
    1058         324 :                          : jsgraph()->UndefinedConstant();
    1059         324 :   Node* this_arg = node->op()->ValueInputCount() > 3
    1060             :                        ? NodeProperties::GetValueInput(node, 3)
    1061         641 :                        : jsgraph()->UndefinedConstant();
    1062             :   ZoneHandleSet<Map> receiver_maps;
    1063             :   NodeProperties::InferReceiverMapsResult result =
    1064             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    1065         648 :                                         &receiver_maps);
    1066         324 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    1067             : 
    1068             :   ElementsKind kind;
    1069         324 :   if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
    1070             :     return NoChange();
    1071             :   }
    1072             : 
    1073             :   // Install code dependencies on the {receiver} prototype maps and the
    1074             :   // global array protector cell.
    1075             :   dependencies()->DependOnProtector(
    1076         308 :       PropertyCellRef(broker(), factory()->no_elements_protector()));
    1077             : 
    1078             :   // If we have unreliable maps, we need a map check.
    1079         308 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    1080             :     effect =
    1081             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    1082          14 :                                                  receiver_maps, p.feedback()),
    1083          42 :                          receiver, effect, control);
    1084             :   }
    1085             : 
    1086         308 :   Node* k = jsgraph()->ZeroConstant();
    1087             : 
    1088             :   Node* original_length = effect = graph()->NewNode(
    1089         308 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    1090        1232 :       effect, control);
    1091             : 
    1092             :   std::vector<Node*> checkpoint_params(
    1093         616 :       {receiver, fncallback, this_arg, k, original_length});
    1094         616 :   const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1095             : 
    1096             :   // Check whether the given callback function is callable. Note that this has
    1097             :   // to happen outside the loop to make sure we also throw on empty arrays.
    1098             :   Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1099             :       jsgraph(), shared, Builtins::kArrayForEachLoopLazyDeoptContinuation,
    1100             :       node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1101         308 :       outer_frame_state, ContinuationFrameStateMode::LAZY);
    1102         308 :   Node* check_fail = nullptr;
    1103         308 :   Node* check_throw = nullptr;
    1104             :   WireInCallbackIsCallableCheck(fncallback, context, check_frame_state, effect,
    1105         308 :                                 &control, &check_fail, &check_throw);
    1106             : 
    1107             :   // Start the loop.
    1108         308 :   Node* vloop = k = WireInLoopStart(k, &control, &effect);
    1109         308 :   Node *loop = control, *eloop = effect;
    1110         308 :   checkpoint_params[3] = k;
    1111             : 
    1112             :   Node* continue_test =
    1113         308 :       graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
    1114             :   Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    1115         616 :                                            continue_test, control);
    1116             : 
    1117         308 :   Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
    1118         308 :   Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
    1119         308 :   control = if_true;
    1120             : 
    1121             :   Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1122             :       jsgraph(), shared, Builtins::kArrayForEachLoopEagerDeoptContinuation,
    1123         308 :       node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1124         308 :       outer_frame_state, ContinuationFrameStateMode::EAGER);
    1125             : 
    1126             :   effect =
    1127         924 :       graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
    1128             : 
    1129             :   // Make sure the map hasn't changed during the iteration
    1130             :   effect =
    1131             :       graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    1132         308 :                                                receiver_maps, p.feedback()),
    1133         924 :                        receiver, effect, control);
    1134             : 
    1135             :   Node* element =
    1136         308 :       SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
    1137             : 
    1138             :   Node* next_k =
    1139         616 :       graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
    1140         308 :   checkpoint_params[3] = next_k;
    1141             : 
    1142             :   Node* hole_true = nullptr;
    1143             :   Node* hole_false = nullptr;
    1144         308 :   Node* effect_true = effect;
    1145             : 
    1146         616 :   if (IsHoleyElementsKind(kind)) {
    1147             :     // Holey elements kind require a hole check and skipping of the element in
    1148             :     // the case of a hole.
    1149             :     Node* check;
    1150          61 :     if (IsDoubleElementsKind(kind)) {
    1151          21 :       check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
    1152             :     } else {
    1153             :       check = graph()->NewNode(simplified()->ReferenceEqual(), element,
    1154          80 :                                jsgraph()->TheHoleConstant());
    1155             :     }
    1156             :     Node* branch =
    1157         122 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    1158          61 :     hole_true = graph()->NewNode(common()->IfTrue(), branch);
    1159          61 :     hole_false = graph()->NewNode(common()->IfFalse(), branch);
    1160          61 :     control = hole_false;
    1161             : 
    1162             :     // The contract is that we don't leak "the hole" into "user JavaScript",
    1163             :     // so we must rename the {element} here to explicitly exclude "the hole"
    1164             :     // from the type of {element}.
    1165             :     element = effect = graph()->NewNode(
    1166         183 :         common()->TypeGuard(Type::NonInternal()), element, effect, control);
    1167             :   }
    1168             : 
    1169             :   frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1170             :       jsgraph(), shared, Builtins::kArrayForEachLoopLazyDeoptContinuation,
    1171         308 :       node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1172         308 :       outer_frame_state, ContinuationFrameStateMode::LAZY);
    1173             : 
    1174             :   control = effect = graph()->NewNode(
    1175         308 :       javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
    1176         924 :       receiver, context, frame_state, effect, control);
    1177             : 
    1178             :   // Rewire potential exception edges.
    1179         308 :   Node* on_exception = nullptr;
    1180         308 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    1181             :     RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
    1182          29 :                                      &check_fail, &control);
    1183             :   }
    1184             : 
    1185         616 :   if (IsHoleyElementsKind(kind)) {
    1186          61 :     Node* after_call_control = control;
    1187          61 :     Node* after_call_effect = effect;
    1188          61 :     control = hole_true;
    1189          61 :     effect = effect_true;
    1190             : 
    1191         122 :     control = graph()->NewNode(common()->Merge(2), control, after_call_control);
    1192             :     effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
    1193         183 :                               control);
    1194             :   }
    1195             : 
    1196         308 :   WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
    1197             : 
    1198         308 :   control = if_false;
    1199         308 :   effect = eloop;
    1200             : 
    1201             :   // Introduce proper LoopExit and LoopExitEffect nodes to mark
    1202             :   // {loop} as a candidate for loop peeling (crbug.com/v8/8273).
    1203         616 :   control = graph()->NewNode(common()->LoopExit(), control, loop);
    1204         924 :   effect = graph()->NewNode(common()->LoopExitEffect(), effect, control);
    1205             : 
    1206             :   // Wire up the branch for the case when IsCallable fails for the callback.
    1207             :   // Since {check_throw} is an unconditional throw, it's impossible to
    1208             :   // return a successful completion. Therefore, we simply connect the successful
    1209             :   // completion to the graph end.
    1210             :   Node* throw_node =
    1211         616 :       graph()->NewNode(common()->Throw(), check_throw, check_fail);
    1212         308 :   NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
    1213             : 
    1214         616 :   ReplaceWithValue(node, jsgraph()->UndefinedConstant(), effect, control);
    1215         308 :   return Replace(jsgraph()->UndefinedConstant());
    1216             : }
    1217             : 
    1218         377 : Reduction JSCallReducer::ReduceArrayReduce(
    1219        1128 :     Node* node, ArrayReduceDirection direction,
    1220        5472 :     const SharedFunctionInfoRef& shared) {
    1221         377 :   if (!FLAG_turbo_inline_array_builtins) return NoChange();
    1222             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1223         377 :   CallParameters const& p = CallParametersOf(node->op());
    1224         377 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    1225             :     return NoChange();
    1226             :   }
    1227         377 :   bool left = direction == ArrayReduceDirection::kLeft;
    1228             : 
    1229         377 :   Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
    1230         377 :   Node* effect = NodeProperties::GetEffectInput(node);
    1231         377 :   Node* control = NodeProperties::GetControlInput(node);
    1232         377 :   Node* context = NodeProperties::GetContextInput(node);
    1233             : 
    1234             :   // Try to determine the {receiver} map.
    1235         377 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1236         377 :   Node* fncallback = node->op()->ValueInputCount() > 2
    1237             :                          ? NodeProperties::GetValueInput(node, 2)
    1238         377 :                          : jsgraph()->UndefinedConstant();
    1239             : 
    1240             :   ZoneHandleSet<Map> receiver_maps;
    1241             :   NodeProperties::InferReceiverMapsResult result =
    1242             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    1243         754 :                                         &receiver_maps);
    1244         377 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    1245             : 
    1246             :   ElementsKind kind;
    1247         377 :   if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
    1248             :     return NoChange();
    1249             :   }
    1250             : 
    1251         442 :   std::function<Node*(Node*)> hole_check = [this, kind](Node* element) {
    1252         884 :     if (IsDoubleElementsKind(kind)) {
    1253         458 :       return graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
    1254             :     } else {
    1255             :       return graph()->NewNode(simplified()->ReferenceEqual(), element,
    1256        1278 :                               jsgraph()->TheHoleConstant());
    1257             :     }
    1258         374 :   };
    1259             : 
    1260             :   // Install code dependencies on the {receiver} prototype maps and the
    1261             :   // global array protector cell.
    1262             :   dependencies()->DependOnProtector(
    1263         374 :       PropertyCellRef(broker(), factory()->no_elements_protector()));
    1264             : 
    1265             :   // If we have unreliable maps, we need a map check.
    1266         374 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    1267             :     effect =
    1268             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    1269           0 :                                                  receiver_maps, p.feedback()),
    1270           0 :                          receiver, effect, control);
    1271             :   }
    1272             : 
    1273             :   Node* original_length = effect = graph()->NewNode(
    1274             :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS)),
    1275        1122 :       receiver, effect, control);
    1276             : 
    1277             :   Node* initial_index =
    1278             :       left ? jsgraph()->ZeroConstant()
    1279             :            : graph()->NewNode(simplified()->NumberSubtract(), original_length,
    1280         898 :                               jsgraph()->OneConstant());
    1281             :   const Operator* next_op =
    1282         748 :       left ? simplified()->NumberAdd() : simplified()->NumberSubtract();
    1283         374 :   Node* k = initial_index;
    1284             : 
    1285             :   Node* check_frame_state;
    1286             :   {
    1287             :     Builtins::Name builtin_lazy =
    1288             :         left ? Builtins::kArrayReduceLoopLazyDeoptContinuation
    1289         374 :              : Builtins::kArrayReduceRightLoopLazyDeoptContinuation;
    1290             :     const std::vector<Node*> checkpoint_params(
    1291             :         {receiver, fncallback, k, original_length,
    1292        1122 :          jsgraph()->UndefinedConstant()});
    1293         748 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1294             :     check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1295             :         jsgraph(), shared, builtin_lazy, node->InputAt(0), context,
    1296             :         checkpoint_params.data(), stack_parameters - 1, outer_frame_state,
    1297         748 :         ContinuationFrameStateMode::LAZY);
    1298             :   }
    1299         374 :   Node* check_fail = nullptr;
    1300         374 :   Node* check_throw = nullptr;
    1301             :   // Check whether the given callback function is callable. Note that
    1302             :   // this has to happen outside the loop to make sure we also throw on
    1303             :   // empty arrays.
    1304             :   WireInCallbackIsCallableCheck(fncallback, context, check_frame_state, effect,
    1305         374 :                                 &control, &check_fail, &check_throw);
    1306             : 
    1307             :   // Set initial accumulator value
    1308         374 :   Node* cur = jsgraph()->TheHoleConstant();
    1309             : 
    1310         748 :   if (node->op()->ValueInputCount() > 3) {
    1311          28 :     cur = NodeProperties::GetValueInput(node, 3);
    1312             :   } else {
    1313             :     // Find first/last non holey element. In case the search fails, we need a
    1314             :     // deopt continuation.
    1315             :     Builtins::Name builtin_eager =
    1316             :         left ? Builtins::kArrayReducePreLoopEagerDeoptContinuation
    1317         346 :              : Builtins::kArrayReduceRightPreLoopEagerDeoptContinuation;
    1318             :     const std::vector<Node*> checkpoint_params(
    1319         692 :         {receiver, fncallback, original_length});
    1320         692 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1321             :     Node* find_first_element_frame_state =
    1322             :         CreateJavaScriptBuiltinContinuationFrameState(
    1323             :             jsgraph(), shared, builtin_eager, node->InputAt(0), context,
    1324             :             checkpoint_params.data(), stack_parameters, outer_frame_state,
    1325         346 :             ContinuationFrameStateMode::EAGER);
    1326             : 
    1327         346 :     Node* vloop = k = WireInLoopStart(k, &control, &effect);
    1328         346 :     Node* loop = control;
    1329         346 :     Node* eloop = effect;
    1330             :     effect = graph()->NewNode(common()->Checkpoint(),
    1331         692 :                               find_first_element_frame_state, effect, control);
    1332             :     Node* continue_test =
    1333             :         left ? graph()->NewNode(simplified()->NumberLessThan(), k,
    1334         420 :                                 original_length)
    1335             :              : graph()->NewNode(simplified()->NumberLessThanOrEqual(),
    1336         754 :                                 jsgraph()->ZeroConstant(), k);
    1337             :     effect = graph()->NewNode(
    1338             :         simplified()->CheckIf(DeoptimizeReason::kNoInitialElement),
    1339        1038 :         continue_test, effect, control);
    1340             : 
    1341         346 :     cur = SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
    1342         346 :     Node* next_k = graph()->NewNode(next_op, k, jsgraph()->OneConstant());
    1343             : 
    1344             :     Node* hole_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    1345         692 :                                          hole_check(cur), control);
    1346         346 :     Node* found_el = graph()->NewNode(common()->IfFalse(), hole_branch);
    1347         346 :     control = found_el;
    1348         346 :     Node* is_hole = graph()->NewNode(common()->IfTrue(), hole_branch);
    1349             : 
    1350         346 :     WireInLoopEnd(loop, eloop, vloop, next_k, is_hole, effect);
    1351             :     // We did the hole-check, so exclude hole from the type.
    1352             :     cur = effect = graph()->NewNode(common()->TypeGuard(Type::NonInternal()),
    1353        1038 :                                     cur, effect, control);
    1354         346 :     k = next_k;
    1355             :   }
    1356             : 
    1357             :   // Start the loop.
    1358        1122 :   Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
    1359             :   Node* eloop = effect =
    1360        1122 :       graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    1361         374 :   Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
    1362         374 :   NodeProperties::MergeControlToEnd(graph(), common(), terminate);
    1363             :   Node* kloop = k = graph()->NewNode(
    1364        1122 :       common()->Phi(MachineRepresentation::kTagged, 2), k, k, loop);
    1365             :   Node* curloop = cur = graph()->NewNode(
    1366         374 :       common()->Phi(MachineRepresentation::kTagged, 2), cur, cur, loop);
    1367             : 
    1368         374 :   control = loop;
    1369         374 :   effect = eloop;
    1370             : 
    1371             :   Node* continue_test =
    1372             :       left
    1373         448 :           ? graph()->NewNode(simplified()->NumberLessThan(), k, original_length)
    1374             :           : graph()->NewNode(simplified()->NumberLessThanOrEqual(),
    1375         824 :                              jsgraph()->ZeroConstant(), k);
    1376             : 
    1377             :   Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    1378         748 :                                            continue_test, control);
    1379             : 
    1380         374 :   Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
    1381         374 :   Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
    1382         374 :   control = if_true;
    1383             : 
    1384             :   {
    1385             :     Builtins::Name builtin_eager =
    1386             :         left ? Builtins::kArrayReduceLoopEagerDeoptContinuation
    1387         374 :              : Builtins::kArrayReduceRightLoopEagerDeoptContinuation;
    1388             :     const std::vector<Node*> checkpoint_params(
    1389         748 :         {receiver, fncallback, k, original_length, curloop});
    1390         748 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1391             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1392             :         jsgraph(), shared, builtin_eager, node->InputAt(0), context,
    1393             :         checkpoint_params.data(), stack_parameters, outer_frame_state,
    1394         374 :         ContinuationFrameStateMode::EAGER);
    1395             :     effect =
    1396        1122 :         graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
    1397             :   }
    1398             : 
    1399             :   // Make sure the map hasn't changed during the iteration
    1400             :   effect = graph()->NewNode(
    1401             :       simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
    1402        1122 :       effect, control);
    1403             : 
    1404             :   Node* element =
    1405         374 :       SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
    1406             : 
    1407         374 :   Node* next_k = graph()->NewNode(next_op, k, jsgraph()->OneConstant());
    1408             : 
    1409             :   Node* hole_true = nullptr;
    1410             :   Node* hole_false = nullptr;
    1411         374 :   Node* effect_true = effect;
    1412             : 
    1413         748 :   if (IsHoleyElementsKind(kind)) {
    1414             :     // Holey elements kind require a hole check and skipping of the element in
    1415             :     // the case of a hole.
    1416             :     Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
    1417         192 :                                     hole_check(element), control);
    1418          96 :     hole_true = graph()->NewNode(common()->IfTrue(), branch);
    1419          96 :     hole_false = graph()->NewNode(common()->IfFalse(), branch);
    1420          96 :     control = hole_false;
    1421             : 
    1422             :     // The contract is that we don't leak "the hole" into "user JavaScript",
    1423             :     // so we must rename the {element} here to explicitly exclude "the hole"
    1424             :     // from the type of {element}.
    1425             :     element = effect = graph()->NewNode(
    1426         288 :         common()->TypeGuard(Type::NonInternal()), element, effect, control);
    1427             :   }
    1428             : 
    1429             :   Node* next_cur;
    1430             :   {
    1431             :     Builtins::Name builtin_lazy =
    1432             :         left ? Builtins::kArrayReduceLoopLazyDeoptContinuation
    1433         374 :              : Builtins::kArrayReduceRightLoopLazyDeoptContinuation;
    1434             :     const std::vector<Node*> checkpoint_params(
    1435         748 :         {receiver, fncallback, next_k, original_length, curloop});
    1436         748 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1437             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1438             :         jsgraph(), shared, builtin_lazy, node->InputAt(0), context,
    1439             :         checkpoint_params.data(), stack_parameters - 1, outer_frame_state,
    1440         748 :         ContinuationFrameStateMode::LAZY);
    1441             : 
    1442             :     next_cur = control = effect =
    1443         374 :         graph()->NewNode(javascript()->Call(6, p.frequency()), fncallback,
    1444             :                          jsgraph()->UndefinedConstant(), cur, element, k,
    1445        1496 :                          receiver, context, frame_state, effect, control);
    1446             :   }
    1447             : 
    1448             :   // Rewire potential exception edges.
    1449         374 :   Node* on_exception = nullptr;
    1450         374 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    1451             :     RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
    1452         166 :                                      &check_fail, &control);
    1453             :   }
    1454             : 
    1455         748 :   if (IsHoleyElementsKind(kind)) {
    1456          96 :     Node* after_call_control = control;
    1457          96 :     Node* after_call_effect = effect;
    1458          96 :     control = hole_true;
    1459          96 :     effect = effect_true;
    1460             : 
    1461         192 :     control = graph()->NewNode(common()->Merge(2), control, after_call_control);
    1462             :     effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
    1463         288 :                               control);
    1464             :     next_cur =
    1465             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), cur,
    1466         192 :                          next_cur, control);
    1467             :   }
    1468             : 
    1469         374 :   k = next_k;
    1470             :   cur = next_cur;
    1471             : 
    1472         374 :   loop->ReplaceInput(1, control);
    1473         374 :   kloop->ReplaceInput(1, k);
    1474         374 :   curloop->ReplaceInput(1, cur);
    1475         374 :   eloop->ReplaceInput(1, effect);
    1476             : 
    1477         374 :   control = if_false;
    1478         374 :   effect = eloop;
    1479             : 
    1480             :   // Wire up the branch for the case when IsCallable fails for the callback.
    1481             :   // Since {check_throw} is an unconditional throw, it's impossible to
    1482             :   // return a successful completion. Therefore, we simply connect the successful
    1483             :   // completion to the graph end.
    1484             :   Node* throw_node =
    1485         748 :       graph()->NewNode(common()->Throw(), check_throw, check_fail);
    1486         374 :   NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
    1487             : 
    1488         374 :   ReplaceWithValue(node, curloop, effect, control);
    1489             :   return Replace(curloop);
    1490             : }
    1491             : 
    1492        1360 : Reduction JSCallReducer::ReduceArrayMap(Node* node,
    1493        3654 :                                         const SharedFunctionInfoRef& shared) {
    1494         348 :   if (!FLAG_turbo_inline_array_builtins) return NoChange();
    1495             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1496         348 :   CallParameters const& p = CallParametersOf(node->op());
    1497         348 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    1498             :     return NoChange();
    1499             :   }
    1500             : 
    1501         332 :   Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
    1502         332 :   Node* effect = NodeProperties::GetEffectInput(node);
    1503         332 :   Node* control = NodeProperties::GetControlInput(node);
    1504         332 :   Node* context = NodeProperties::GetContextInput(node);
    1505             : 
    1506             :   // Try to determine the {receiver} map.
    1507         332 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1508         332 :   Node* fncallback = node->op()->ValueInputCount() > 2
    1509             :                          ? NodeProperties::GetValueInput(node, 2)
    1510         332 :                          : jsgraph()->UndefinedConstant();
    1511         332 :   Node* this_arg = node->op()->ValueInputCount() > 3
    1512             :                        ? NodeProperties::GetValueInput(node, 3)
    1513         659 :                        : jsgraph()->UndefinedConstant();
    1514             :   ZoneHandleSet<Map> receiver_maps;
    1515             :   NodeProperties::InferReceiverMapsResult result =
    1516             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    1517         664 :                                         &receiver_maps);
    1518         332 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    1519             : 
    1520             :   // Ensure that any changes to the Array species constructor cause deopt.
    1521         332 :   if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
    1522             : 
    1523             :   ElementsKind kind;
    1524         329 :   if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
    1525             :     return NoChange();
    1526             :   }
    1527             : 
    1528         652 :   if (IsHoleyElementsKind(kind)) {
    1529             :     dependencies()->DependOnProtector(
    1530          21 :         PropertyCellRef(broker(), factory()->no_elements_protector()));
    1531             :   }
    1532             : 
    1533             :   dependencies()->DependOnProtector(
    1534         326 :       PropertyCellRef(broker(), factory()->array_species_protector()));
    1535             : 
    1536             :   Node* array_constructor = jsgraph()->Constant(
    1537         978 :       native_context().GetInitialJSArrayMap(kind).GetConstructor());
    1538             : 
    1539         326 :   Node* k = jsgraph()->ZeroConstant();
    1540             : 
    1541             :   // If we have unreliable maps, we need a map check.
    1542         326 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    1543             :     effect =
    1544             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    1545          10 :                                                  receiver_maps, p.feedback()),
    1546          30 :                          receiver, effect, control);
    1547             :   }
    1548             : 
    1549             :   Node* original_length = effect = graph()->NewNode(
    1550         326 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    1551        1304 :       effect, control);
    1552             : 
    1553             :   // Even though {JSCreateArray} is not marked as {kNoThrow}, we can elide the
    1554             :   // exceptional projections because it cannot throw with the given parameters.
    1555             :   Node* a = control = effect = graph()->NewNode(
    1556             :       javascript()->CreateArray(1, MaybeHandle<AllocationSite>()),
    1557             :       array_constructor, array_constructor, original_length, context,
    1558         978 :       outer_frame_state, effect, control);
    1559             : 
    1560             :   std::vector<Node*> checkpoint_params(
    1561         652 :       {receiver, fncallback, this_arg, a, k, original_length});
    1562         652 :   const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1563             : 
    1564             :   // Check whether the given callback function is callable. Note that this has
    1565             :   // to happen outside the loop to make sure we also throw on empty arrays.
    1566             :   Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1567             :       jsgraph(), shared, Builtins::kArrayMapLoopLazyDeoptContinuation,
    1568             :       node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1569         326 :       outer_frame_state, ContinuationFrameStateMode::LAZY);
    1570         326 :   Node* check_fail = nullptr;
    1571         326 :   Node* check_throw = nullptr;
    1572             :   WireInCallbackIsCallableCheck(fncallback, context, check_frame_state, effect,
    1573         326 :                                 &control, &check_fail, &check_throw);
    1574             : 
    1575             :   // Start the loop.
    1576         326 :   Node* vloop = k = WireInLoopStart(k, &control, &effect);
    1577         326 :   Node *loop = control, *eloop = effect;
    1578         326 :   checkpoint_params[4] = k;
    1579             : 
    1580             :   Node* continue_test =
    1581         326 :       graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
    1582             :   Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    1583         652 :                                            continue_test, control);
    1584             : 
    1585         326 :   Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
    1586         326 :   Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
    1587         326 :   control = if_true;
    1588             : 
    1589             :   Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1590             :       jsgraph(), shared, Builtins::kArrayMapLoopEagerDeoptContinuation,
    1591         326 :       node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1592         326 :       outer_frame_state, ContinuationFrameStateMode::EAGER);
    1593             : 
    1594             :   effect =
    1595         978 :       graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
    1596             : 
    1597             :   // Make sure the map hasn't changed during the iteration
    1598             :   effect =
    1599             :       graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    1600         326 :                                                receiver_maps, p.feedback()),
    1601         978 :                        receiver, effect, control);
    1602             : 
    1603             :   Node* element =
    1604         326 :       SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
    1605             : 
    1606             :   Node* next_k =
    1607         652 :       graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
    1608             : 
    1609             :   Node* hole_true = nullptr;
    1610             :   Node* hole_false = nullptr;
    1611         326 :   Node* effect_true = effect;
    1612             : 
    1613         652 :   if (IsHoleyElementsKind(kind)) {
    1614             :     // Holey elements kind require a hole check and skipping of the element in
    1615             :     // the case of a hole.
    1616             :     Node* check;
    1617          21 :     if (IsDoubleElementsKind(kind)) {
    1618           5 :       check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
    1619             :     } else {
    1620             :       check = graph()->NewNode(simplified()->ReferenceEqual(), element,
    1621          32 :                                jsgraph()->TheHoleConstant());
    1622             :     }
    1623             :     Node* branch =
    1624          42 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    1625          21 :     hole_true = graph()->NewNode(common()->IfTrue(), branch);
    1626          21 :     hole_false = graph()->NewNode(common()->IfFalse(), branch);
    1627          21 :     control = hole_false;
    1628             : 
    1629             :     // The contract is that we don't leak "the hole" into "user JavaScript",
    1630             :     // so we must rename the {element} here to explicitly exclude "the hole"
    1631             :     // from the type of {element}.
    1632             :     element = effect = graph()->NewNode(
    1633          63 :         common()->TypeGuard(Type::NonInternal()), element, effect, control);
    1634             :   }
    1635             : 
    1636             :   // This frame state is dealt with by hand in
    1637             :   // ArrayMapLoopLazyDeoptContinuation.
    1638             :   frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1639             :       jsgraph(), shared, Builtins::kArrayMapLoopLazyDeoptContinuation,
    1640         326 :       node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1641         326 :       outer_frame_state, ContinuationFrameStateMode::LAZY);
    1642             : 
    1643             :   Node* callback_value = control = effect = graph()->NewNode(
    1644         326 :       javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
    1645         978 :       receiver, context, frame_state, effect, control);
    1646             : 
    1647             :   // Rewire potential exception edges.
    1648         326 :   Node* on_exception = nullptr;
    1649         326 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    1650             :     RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
    1651          30 :                                      &check_fail, &control);
    1652             :   }
    1653             : 
    1654             :   // The array {a} should be HOLEY_SMI_ELEMENTS because we'd only come into this
    1655             :   // loop if the input array length is non-zero, and "new Array({x > 0})" always
    1656             :   // produces a HOLEY array.
    1657             :   MapRef holey_double_map =
    1658         326 :       native_context().GetInitialJSArrayMap(HOLEY_DOUBLE_ELEMENTS);
    1659         326 :   MapRef holey_map = native_context().GetInitialJSArrayMap(HOLEY_ELEMENTS);
    1660             :   effect = graph()->NewNode(simplified()->TransitionAndStoreElement(
    1661             :                                 holey_double_map.object(), holey_map.object()),
    1662         978 :                             a, k, callback_value, effect, control);
    1663             : 
    1664         652 :   if (IsHoleyElementsKind(kind)) {
    1665          21 :     Node* after_call_and_store_control = control;
    1666             :     Node* after_call_and_store_effect = effect;
    1667          21 :     control = hole_true;
    1668          21 :     effect = effect_true;
    1669             : 
    1670             :     control = graph()->NewNode(common()->Merge(2), control,
    1671          42 :                                after_call_and_store_control);
    1672             :     effect = graph()->NewNode(common()->EffectPhi(2), effect,
    1673          63 :                               after_call_and_store_effect, control);
    1674             :   }
    1675             : 
    1676         326 :   WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
    1677             : 
    1678         326 :   control = if_false;
    1679         326 :   effect = eloop;
    1680             : 
    1681             :   // Wire up the branch for the case when IsCallable fails for the callback.
    1682             :   // Since {check_throw} is an unconditional throw, it's impossible to
    1683             :   // return a successful completion. Therefore, we simply connect the successful
    1684             :   // completion to the graph end.
    1685             :   Node* throw_node =
    1686         652 :       graph()->NewNode(common()->Throw(), check_throw, check_fail);
    1687         326 :   NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
    1688             : 
    1689         326 :   ReplaceWithValue(node, a, effect, control);
    1690             :   return Replace(a);
    1691             : }
    1692             : 
    1693         223 : Reduction JSCallReducer::ReduceArrayFilter(
    1694        3251 :     Node* node, const SharedFunctionInfoRef& shared) {
    1695         223 :   if (!FLAG_turbo_inline_array_builtins) return NoChange();
    1696             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1697         223 :   CallParameters const& p = CallParametersOf(node->op());
    1698         223 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    1699             :     return NoChange();
    1700             :   }
    1701             : 
    1702         207 :   Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
    1703         207 :   Node* effect = NodeProperties::GetEffectInput(node);
    1704         207 :   Node* control = NodeProperties::GetControlInput(node);
    1705         207 :   Node* context = NodeProperties::GetContextInput(node);
    1706             :   // Try to determine the {receiver} map.
    1707         207 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1708         207 :   Node* fncallback = node->op()->ValueInputCount() > 2
    1709             :                          ? NodeProperties::GetValueInput(node, 2)
    1710         207 :                          : jsgraph()->UndefinedConstant();
    1711         207 :   Node* this_arg = node->op()->ValueInputCount() > 3
    1712             :                        ? NodeProperties::GetValueInput(node, 3)
    1713         409 :                        : jsgraph()->UndefinedConstant();
    1714             :   ZoneHandleSet<Map> receiver_maps;
    1715             :   NodeProperties::InferReceiverMapsResult result =
    1716             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    1717         414 :                                         &receiver_maps);
    1718         207 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    1719             : 
    1720             :   // And ensure that any changes to the Array species constructor cause deopt.
    1721         197 :   if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
    1722             : 
    1723             :   ElementsKind kind;
    1724         197 :   if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
    1725             :     return NoChange();
    1726             :   }
    1727             : 
    1728             :   // The output array is packed (filter doesn't visit holes).
    1729         164 :   const ElementsKind packed_kind = GetPackedElementsKind(kind);
    1730             : 
    1731         164 :   if (IsHoleyElementsKind(kind)) {
    1732             :     dependencies()->DependOnProtector(
    1733          15 :         PropertyCellRef(broker(), factory()->no_elements_protector()));
    1734             :   }
    1735             : 
    1736             :   dependencies()->DependOnProtector(
    1737         164 :       PropertyCellRef(broker(), factory()->array_species_protector()));
    1738             : 
    1739         328 :   MapRef initial_map = native_context().GetInitialJSArrayMap(packed_kind);
    1740             : 
    1741         164 :   Node* k = jsgraph()->ZeroConstant();
    1742         164 :   Node* to = jsgraph()->ZeroConstant();
    1743             : 
    1744             :   // If we have unreliable maps, we need a map check.
    1745         164 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    1746             :     effect =
    1747             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    1748           5 :                                                  receiver_maps, p.feedback()),
    1749          15 :                          receiver, effect, control);
    1750             :   }
    1751             : 
    1752             :   Node* a;  // Construct the output array.
    1753             :   {
    1754         164 :     AllocationBuilder ab(jsgraph(), effect, control);
    1755         164 :     ab.Allocate(initial_map.instance_size(), NOT_TENURED, Type::Array());
    1756         164 :     ab.Store(AccessBuilder::ForMap(), initial_map);
    1757         164 :     Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
    1758         164 :     ab.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array);
    1759         164 :     ab.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
    1760             :     ab.Store(AccessBuilder::ForJSArrayLength(packed_kind),
    1761         164 :              jsgraph()->ZeroConstant());
    1762         164 :     for (int i = 0; i < initial_map.GetInObjectProperties(); ++i) {
    1763             :       ab.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
    1764           0 :                jsgraph()->UndefinedConstant());
    1765             :     }
    1766         164 :     a = effect = ab.Finish();
    1767             :   }
    1768             : 
    1769             :   Node* original_length = effect = graph()->NewNode(
    1770         164 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    1771         656 :       effect, control);
    1772             : 
    1773             :   // Check whether the given callback function is callable. Note that this has
    1774             :   // to happen outside the loop to make sure we also throw on empty arrays.
    1775         164 :   Node* check_fail = nullptr;
    1776         164 :   Node* check_throw = nullptr;
    1777             :   {
    1778             :     // This frame state doesn't ever call the deopt continuation, it's only
    1779             :     // necessary to specifiy a continuation in order to handle the exceptional
    1780             :     // case. We don't have all the values available to completely fill out
    1781             :     // checkpoint_params yet, but that's okay because it'll never be called.
    1782             :     // Therefore, "to" is mentioned twice, once standing in for the k_value
    1783             :     // value.
    1784             :     std::vector<Node*> checkpoint_params(
    1785         328 :         {receiver, fncallback, this_arg, a, k, original_length, to, to});
    1786         328 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1787             : 
    1788             :     Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1789             :         jsgraph(), shared, Builtins::kArrayFilterLoopLazyDeoptContinuation,
    1790             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1791         164 :         outer_frame_state, ContinuationFrameStateMode::LAZY);
    1792             :     WireInCallbackIsCallableCheck(fncallback, context, check_frame_state,
    1793         164 :                                   effect, &control, &check_fail, &check_throw);
    1794             :   }
    1795             : 
    1796             :   // Start the loop.
    1797         164 :   Node* vloop = k = WireInLoopStart(k, &control, &effect);
    1798         164 :   Node *loop = control, *eloop = effect;
    1799             :   Node* v_to_loop = to = graph()->NewNode(
    1800         164 :       common()->Phi(MachineRepresentation::kTaggedSigned, 2), to, to, loop);
    1801             : 
    1802             :   Node* continue_test =
    1803         328 :       graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
    1804             :   Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    1805         328 :                                            continue_test, control);
    1806             : 
    1807         164 :   Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
    1808         164 :   Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
    1809         164 :   control = if_true;
    1810             : 
    1811             :   {
    1812             :     std::vector<Node*> checkpoint_params(
    1813         328 :         {receiver, fncallback, this_arg, a, k, original_length, to});
    1814         328 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1815             : 
    1816             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1817             :         jsgraph(), shared, Builtins::kArrayFilterLoopEagerDeoptContinuation,
    1818             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1819         164 :         outer_frame_state, ContinuationFrameStateMode::EAGER);
    1820             : 
    1821             :     effect =
    1822         492 :         graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
    1823             :   }
    1824             : 
    1825             :   // Make sure the map hasn't changed during the iteration.
    1826             :   effect =
    1827             :       graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    1828         164 :                                                receiver_maps, p.feedback()),
    1829         492 :                        receiver, effect, control);
    1830             : 
    1831             :   Node* element =
    1832         164 :       SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
    1833             : 
    1834             :   Node* next_k =
    1835         328 :       graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
    1836             : 
    1837             :   Node* hole_true = nullptr;
    1838             :   Node* hole_false = nullptr;
    1839         164 :   Node* effect_true = effect;
    1840             :   Node* hole_true_vto = to;
    1841             : 
    1842         328 :   if (IsHoleyElementsKind(kind)) {
    1843             :     // Holey elements kind require a hole check and skipping of the element in
    1844             :     // the case of a hole.
    1845             :     Node* check;
    1846          15 :     if (IsDoubleElementsKind(kind)) {
    1847           5 :       check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
    1848             :     } else {
    1849             :       check = graph()->NewNode(simplified()->ReferenceEqual(), element,
    1850          20 :                                jsgraph()->TheHoleConstant());
    1851             :     }
    1852             :     Node* branch =
    1853          30 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    1854          15 :     hole_true = graph()->NewNode(common()->IfTrue(), branch);
    1855          15 :     hole_false = graph()->NewNode(common()->IfFalse(), branch);
    1856          15 :     control = hole_false;
    1857             : 
    1858             :     // The contract is that we don't leak "the hole" into "user JavaScript",
    1859             :     // so we must rename the {element} here to explicitly exclude "the hole"
    1860             :     // from the type of {element}.
    1861             :     element = effect = graph()->NewNode(
    1862          45 :         common()->TypeGuard(Type::NonInternal()), element, effect, control);
    1863             :   }
    1864             : 
    1865             :   Node* callback_value = nullptr;
    1866             :   {
    1867             :     // This frame state is dealt with by hand in
    1868             :     // Builtins::kArrayFilterLoopLazyDeoptContinuation.
    1869             :     std::vector<Node*> checkpoint_params(
    1870         328 :         {receiver, fncallback, this_arg, a, k, original_length, element, to});
    1871         328 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1872             : 
    1873             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1874             :         jsgraph(), shared, Builtins::kArrayFilterLoopLazyDeoptContinuation,
    1875             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1876         164 :         outer_frame_state, ContinuationFrameStateMode::LAZY);
    1877             : 
    1878             :     callback_value = control = effect = graph()->NewNode(
    1879         164 :         javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
    1880         492 :         receiver, context, frame_state, effect, control);
    1881             :   }
    1882             : 
    1883             :   // Rewire potential exception edges.
    1884         164 :   Node* on_exception = nullptr;
    1885         164 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    1886             :     RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
    1887          22 :                                      &check_fail, &control);
    1888             :   }
    1889             : 
    1890             :   // We need an eager frame state for right after the callback function
    1891             :   // returned, just in case an attempt to grow the output array fails.
    1892             :   //
    1893             :   // Note that we are intentionally reusing the
    1894             :   // Builtins::kArrayFilterLoopLazyDeoptContinuation as an *eager* entry
    1895             :   // point in this case. This is safe, because re-evaluating a [ToBoolean]
    1896             :   // coercion is safe.
    1897             :   {
    1898             :     std::vector<Node*> checkpoint_params({receiver, fncallback, this_arg, a, k,
    1899             :                                           original_length, element, to,
    1900         328 :                                           callback_value});
    1901         328 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    1902             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    1903             :         jsgraph(), shared, Builtins::kArrayFilterLoopLazyDeoptContinuation,
    1904             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    1905         164 :         outer_frame_state, ContinuationFrameStateMode::EAGER);
    1906             : 
    1907             :     effect =
    1908         492 :         graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
    1909             :   }
    1910             : 
    1911             :   // We have to coerce callback_value to boolean, and only store the element in
    1912             :   // a if it's true. The checkpoint above protects against the case that
    1913             :   // growing {a} fails.
    1914             :   to = DoFilterPostCallbackWork(packed_kind, &control, &effect, a, to, element,
    1915         164 :                                 callback_value);
    1916             : 
    1917         328 :   if (IsHoleyElementsKind(kind)) {
    1918          15 :     Node* after_call_control = control;
    1919          15 :     Node* after_call_effect = effect;
    1920          15 :     control = hole_true;
    1921          15 :     effect = effect_true;
    1922             : 
    1923          30 :     control = graph()->NewNode(common()->Merge(2), control, after_call_control);
    1924             :     effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
    1925          45 :                               control);
    1926             :     to =
    1927             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTaggedSigned, 2),
    1928          30 :                          hole_true_vto, to, control);
    1929             :   }
    1930             : 
    1931         164 :   WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
    1932         164 :   v_to_loop->ReplaceInput(1, to);
    1933             : 
    1934         164 :   control = if_false;
    1935         164 :   effect = eloop;
    1936             : 
    1937             :   // Wire up the branch for the case when IsCallable fails for the callback.
    1938             :   // Since {check_throw} is an unconditional throw, it's impossible to
    1939             :   // return a successful completion. Therefore, we simply connect the successful
    1940             :   // completion to the graph end.
    1941             :   Node* throw_node =
    1942         328 :       graph()->NewNode(common()->Throw(), check_throw, check_fail);
    1943         164 :   NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
    1944             : 
    1945         164 :   ReplaceWithValue(node, a, effect, control);
    1946             :   return Replace(a);
    1947             : }
    1948             : 
    1949        1072 : Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
    1950        2725 :                                          const SharedFunctionInfoRef& shared) {
    1951         283 :   if (!FLAG_turbo_inline_array_builtins) return NoChange();
    1952             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    1953         283 :   CallParameters const& p = CallParametersOf(node->op());
    1954         283 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    1955             :     return NoChange();
    1956             :   }
    1957             : 
    1958             :   Builtins::Name eager_continuation_builtin;
    1959             :   Builtins::Name lazy_continuation_builtin;
    1960             :   Builtins::Name after_callback_lazy_continuation_builtin;
    1961         253 :   if (variant == ArrayFindVariant::kFind) {
    1962             :     eager_continuation_builtin = Builtins::kArrayFindLoopEagerDeoptContinuation;
    1963             :     lazy_continuation_builtin = Builtins::kArrayFindLoopLazyDeoptContinuation;
    1964             :     after_callback_lazy_continuation_builtin =
    1965             :         Builtins::kArrayFindLoopAfterCallbackLazyDeoptContinuation;
    1966             :   } else {
    1967             :     DCHECK_EQ(ArrayFindVariant::kFindIndex, variant);
    1968             :     eager_continuation_builtin =
    1969             :         Builtins::kArrayFindIndexLoopEagerDeoptContinuation;
    1970             :     lazy_continuation_builtin =
    1971             :         Builtins::kArrayFindIndexLoopLazyDeoptContinuation;
    1972             :     after_callback_lazy_continuation_builtin =
    1973             :         Builtins::kArrayFindIndexLoopAfterCallbackLazyDeoptContinuation;
    1974             :   }
    1975             : 
    1976         253 :   Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
    1977         253 :   Node* effect = NodeProperties::GetEffectInput(node);
    1978         253 :   Node* control = NodeProperties::GetControlInput(node);
    1979         253 :   Node* context = NodeProperties::GetContextInput(node);
    1980             : 
    1981             :   // Try to determine the {receiver} map.
    1982         253 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    1983         253 :   Node* fncallback = node->op()->ValueInputCount() > 2
    1984             :                          ? NodeProperties::GetValueInput(node, 2)
    1985         253 :                          : jsgraph()->UndefinedConstant();
    1986         253 :   Node* this_arg = node->op()->ValueInputCount() > 3
    1987             :                        ? NodeProperties::GetValueInput(node, 3)
    1988         496 :                        : jsgraph()->UndefinedConstant();
    1989             :   ZoneHandleSet<Map> receiver_maps;
    1990             :   NodeProperties::InferReceiverMapsResult result =
    1991             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    1992         506 :                                         &receiver_maps);
    1993         253 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    1994             : 
    1995             :   ElementsKind kind;
    1996         253 :   if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
    1997             :     return NoChange();
    1998             :   }
    1999             : 
    2000             :   // Install code dependencies on the {receiver} prototype maps and the
    2001             :   // global array protector cell.
    2002             :   dependencies()->DependOnProtector(
    2003         247 :       PropertyCellRef(broker(), factory()->no_elements_protector()));
    2004             : 
    2005             :   // If we have unreliable maps, we need a map check.
    2006         247 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    2007             :     effect =
    2008             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    2009          10 :                                                  receiver_maps, p.feedback()),
    2010          30 :                          receiver, effect, control);
    2011             :   }
    2012             : 
    2013         247 :   Node* k = jsgraph()->ZeroConstant();
    2014             : 
    2015             :   Node* original_length = effect = graph()->NewNode(
    2016         247 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    2017         988 :       effect, control);
    2018             : 
    2019             :   std::vector<Node*> checkpoint_params(
    2020         494 :       {receiver, fncallback, this_arg, k, original_length});
    2021         494 :   const int stack_parameters = static_cast<int>(checkpoint_params.size());
    2022             : 
    2023             :   // Check whether the given callback function is callable. Note that this has
    2024             :   // to happen outside the loop to make sure we also throw on empty arrays.
    2025         247 :   Node* check_fail = nullptr;
    2026         247 :   Node* check_throw = nullptr;
    2027             :   {
    2028             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    2029             :         jsgraph(), shared, lazy_continuation_builtin, node->InputAt(0), context,
    2030             :         &checkpoint_params[0], stack_parameters, outer_frame_state,
    2031         247 :         ContinuationFrameStateMode::LAZY);
    2032             :     WireInCallbackIsCallableCheck(fncallback, context, frame_state, effect,
    2033         247 :                                   &control, &check_fail, &check_throw);
    2034             :   }
    2035             : 
    2036             :   // Start the loop.
    2037         247 :   Node* vloop = k = WireInLoopStart(k, &control, &effect);
    2038         247 :   Node *loop = control, *eloop = effect;
    2039         247 :   checkpoint_params[3] = k;
    2040             : 
    2041             :   // Check if we've iterated past the last element of the array.
    2042             :   Node* if_false = nullptr;
    2043             :   {
    2044             :     Node* continue_test =
    2045         247 :         graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
    2046             :     Node* continue_branch = graph()->NewNode(
    2047         494 :         common()->Branch(BranchHint::kTrue), continue_test, control);
    2048         494 :     control = graph()->NewNode(common()->IfTrue(), continue_branch);
    2049         247 :     if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
    2050             :   }
    2051             : 
    2052             :   // Check the map hasn't changed during the iteration.
    2053             :   {
    2054             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    2055             :         jsgraph(), shared, eager_continuation_builtin, node->InputAt(0),
    2056         247 :         context, &checkpoint_params[0], stack_parameters, outer_frame_state,
    2057         247 :         ContinuationFrameStateMode::EAGER);
    2058             : 
    2059             :     effect =
    2060         741 :         graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
    2061             : 
    2062             :     effect =
    2063             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    2064         247 :                                                  receiver_maps, p.feedback()),
    2065         741 :                          receiver, effect, control);
    2066             :   }
    2067             : 
    2068             :   // Load k-th element from receiver.
    2069             :   Node* element =
    2070         247 :       SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
    2071             : 
    2072             :   // Increment k for the next iteration.
    2073         247 :   Node* next_k = checkpoint_params[3] =
    2074         741 :       graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
    2075             : 
    2076             :   // Replace holes with undefined.
    2077         247 :   if (kind == HOLEY_DOUBLE_ELEMENTS) {
    2078             :     // TODO(7409): avoid deopt if not all uses of value are truncated.
    2079             :     CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
    2080             :     element = effect =
    2081             :         graph()->NewNode(simplified()->CheckFloat64Hole(mode, p.feedback()),
    2082          51 :                          element, effect, control);
    2083         230 :   } else if (IsHoleyElementsKind(kind)) {
    2084             :     element =
    2085          20 :         graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), element);
    2086             :   }
    2087             : 
    2088             :   Node* if_found_return_value =
    2089         247 :       (variant == ArrayFindVariant::kFind) ? element : k;
    2090             : 
    2091             :   // Call the callback.
    2092             :   Node* callback_value = nullptr;
    2093             :   {
    2094             :     std::vector<Node*> call_checkpoint_params({receiver, fncallback, this_arg,
    2095             :                                                next_k, original_length,
    2096         494 :                                                if_found_return_value});
    2097             :     const int call_stack_parameters =
    2098         494 :         static_cast<int>(call_checkpoint_params.size());
    2099             : 
    2100             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    2101             :         jsgraph(), shared, after_callback_lazy_continuation_builtin,
    2102             :         node->InputAt(0), context, &call_checkpoint_params[0],
    2103             :         call_stack_parameters, outer_frame_state,
    2104         247 :         ContinuationFrameStateMode::LAZY);
    2105             : 
    2106             :     callback_value = control = effect = graph()->NewNode(
    2107         247 :         javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
    2108         741 :         receiver, context, frame_state, effect, control);
    2109             :   }
    2110             : 
    2111             :   // Rewire potential exception edges.
    2112         247 :   Node* on_exception = nullptr;
    2113         247 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    2114             :     RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
    2115          30 :                                      &check_fail, &control);
    2116             :   }
    2117             : 
    2118             :   // Check whether the given callback function returned a truthy value.
    2119             :   Node* boolean_result =
    2120         247 :       graph()->NewNode(simplified()->ToBoolean(), callback_value);
    2121         247 :   Node* efound_branch = effect;
    2122             :   Node* found_branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
    2123         494 :                                         boolean_result, control);
    2124         247 :   Node* if_found = graph()->NewNode(common()->IfTrue(), found_branch);
    2125         247 :   Node* if_notfound = graph()->NewNode(common()->IfFalse(), found_branch);
    2126         247 :   control = if_notfound;
    2127             : 
    2128             :   // Close the loop.
    2129         247 :   WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
    2130             : 
    2131         494 :   control = graph()->NewNode(common()->Merge(2), if_found, if_false);
    2132             :   effect =
    2133         494 :       graph()->NewNode(common()->EffectPhi(2), efound_branch, eloop, control);
    2134             : 
    2135             :   Node* if_not_found_value = (variant == ArrayFindVariant::kFind)
    2136             :                                  ? jsgraph()->UndefinedConstant()
    2137         494 :                                  : jsgraph()->MinusOneConstant();
    2138             :   Node* value =
    2139             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2140         494 :                        if_found_return_value, if_not_found_value, control);
    2141             : 
    2142             :   // Introduce proper LoopExit/LoopExitEffect/LoopExitValue to mark
    2143             :   // {loop} as a candidate for loop peeling (crbug.com/v8/8273).
    2144         741 :   control = graph()->NewNode(common()->LoopExit(), control, loop);
    2145         741 :   effect = graph()->NewNode(common()->LoopExitEffect(), effect, control);
    2146         494 :   value = graph()->NewNode(common()->LoopExitValue(), value, control);
    2147             : 
    2148             :   // Wire up the branch for the case when IsCallable fails for the callback.
    2149             :   // Since {check_throw} is an unconditional throw, it's impossible to
    2150             :   // return a successful completion. Therefore, we simply connect the successful
    2151             :   // completion to the graph end.
    2152             :   Node* throw_node =
    2153         494 :       graph()->NewNode(common()->Throw(), check_throw, check_fail);
    2154         247 :   NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
    2155             : 
    2156         247 :   ReplaceWithValue(node, value, effect, control);
    2157             :   return Replace(value);
    2158             : }
    2159             : 
    2160         164 : Node* JSCallReducer::DoFilterPostCallbackWork(ElementsKind kind, Node** control,
    2161             :                                               Node** effect, Node* a, Node* to,
    2162             :                                               Node* element,
    2163         164 :                                               Node* callback_value) {
    2164             :   Node* boolean_result =
    2165         164 :       graph()->NewNode(simplified()->ToBoolean(), callback_value);
    2166             :   Node* boolean_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2167         328 :                                           boolean_result, *control);
    2168             : 
    2169         164 :   Node* if_true = graph()->NewNode(common()->IfTrue(), boolean_branch);
    2170         164 :   Node* etrue = *effect;
    2171             :   Node* vtrue;
    2172             :   {
    2173             :     // Load the elements backing store of the {receiver}.
    2174             :     Node* elements = etrue = graph()->NewNode(
    2175             :         simplified()->LoadField(AccessBuilder::ForJSObjectElements()), a, etrue,
    2176         492 :         if_true);
    2177             : 
    2178             :     DCHECK(TypeCache::Get()->kFixedDoubleArrayLengthType.Is(
    2179             :         TypeCache::Get()->kFixedArrayLengthType));
    2180             :     Node* checked_to = etrue = graph()->NewNode(
    2181         164 :         common()->TypeGuard(TypeCache::Get()->kFixedArrayLengthType), to, etrue,
    2182         164 :         if_true);
    2183             :     Node* elements_length = etrue = graph()->NewNode(
    2184             :         simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), elements,
    2185         492 :         etrue, if_true);
    2186             : 
    2187             :     GrowFastElementsMode mode =
    2188             :         IsDoubleElementsKind(kind) ? GrowFastElementsMode::kDoubleElements
    2189         164 :                                    : GrowFastElementsMode::kSmiOrObjectElements;
    2190             :     elements = etrue = graph()->NewNode(
    2191             :         simplified()->MaybeGrowFastElements(mode, VectorSlotPair()), a,
    2192         492 :         elements, checked_to, elements_length, etrue, if_true);
    2193             : 
    2194             :     // Update the length of {a}.
    2195             :     Node* new_length_a = graph()->NewNode(simplified()->NumberAdd(), checked_to,
    2196         328 :                                           jsgraph()->OneConstant());
    2197             : 
    2198             :     etrue = graph()->NewNode(
    2199         164 :         simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)), a,
    2200         492 :         new_length_a, etrue, if_true);
    2201             : 
    2202             :     // Append the value to the {elements}.
    2203             :     etrue = graph()->NewNode(
    2204             :         simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(kind)),
    2205         492 :         elements, checked_to, element, etrue, if_true);
    2206             : 
    2207             :     vtrue = new_length_a;
    2208             :   }
    2209             : 
    2210         164 :   Node* if_false = graph()->NewNode(common()->IfFalse(), boolean_branch);
    2211         164 :   Node* efalse = *effect;
    2212             :   Node* vfalse = to;
    2213             : 
    2214         328 :   *control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    2215         328 :   *effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, *control);
    2216             :   to = graph()->NewNode(common()->Phi(MachineRepresentation::kTaggedSigned, 2),
    2217         328 :                         vtrue, vfalse, *control);
    2218         164 :   return to;
    2219             : }
    2220             : 
    2221        1786 : void JSCallReducer::WireInCallbackIsCallableCheck(
    2222             :     Node* fncallback, Node* context, Node* check_frame_state, Node* effect,
    2223        1786 :     Node** control, Node** check_fail, Node** check_throw) {
    2224        1786 :   Node* check = graph()->NewNode(simplified()->ObjectIsCallable(), fncallback);
    2225             :   Node* check_branch =
    2226        3572 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, *control);
    2227        3572 :   *check_fail = graph()->NewNode(common()->IfFalse(), check_branch);
    2228             :   *check_throw = *check_fail = graph()->NewNode(
    2229             :       javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
    2230             :       jsgraph()->Constant(
    2231             :           static_cast<int>(MessageTemplate::kCalledNonCallable)),
    2232        5358 :       fncallback, context, check_frame_state, effect, *check_fail);
    2233        3572 :   *control = graph()->NewNode(common()->IfTrue(), check_branch);
    2234        1786 : }
    2235             : 
    2236         347 : void JSCallReducer::RewirePostCallbackExceptionEdges(Node* check_throw,
    2237             :                                                      Node* on_exception,
    2238             :                                                      Node* effect,
    2239             :                                                      Node** check_fail,
    2240             :                                                      Node** control) {
    2241             :   // Create appropriate {IfException} and {IfSuccess} nodes.
    2242             :   Node* if_exception0 =
    2243         694 :       graph()->NewNode(common()->IfException(), check_throw, *check_fail);
    2244        1041 :   *check_fail = graph()->NewNode(common()->IfSuccess(), *check_fail);
    2245             :   Node* if_exception1 =
    2246         694 :       graph()->NewNode(common()->IfException(), effect, *control);
    2247        1041 :   *control = graph()->NewNode(common()->IfSuccess(), *control);
    2248             : 
    2249             :   // Join the exception edges.
    2250             :   Node* merge =
    2251         347 :       graph()->NewNode(common()->Merge(2), if_exception0, if_exception1);
    2252             :   Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception0,
    2253         347 :                                 if_exception1, merge);
    2254             :   Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2255         347 :                                if_exception0, if_exception1, merge);
    2256         347 :   ReplaceWithValue(on_exception, phi, ephi, merge);
    2257         347 : }
    2258             : 
    2259        2018 : Node* JSCallReducer::SafeLoadElement(ElementsKind kind, Node* receiver,
    2260             :                                      Node* control, Node** effect, Node** k,
    2261             :                                      const VectorSlotPair& feedback) {
    2262             :   // Make sure that the access is still in bounds, since the callback could have
    2263             :   // changed the array's size.
    2264             :   Node* length = *effect = graph()->NewNode(
    2265        2018 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    2266        8072 :       *effect, control);
    2267             :   *k = *effect = graph()->NewNode(simplified()->CheckBounds(feedback), *k,
    2268        6054 :                                   length, *effect, control);
    2269             : 
    2270             :   // Reload the elements pointer before calling the callback, since the previous
    2271             :   // callback might have resized the array causing the elements buffer to be
    2272             :   // re-allocated.
    2273             :   Node* elements = *effect = graph()->NewNode(
    2274             :       simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
    2275        6054 :       *effect, control);
    2276             : 
    2277             :   Node* element = *effect = graph()->NewNode(
    2278             :       simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(
    2279             :           kind, LoadSensitivity::kCritical)),
    2280        6054 :       elements, *k, *effect, control);
    2281        2018 :   return element;
    2282             : }
    2283             : 
    2284         540 : Reduction JSCallReducer::ReduceArrayEvery(Node* node,
    2285        1628 :                                           const SharedFunctionInfoRef& shared) {
    2286         135 :   if (!FLAG_turbo_inline_array_builtins) return NoChange();
    2287             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    2288         135 :   CallParameters const& p = CallParametersOf(node->op());
    2289         135 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    2290             :     return NoChange();
    2291             :   }
    2292             : 
    2293         135 :   Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
    2294         135 :   Node* effect = NodeProperties::GetEffectInput(node);
    2295         135 :   Node* control = NodeProperties::GetControlInput(node);
    2296         135 :   Node* context = NodeProperties::GetContextInput(node);
    2297             :   // Try to determine the {receiver} map.
    2298         135 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    2299         135 :   Node* fncallback = node->op()->ValueInputCount() > 2
    2300             :                          ? NodeProperties::GetValueInput(node, 2)
    2301         135 :                          : jsgraph()->UndefinedConstant();
    2302         135 :   Node* this_arg = node->op()->ValueInputCount() > 3
    2303             :                        ? NodeProperties::GetValueInput(node, 3)
    2304         265 :                        : jsgraph()->UndefinedConstant();
    2305             :   ZoneHandleSet<Map> receiver_maps;
    2306             :   NodeProperties::InferReceiverMapsResult result =
    2307             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    2308         270 :                                         &receiver_maps);
    2309         135 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    2310             : 
    2311             :   // And ensure that any changes to the Array species constructor cause deopt.
    2312         135 :   if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
    2313             : 
    2314             :   ElementsKind kind;
    2315         135 :   if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
    2316             :     return NoChange();
    2317             :   }
    2318             : 
    2319         264 :   if (IsHoleyElementsKind(kind)) {
    2320             :     dependencies()->DependOnProtector(
    2321          15 :         PropertyCellRef(broker(), factory()->no_elements_protector()));
    2322             :   }
    2323             : 
    2324             :   dependencies()->DependOnProtector(
    2325         132 :       PropertyCellRef(broker(), factory()->array_species_protector()));
    2326             : 
    2327             :   // If we have unreliable maps, we need a map check.
    2328         132 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    2329             :     effect =
    2330             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    2331           5 :                                                  receiver_maps, p.feedback()),
    2332          15 :                          receiver, effect, control);
    2333             :   }
    2334             : 
    2335         132 :   Node* k = jsgraph()->ZeroConstant();
    2336             : 
    2337             :   // Make sure the map hasn't changed before we construct the output array.
    2338             :   effect = graph()->NewNode(
    2339             :       simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
    2340         396 :       effect, control);
    2341             : 
    2342             :   Node* original_length = effect = graph()->NewNode(
    2343         132 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    2344         528 :       effect, control);
    2345             : 
    2346             :   // Check whether the given callback function is callable. Note that this has
    2347             :   // to happen outside the loop to make sure we also throw on empty arrays.
    2348         132 :   Node* check_fail = nullptr;
    2349         132 :   Node* check_throw = nullptr;
    2350             :   {
    2351             :     // This frame state doesn't ever call the deopt continuation, it's only
    2352             :     // necessary to specifiy a continuation in order to handle the exceptional
    2353             :     // case.
    2354             :     std::vector<Node*> checkpoint_params(
    2355         264 :         {receiver, fncallback, this_arg, k, original_length});
    2356         264 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    2357             : 
    2358             :     Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    2359             :         jsgraph(), shared, Builtins::kArrayEveryLoopLazyDeoptContinuation,
    2360             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    2361         132 :         outer_frame_state, ContinuationFrameStateMode::LAZY);
    2362             :     WireInCallbackIsCallableCheck(fncallback, context, check_frame_state,
    2363         132 :                                   effect, &control, &check_fail, &check_throw);
    2364             :   }
    2365             : 
    2366             :   // Start the loop.
    2367         132 :   Node* vloop = k = WireInLoopStart(k, &control, &effect);
    2368         132 :   Node *loop = control, *eloop = effect;
    2369             : 
    2370             :   Node* continue_test =
    2371         132 :       graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
    2372             :   Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2373         264 :                                            continue_test, control);
    2374             : 
    2375         132 :   Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
    2376         132 :   Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
    2377         132 :   control = if_true;
    2378             : 
    2379             :   {
    2380             :     std::vector<Node*> checkpoint_params(
    2381         264 :         {receiver, fncallback, this_arg, k, original_length});
    2382         264 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    2383             : 
    2384             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    2385             :         jsgraph(), shared, Builtins::kArrayEveryLoopEagerDeoptContinuation,
    2386             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    2387         132 :         outer_frame_state, ContinuationFrameStateMode::EAGER);
    2388             : 
    2389             :     effect =
    2390         396 :         graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
    2391             :   }
    2392             : 
    2393             :   // Make sure the map hasn't changed during the iteration.
    2394             :   effect =
    2395             :       graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    2396         132 :                                                receiver_maps, p.feedback()),
    2397         396 :                        receiver, effect, control);
    2398             : 
    2399             :   Node* element =
    2400         132 :       SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
    2401             : 
    2402             :   Node* next_k =
    2403         264 :       graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
    2404             : 
    2405             :   Node* hole_true = nullptr;
    2406             :   Node* hole_false = nullptr;
    2407         132 :   Node* effect_true = effect;
    2408             : 
    2409         264 :   if (IsHoleyElementsKind(kind)) {
    2410             :     // Holey elements kind require a hole check and skipping of the element in
    2411             :     // the case of a hole.
    2412             :     Node* check;
    2413          15 :     if (IsDoubleElementsKind(kind)) {
    2414           5 :       check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
    2415             :     } else {
    2416             :       check = graph()->NewNode(simplified()->ReferenceEqual(), element,
    2417          20 :                                jsgraph()->TheHoleConstant());
    2418             :     }
    2419             :     Node* branch =
    2420          30 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    2421          15 :     hole_true = graph()->NewNode(common()->IfTrue(), branch);
    2422          15 :     hole_false = graph()->NewNode(common()->IfFalse(), branch);
    2423          15 :     control = hole_false;
    2424             : 
    2425             :     // The contract is that we don't leak "the hole" into "user JavaScript",
    2426             :     // so we must rename the {element} here to explicitly exclude "the hole"
    2427             :     // from the type of {element}.
    2428             :     element = effect = graph()->NewNode(
    2429          45 :         common()->TypeGuard(Type::NonInternal()), element, effect, control);
    2430             :   }
    2431             : 
    2432             :   Node* callback_value = nullptr;
    2433             :   {
    2434             :     // This frame state is dealt with by hand in
    2435             :     // Builtins::kArrayEveryLoopLazyDeoptContinuation.
    2436             :     std::vector<Node*> checkpoint_params(
    2437         264 :         {receiver, fncallback, this_arg, k, original_length});
    2438         264 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    2439             : 
    2440             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    2441             :         jsgraph(), shared, Builtins::kArrayEveryLoopLazyDeoptContinuation,
    2442             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    2443         132 :         outer_frame_state, ContinuationFrameStateMode::LAZY);
    2444             : 
    2445             :     callback_value = control = effect = graph()->NewNode(
    2446         132 :         javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
    2447         396 :         receiver, context, frame_state, effect, control);
    2448             :   }
    2449             : 
    2450             :   // Rewire potential exception edges.
    2451         132 :   Node* on_exception = nullptr;
    2452         132 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    2453             :     RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
    2454          15 :                                      &check_fail, &control);
    2455             :   }
    2456             : 
    2457             :   // We have to coerce callback_value to boolean.
    2458             :   Node* if_false_callback;
    2459             :   Node* efalse_callback;
    2460             :   {
    2461             :     Node* boolean_result =
    2462         132 :         graph()->NewNode(simplified()->ToBoolean(), callback_value);
    2463             :     Node* boolean_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2464         264 :                                             boolean_result, control);
    2465         132 :     if_false_callback = graph()->NewNode(common()->IfFalse(), boolean_branch);
    2466         132 :     efalse_callback = effect;
    2467             : 
    2468             :     // Nothing to do in the true case.
    2469         264 :     control = graph()->NewNode(common()->IfTrue(), boolean_branch);
    2470             :   }
    2471             : 
    2472         264 :   if (IsHoleyElementsKind(kind)) {
    2473             :     Node* after_call_control = control;
    2474          15 :     Node* after_call_effect = effect;
    2475          15 :     control = hole_true;
    2476          15 :     effect = effect_true;
    2477             : 
    2478          30 :     control = graph()->NewNode(common()->Merge(2), control, after_call_control);
    2479             :     effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
    2480          45 :                               control);
    2481             :   }
    2482             : 
    2483         132 :   WireInLoopEnd(loop, eloop, vloop, next_k, control, effect);
    2484             : 
    2485         264 :   control = graph()->NewNode(common()->Merge(2), if_false, if_false_callback);
    2486             :   effect =
    2487         264 :       graph()->NewNode(common()->EffectPhi(2), eloop, efalse_callback, control);
    2488             :   Node* value = graph()->NewNode(
    2489             :       common()->Phi(MachineRepresentation::kTagged, 2),
    2490         528 :       jsgraph()->TrueConstant(), jsgraph()->FalseConstant(), control);
    2491             : 
    2492             :   // Introduce proper LoopExit/LoopExitEffect/LoopExitValue to mark
    2493             :   // {loop} as a candidate for loop peeling (crbug.com/v8/8273).
    2494         396 :   control = graph()->NewNode(common()->LoopExit(), control, loop);
    2495         396 :   effect = graph()->NewNode(common()->LoopExitEffect(), effect, control);
    2496         264 :   value = graph()->NewNode(common()->LoopExitValue(), value, control);
    2497             : 
    2498             :   // Wire up the branch for the case when IsCallable fails for the callback.
    2499             :   // Since {check_throw} is an unconditional throw, it's impossible to
    2500             :   // return a successful completion. Therefore, we simply connect the successful
    2501             :   // completion to the graph end.
    2502             :   Node* throw_node =
    2503         264 :       graph()->NewNode(common()->Throw(), check_throw, check_fail);
    2504         132 :   NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
    2505             : 
    2506         132 :   ReplaceWithValue(node, value, effect, control);
    2507             :   return Replace(value);
    2508             : }
    2509             : 
    2510             : namespace {
    2511             : 
    2512             : // Returns the correct Callable for Array's indexOf based on the receiver's
    2513             : // |elements_kind| and |isolate|. Assumes that |elements_kind| is a fast one.
    2514         915 : Callable GetCallableForArrayIndexOf(ElementsKind elements_kind,
    2515             :                                     Isolate* isolate) {
    2516         915 :   switch (elements_kind) {
    2517             :     case PACKED_SMI_ELEMENTS:
    2518             :     case HOLEY_SMI_ELEMENTS:
    2519             :     case PACKED_ELEMENTS:
    2520             :     case HOLEY_ELEMENTS:
    2521         915 :       return Builtins::CallableFor(isolate, Builtins::kArrayIndexOfSmiOrObject);
    2522             :     case PACKED_DOUBLE_ELEMENTS:
    2523             :       return Builtins::CallableFor(isolate,
    2524           0 :                                    Builtins::kArrayIndexOfPackedDoubles);
    2525             :     default:
    2526             :       DCHECK_EQ(HOLEY_DOUBLE_ELEMENTS, elements_kind);
    2527             :       return Builtins::CallableFor(isolate,
    2528           0 :                                    Builtins::kArrayIndexOfHoleyDoubles);
    2529             :   }
    2530             : }
    2531             : 
    2532             : // Returns the correct Callable for Array's includes based on the receiver's
    2533             : // |elements_kind| and |isolate|. Assumes that |elements_kind| is a fast one.
    2534          44 : Callable GetCallableForArrayIncludes(ElementsKind elements_kind,
    2535             :                                      Isolate* isolate) {
    2536          44 :   switch (elements_kind) {
    2537             :     case PACKED_SMI_ELEMENTS:
    2538             :     case HOLEY_SMI_ELEMENTS:
    2539             :     case PACKED_ELEMENTS:
    2540             :     case HOLEY_ELEMENTS:
    2541             :       return Builtins::CallableFor(isolate,
    2542          37 :                                    Builtins::kArrayIncludesSmiOrObject);
    2543             :     case PACKED_DOUBLE_ELEMENTS:
    2544             :       return Builtins::CallableFor(isolate,
    2545           7 :                                    Builtins::kArrayIncludesPackedDoubles);
    2546             :     default:
    2547             :       DCHECK_EQ(HOLEY_DOUBLE_ELEMENTS, elements_kind);
    2548             :       return Builtins::CallableFor(isolate,
    2549           0 :                                    Builtins::kArrayIncludesHoleyDoubles);
    2550             :   }
    2551             : }
    2552             : 
    2553             : }  // namespace
    2554             : 
    2555             : // For search_variant == kIndexOf:
    2556             : // ES6 Array.prototype.indexOf(searchElement[, fromIndex])
    2557             : // #sec-array.prototype.indexof
    2558             : // For search_variant == kIncludes:
    2559             : // ES7 Array.prototype.inludes(searchElement[, fromIndex])
    2560             : // #sec-array.prototype.includes
    2561        1035 : Reduction JSCallReducer::ReduceArrayIndexOfIncludes(
    2562        7025 :     SearchVariant search_variant, Node* node) {
    2563        1035 :   CallParameters const& p = CallParametersOf(node->op());
    2564        1035 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    2565             :     return NoChange();
    2566             :   }
    2567             : 
    2568             :   Handle<Map> map;
    2569        2046 :   if (!NodeProperties::GetMapWitness(broker(), node).ToHandle(&map))
    2570             :     return NoChange();
    2571             : 
    2572             :   MapRef receiver_map(broker(), map);
    2573        1007 :   if (!receiver_map.supports_fast_array_iteration()) return NoChange();
    2574             : 
    2575         959 :   ElementsKind const elements_kind = receiver_map.elements_kind();
    2576         959 :   if (IsHoleyElementsKind(elements_kind)) {
    2577             :     dependencies()->DependOnProtector(
    2578          34 :         PropertyCellRef(broker(), factory()->no_elements_protector()));
    2579             :   }
    2580             : 
    2581             :   Callable const callable =
    2582             :       search_variant == SearchVariant::kIndexOf
    2583             :           ? GetCallableForArrayIndexOf(elements_kind, isolate())
    2584        1918 :           : GetCallableForArrayIncludes(elements_kind, isolate());
    2585             :   CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
    2586             :       graph()->zone(), callable.descriptor(),
    2587             :       callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
    2588        1918 :       Operator::kEliminatable);
    2589             :   // The stub expects the following arguments: the receiver array, its elements,
    2590             :   // the search_element, the array length, and the index to start searching
    2591             :   // from.
    2592         959 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    2593         959 :   Node* effect = NodeProperties::GetEffectInput(node);
    2594         959 :   Node* control = NodeProperties::GetControlInput(node);
    2595             :   Node* elements = effect = graph()->NewNode(
    2596             :       simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
    2597        2877 :       effect, control);
    2598         959 :   Node* search_element = (node->op()->ValueInputCount() >= 3)
    2599             :                              ? NodeProperties::GetValueInput(node, 2)
    2600         959 :                              : jsgraph()->UndefinedConstant();
    2601             :   Node* length = effect = graph()->NewNode(
    2602         959 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
    2603        2877 :       receiver, effect, control);
    2604         959 :   Node* new_from_index = jsgraph()->ZeroConstant();
    2605        1918 :   if (node->op()->ValueInputCount() >= 4) {
    2606          28 :     Node* from_index = NodeProperties::GetValueInput(node, 3);
    2607          28 :     from_index = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()),
    2608          28 :                                            from_index, effect, control);
    2609             :     // If the index is negative, it means the offset from the end and therefore
    2610             :     // needs to be added to the length. If the result is still negative, it
    2611             :     // needs to be clamped to 0.
    2612             :     new_from_index = graph()->NewNode(
    2613             :         common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
    2614             :         graph()->NewNode(simplified()->NumberLessThan(), from_index,
    2615             :                          jsgraph()->ZeroConstant()),
    2616             :         graph()->NewNode(
    2617             :             simplified()->NumberMax(),
    2618             :             graph()->NewNode(simplified()->NumberAdd(), length, from_index),
    2619             :             jsgraph()->ZeroConstant()),
    2620         168 :         from_index);
    2621             :   }
    2622             : 
    2623         959 :   Node* context = NodeProperties::GetContextInput(node);
    2624             :   Node* replacement_node = effect = graph()->NewNode(
    2625             :       common()->Call(desc), jsgraph()->HeapConstant(callable.code()), elements,
    2626        2877 :       search_element, length, new_from_index, context, effect);
    2627         959 :   ReplaceWithValue(node, replacement_node, effect);
    2628             :   return Replace(replacement_node);
    2629             : }
    2630             : 
    2631         556 : Reduction JSCallReducer::ReduceArraySome(Node* node,
    2632        1506 :                                          const SharedFunctionInfoRef& shared) {
    2633         139 :   if (!FLAG_turbo_inline_array_builtins) return NoChange();
    2634             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    2635         139 :   CallParameters const& p = CallParametersOf(node->op());
    2636         139 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    2637             :     return NoChange();
    2638             :   }
    2639             : 
    2640         139 :   Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
    2641         139 :   Node* effect = NodeProperties::GetEffectInput(node);
    2642         139 :   Node* control = NodeProperties::GetControlInput(node);
    2643         139 :   Node* context = NodeProperties::GetContextInput(node);
    2644             :   // Try to determine the {receiver} map.
    2645         139 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    2646         139 :   Node* fncallback = node->op()->ValueInputCount() > 2
    2647             :                          ? NodeProperties::GetValueInput(node, 2)
    2648         139 :                          : jsgraph()->UndefinedConstant();
    2649         139 :   Node* this_arg = node->op()->ValueInputCount() > 3
    2650             :                        ? NodeProperties::GetValueInput(node, 3)
    2651         278 :                        : jsgraph()->UndefinedConstant();
    2652             :   ZoneHandleSet<Map> receiver_maps;
    2653             :   NodeProperties::InferReceiverMapsResult result =
    2654             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    2655         278 :                                         &receiver_maps);
    2656         139 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    2657             : 
    2658             :   // And ensure that any changes to the Array species constructor cause deopt.
    2659         139 :   if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
    2660             : 
    2661             :   ElementsKind kind;
    2662         124 :   if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
    2663             :     return NoChange();
    2664             :   }
    2665             : 
    2666         242 :   if (IsHoleyElementsKind(kind)) {
    2667             :     dependencies()->DependOnProtector(
    2668           5 :         PropertyCellRef(broker(), factory()->no_elements_protector()));
    2669             :   }
    2670             : 
    2671             :   dependencies()->DependOnProtector(
    2672         121 :       PropertyCellRef(broker(), factory()->array_species_protector()));
    2673             : 
    2674         121 :   Node* k = jsgraph()->ZeroConstant();
    2675             : 
    2676             :   // If we have unreliable maps, we need a map check.
    2677         121 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    2678             :     effect =
    2679             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    2680           0 :                                                  receiver_maps, p.feedback()),
    2681           0 :                          receiver, effect, control);
    2682             :   }
    2683             : 
    2684             :   // Make sure the map hasn't changed before we construct the output array.
    2685             :   effect = graph()->NewNode(
    2686             :       simplified()->CheckMaps(CheckMapsFlag::kNone, receiver_maps), receiver,
    2687         363 :       effect, control);
    2688             : 
    2689             :   Node* original_length = effect = graph()->NewNode(
    2690         121 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    2691         484 :       effect, control);
    2692             : 
    2693             :   // Check whether the given callback function is callable. Note that this has
    2694             :   // to happen outside the loop to make sure we also throw on empty arrays.
    2695         121 :   Node* check_fail = nullptr;
    2696         121 :   Node* check_throw = nullptr;
    2697             :   {
    2698             :     // This frame state doesn't ever call the deopt continuation, it's only
    2699             :     // necessary to specifiy a continuation in order to handle the exceptional
    2700             :     // case.
    2701             :     std::vector<Node*> checkpoint_params(
    2702         242 :         {receiver, fncallback, this_arg, k, original_length});
    2703         242 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    2704             : 
    2705             :     Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    2706             :         jsgraph(), shared, Builtins::kArraySomeLoopLazyDeoptContinuation,
    2707             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    2708         121 :         outer_frame_state, ContinuationFrameStateMode::LAZY);
    2709             :     WireInCallbackIsCallableCheck(fncallback, context, check_frame_state,
    2710         121 :                                   effect, &control, &check_fail, &check_throw);
    2711             :   }
    2712             : 
    2713             :   // Start the loop.
    2714         363 :   Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
    2715             :   Node* eloop = effect =
    2716         363 :       graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    2717         121 :   Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
    2718         121 :   NodeProperties::MergeControlToEnd(graph(), common(), terminate);
    2719             :   Node* vloop = k = graph()->NewNode(
    2720         363 :       common()->Phi(MachineRepresentation::kTagged, 2), k, k, loop);
    2721             : 
    2722             :   Node* continue_test =
    2723         121 :       graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
    2724             :   Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2725         242 :                                            continue_test, control);
    2726             : 
    2727         121 :   Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
    2728         121 :   Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
    2729         121 :   control = if_true;
    2730             : 
    2731             :   {
    2732             :     std::vector<Node*> checkpoint_params(
    2733         242 :         {receiver, fncallback, this_arg, k, original_length});
    2734         242 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    2735             : 
    2736             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    2737             :         jsgraph(), shared, Builtins::kArraySomeLoopEagerDeoptContinuation,
    2738             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    2739         121 :         outer_frame_state, ContinuationFrameStateMode::EAGER);
    2740             : 
    2741             :     effect =
    2742         363 :         graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
    2743             :   }
    2744             : 
    2745             :   // Make sure the map hasn't changed during the iteration.
    2746             :   effect =
    2747             :       graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    2748         121 :                                                receiver_maps, p.feedback()),
    2749         363 :                        receiver, effect, control);
    2750             : 
    2751             :   Node* element =
    2752         121 :       SafeLoadElement(kind, receiver, control, &effect, &k, p.feedback());
    2753             : 
    2754             :   Node* next_k =
    2755         242 :       graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->OneConstant());
    2756             : 
    2757             :   Node* hole_true = nullptr;
    2758             :   Node* hole_false = nullptr;
    2759         121 :   Node* effect_true = effect;
    2760             : 
    2761         242 :   if (IsHoleyElementsKind(kind)) {
    2762             :     // Holey elements kind require a hole check and skipping of the element in
    2763             :     // the case of a hole.
    2764             :     Node* check;
    2765           5 :     if (IsDoubleElementsKind(kind)) {
    2766           0 :       check = graph()->NewNode(simplified()->NumberIsFloat64Hole(), element);
    2767             :     } else {
    2768             :       check = graph()->NewNode(simplified()->ReferenceEqual(), element,
    2769          10 :                                jsgraph()->TheHoleConstant());
    2770             :     }
    2771             :     Node* branch =
    2772          10 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    2773           5 :     hole_true = graph()->NewNode(common()->IfTrue(), branch);
    2774           5 :     hole_false = graph()->NewNode(common()->IfFalse(), branch);
    2775           5 :     control = hole_false;
    2776             : 
    2777             :     // The contract is that we don't leak "the hole" into "user JavaScript",
    2778             :     // so we must rename the {element} here to explicitly exclude "the hole"
    2779             :     // from the type of {element}.
    2780             :     element = effect = graph()->NewNode(
    2781          15 :         common()->TypeGuard(Type::NonInternal()), element, effect, control);
    2782             :   }
    2783             : 
    2784             :   Node* callback_value = nullptr;
    2785             :   {
    2786             :     // This frame state is dealt with by hand in
    2787             :     // Builtins::kArrayEveryLoopLazyDeoptContinuation.
    2788             :     std::vector<Node*> checkpoint_params(
    2789         242 :         {receiver, fncallback, this_arg, k, original_length});
    2790         242 :     const int stack_parameters = static_cast<int>(checkpoint_params.size());
    2791             : 
    2792             :     Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    2793             :         jsgraph(), shared, Builtins::kArraySomeLoopLazyDeoptContinuation,
    2794             :         node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
    2795         121 :         outer_frame_state, ContinuationFrameStateMode::LAZY);
    2796             : 
    2797             :     callback_value = control = effect = graph()->NewNode(
    2798         121 :         javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
    2799         363 :         receiver, context, frame_state, effect, control);
    2800             :   }
    2801             : 
    2802             :   // Rewire potential exception edges.
    2803         121 :   Node* on_exception = nullptr;
    2804         121 :   if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    2805             :     RewirePostCallbackExceptionEdges(check_throw, on_exception, effect,
    2806          15 :                                      &check_fail, &control);
    2807             :   }
    2808             : 
    2809             :   // We have to coerce callback_value to boolean.
    2810             :   Node* if_true_callback;
    2811             :   Node* etrue_callback;
    2812             :   {
    2813             :     Node* boolean_result =
    2814         121 :         graph()->NewNode(simplified()->ToBoolean(), callback_value);
    2815             :     Node* boolean_branch = graph()->NewNode(
    2816         242 :         common()->Branch(BranchHint::kFalse), boolean_result, control);
    2817         121 :     if_true_callback = graph()->NewNode(common()->IfTrue(), boolean_branch);
    2818         121 :     etrue_callback = effect;
    2819             : 
    2820             :     // Nothing to do in the false case.
    2821         242 :     control = graph()->NewNode(common()->IfFalse(), boolean_branch);
    2822             :   }
    2823             : 
    2824         242 :   if (IsHoleyElementsKind(kind)) {
    2825             :     Node* after_call_control = control;
    2826           5 :     Node* after_call_effect = effect;
    2827           5 :     control = hole_true;
    2828           5 :     effect = effect_true;
    2829             : 
    2830          10 :     control = graph()->NewNode(common()->Merge(2), control, after_call_control);
    2831             :     effect = graph()->NewNode(common()->EffectPhi(2), effect, after_call_effect,
    2832          15 :                               control);
    2833             :   }
    2834             : 
    2835         121 :   loop->ReplaceInput(1, control);
    2836         121 :   vloop->ReplaceInput(1, next_k);
    2837         121 :   eloop->ReplaceInput(1, effect);
    2838             : 
    2839         242 :   control = graph()->NewNode(common()->Merge(2), if_false, if_true_callback);
    2840             :   effect =
    2841         242 :       graph()->NewNode(common()->EffectPhi(2), eloop, etrue_callback, control);
    2842             :   Node* value = graph()->NewNode(
    2843             :       common()->Phi(MachineRepresentation::kTagged, 2),
    2844         484 :       jsgraph()->FalseConstant(), jsgraph()->TrueConstant(), control);
    2845             : 
    2846             :   // Introduce proper LoopExit/LoopExitEffect/LoopExitValue to mark
    2847             :   // {loop} as a candidate for loop peeling (crbug.com/v8/8273).
    2848         363 :   control = graph()->NewNode(common()->LoopExit(), control, loop);
    2849         363 :   effect = graph()->NewNode(common()->LoopExitEffect(), effect, control);
    2850         242 :   value = graph()->NewNode(common()->LoopExitValue(), value, control);
    2851             : 
    2852             :   // Wire up the branch for the case when IsCallable fails for the callback.
    2853             :   // Since {check_throw} is an unconditional throw, it's impossible to
    2854             :   // return a successful completion. Therefore, we simply connect the successful
    2855             :   // completion to the graph end.
    2856             :   Node* throw_node =
    2857         242 :       graph()->NewNode(common()->Throw(), check_throw, check_fail);
    2858         121 :   NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
    2859             : 
    2860         121 :   ReplaceWithValue(node, value, effect, control);
    2861             :   return Replace(value);
    2862             : }
    2863             : 
    2864       12613 : Reduction JSCallReducer::ReduceCallApiFunction(
    2865      105772 :     Node* node, const SharedFunctionInfoRef& shared) {
    2866             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    2867       25226 :   CallParameters const& p = CallParametersOf(node->op());
    2868       12613 :   int const argc = static_cast<int>(p.arity()) - 2;
    2869       12613 :   Node* target = NodeProperties::GetValueInput(node, 0);
    2870             :   Node* receiver =
    2871             :       (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
    2872       30529 :           ? jsgraph()->Constant(native_context().global_proxy_object())
    2873       25226 :           : NodeProperties::GetValueInput(node, 1);
    2874       12613 :   Node* effect = NodeProperties::GetEffectInput(node);
    2875       12613 :   Node* control = NodeProperties::GetControlInput(node);
    2876             : 
    2877             :   Handle<FunctionTemplateInfo> function_template_info(
    2878       25226 :       FunctionTemplateInfo::cast(shared.object()->function_data()), isolate());
    2879             : 
    2880             :   // Infer the {receiver} maps, and check if we can inline the API function
    2881             :   // callback based on those.
    2882             :   ZoneHandleSet<Map> receiver_maps;
    2883             :   NodeProperties::InferReceiverMapsResult result =
    2884             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    2885       12613 :                                         &receiver_maps);
    2886       12613 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    2887       22585 :   for (Handle<Map> map : receiver_maps) {
    2888             :     MapRef receiver_map(broker(), map);
    2889       37839 :     if (!receiver_map.IsJSObjectMap() ||
    2890       19944 :         (!function_template_info->accept_any_receiver() &&
    2891           0 :          receiver_map.is_access_check_needed())) {
    2892        2641 :       return NoChange();
    2893             :     }
    2894             :     // In case of unreliable {receiver} information, the {receiver_maps}
    2895             :     // must all be stable in order to consume the information.
    2896        9972 :     if (result == NodeProperties::kUnreliableReceiverMaps) {
    2897        9636 :       if (!receiver_map.is_stable()) return NoChange();
    2898             :     }
    2899             :   }
    2900             : 
    2901             :   // See if we can constant-fold the compatible receiver checks.
    2902        9972 :   CallOptimization call_optimization(isolate(), function_template_info);
    2903        9972 :   if (!call_optimization.is_simple_api_call()) return NoChange();
    2904             :   CallOptimization::HolderLookup lookup;
    2905             :   Handle<JSObject> api_holder =
    2906        9972 :       call_optimization.LookupHolderOfExpectedType(receiver_maps[0], &lookup);
    2907        9972 :   if (lookup == CallOptimization::kHolderNotFound) return NoChange();
    2908        9924 :   for (size_t i = 1; i < receiver_maps.size(); ++i) {
    2909             :     CallOptimization::HolderLookup lookupi;
    2910             :     Handle<JSObject> holder = call_optimization.LookupHolderOfExpectedType(
    2911           0 :         receiver_maps[i], &lookupi);
    2912           0 :     if (lookup != lookupi) return NoChange();
    2913           0 :     if (!api_holder.is_identical_to(holder)) return NoChange();
    2914             :   }
    2915             : 
    2916             :   // Install stability dependencies for unreliable {receiver_maps}.
    2917        9924 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    2918       19272 :     for (Handle<Map> map : receiver_maps) {
    2919             :       MapRef receiver_map(broker(), map);
    2920        9636 :       dependencies()->DependOnStableMap(receiver_map);
    2921             :     }
    2922             :   }
    2923             : 
    2924             :   // Load the {target}s context.
    2925             :   Node* context = effect = graph()->NewNode(
    2926             :       simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
    2927       29772 :       effect, control);
    2928             : 
    2929             :   // CallApiCallbackStub's register arguments: code, target, call data, holder,
    2930             :   // function address.
    2931             :   // TODO(turbofan): Consider introducing a JSCallApiCallback operator for
    2932             :   // this and lower it during JSGenericLowering, and unify this with the
    2933             :   // JSNativeContextSpecialization::InlineApiCall method a bit.
    2934             :   Handle<CallHandlerInfo> call_handler_info(
    2935       19848 :       CallHandlerInfo::cast(function_template_info->call_code()), isolate());
    2936       19848 :   Handle<Object> data(call_handler_info->data(), isolate());
    2937        9924 :   Callable call_api_callback = CodeFactory::CallApiCallback(isolate());
    2938             :   CallInterfaceDescriptor cid = call_api_callback.descriptor();
    2939             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    2940             :       graph()->zone(), cid,
    2941        9924 :       cid.GetStackParameterCount() + argc + 1 /* implicit receiver */,
    2942       19848 :       CallDescriptor::kNeedsFrameState);
    2943       19848 :   ApiFunction api_function(v8::ToCData<Address>(call_handler_info->callback()));
    2944        9924 :   Node* holder = lookup == CallOptimization::kHolderFound
    2945        9931 :                      ? jsgraph()->HeapConstant(api_holder)
    2946       19848 :                      : receiver;
    2947             :   ExternalReference function_reference = ExternalReference::Create(
    2948        9924 :       &api_function, ExternalReference::DIRECT_API_CALL);
    2949             :   node->InsertInput(graph()->zone(), 0,
    2950       19848 :                     jsgraph()->HeapConstant(call_api_callback.code()));
    2951        9924 :   node->ReplaceInput(1, context);
    2952             :   node->InsertInput(graph()->zone(), 2,
    2953       19848 :                     jsgraph()->ExternalConstant(function_reference));
    2954       29772 :   node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(argc));
    2955       19848 :   node->InsertInput(graph()->zone(), 4, jsgraph()->Constant(data));
    2956        9924 :   node->InsertInput(graph()->zone(), 5, holder);
    2957        9924 :   node->ReplaceInput(6, receiver);
    2958        9924 :   node->RemoveInput(7 + argc);           // Remove context input.
    2959        9924 :   node->ReplaceInput(8 + argc, effect);  // Update effect input.
    2960        9924 :   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
    2961             :   return Changed(node);
    2962             : }
    2963             : 
    2964             : namespace {
    2965             : 
    2966             : // Check whether elements aren't mutated; we play it extremely safe here by
    2967             : // explicitly checking that {node} is only used by {LoadField} or {LoadElement}.
    2968          37 : bool IsSafeArgumentsElements(Node* node) {
    2969         259 :   for (Edge const edge : node->use_edges()) {
    2970         111 :     if (!NodeProperties::IsValueEdge(edge)) continue;
    2971         185 :     if (edge.from()->opcode() != IrOpcode::kLoadField &&
    2972          37 :         edge.from()->opcode() != IrOpcode::kLoadElement) {
    2973           0 :       return false;
    2974             :     }
    2975             :   }
    2976             :   return true;
    2977             : }
    2978             : 
    2979             : }  // namespace
    2980             : 
    2981        3201 : Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
    2982             :     Node* node, int arity, CallFrequency const& frequency,
    2983        4346 :     VectorSlotPair const& feedback) {
    2984             :   DCHECK(node->opcode() == IrOpcode::kJSCallWithArrayLike ||
    2985             :          node->opcode() == IrOpcode::kJSCallWithSpread ||
    2986             :          node->opcode() == IrOpcode::kJSConstructWithArrayLike ||
    2987             :          node->opcode() == IrOpcode::kJSConstructWithSpread);
    2988             : 
    2989             :   // In case of a call/construct with spread, we need to
    2990             :   // ensure that it's safe to avoid the actual iteration.
    2991       11697 :   if ((node->opcode() == IrOpcode::kJSCallWithSpread ||
    2992        5403 :        node->opcode() == IrOpcode::kJSConstructWithSpread) &&
    2993        2201 :       !isolate()->IsArrayIteratorLookupChainIntact()) {
    2994             :     return NoChange();
    2995             :   }
    2996             : 
    2997             :   // Check if {arguments_list} is an arguments object, and {node} is the only
    2998             :   // value user of {arguments_list} (except for value uses in frame states).
    2999        4441 :   Node* arguments_list = NodeProperties::GetValueInput(node, arity);
    3000        2761 :   if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) {
    3001             :     return NoChange();
    3002             :   }
    3003       25341 :   for (Edge edge : arguments_list->use_edges()) {
    3004       10931 :     if (!NodeProperties::IsValueEdge(edge)) continue;
    3005        9220 :     Node* const user = edge.from();
    3006        9183 :     switch (user->opcode()) {
    3007             :       case IrOpcode::kCheckMaps:
    3008             :       case IrOpcode::kFrameState:
    3009             :       case IrOpcode::kStateValues:
    3010             :       case IrOpcode::kReferenceEqual:
    3011             :       case IrOpcode::kReturn:
    3012             :         // Ignore safe uses that definitely don't mess with the arguments.
    3013             :         continue;
    3014             :       case IrOpcode::kLoadField: {
    3015             :         DCHECK_EQ(arguments_list, user->InputAt(0));
    3016          90 :         FieldAccess const& access = FieldAccessOf(user->op());
    3017          90 :         if (access.offset == JSArray::kLengthOffset) {
    3018             :           // Ignore uses for arguments#length.
    3019             :           STATIC_ASSERT(
    3020             :               static_cast<int>(JSArray::kLengthOffset) ==
    3021             :               static_cast<int>(JSArgumentsObjectWithLength::kLengthOffset));
    3022             :           continue;
    3023          37 :         } else if (access.offset == JSObject::kElementsOffset) {
    3024             :           // Ignore safe uses for arguments#elements.
    3025          37 :           if (IsSafeArgumentsElements(user)) continue;
    3026             :         }
    3027             :         break;
    3028             :       }
    3029             :       case IrOpcode::kJSCallWithArrayLike:
    3030             :         // Ignore uses as argumentsList input to calls with array like.
    3031         488 :         if (user->InputAt(2) == arguments_list) continue;
    3032             :         break;
    3033             :       case IrOpcode::kJSConstructWithArrayLike:
    3034             :         // Ignore uses as argumentsList input to calls with array like.
    3035         140 :         if (user->InputAt(1) == arguments_list) continue;
    3036             :         break;
    3037             :       case IrOpcode::kJSCallWithSpread: {
    3038             :         // Ignore uses as spread input to calls with spread.
    3039         411 :         CallParameters p = CallParametersOf(user->op());
    3040         411 :         int const arity = static_cast<int>(p.arity() - 1);
    3041         411 :         if (user->InputAt(arity) == arguments_list) continue;
    3042             :         break;
    3043             :       }
    3044             :       case IrOpcode::kJSConstructWithSpread: {
    3045             :         // Ignore uses as spread input to construct with spread.
    3046         927 :         ConstructParameters p = ConstructParametersOf(user->op());
    3047         927 :         int const arity = static_cast<int>(p.arity() - 2);
    3048         927 :         if (user->InputAt(arity) == arguments_list) continue;
    3049             :         break;
    3050             :       }
    3051             :       default:
    3052             :         break;
    3053             :     }
    3054             :     // We cannot currently reduce the {node} to something better than what
    3055             :     // it already is, but we might be able to do something about the {node}
    3056             :     // later, so put it on the waitlist and try again during finalization.
    3057             :     waitlist_.insert(node);
    3058         119 :     return NoChange();
    3059             :   }
    3060             : 
    3061             :   // Get to the actual frame state from which to extract the arguments;
    3062             :   // we can only optimize this in case the {node} was already inlined into
    3063             :   // some other function (and same for the {arguments_list}).
    3064        1680 :   CreateArgumentsType const type = CreateArgumentsTypeOf(arguments_list->op());
    3065        1680 :   Node* frame_state = NodeProperties::GetFrameStateInput(arguments_list);
    3066        1680 :   FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
    3067             :   int start_index = 0;
    3068             : 
    3069             :   int formal_parameter_count;
    3070             :   {
    3071             :     Handle<SharedFunctionInfo> shared;
    3072        1680 :     if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
    3073             :     formal_parameter_count = SharedFunctionInfoRef(broker(), shared)
    3074        1680 :                                  .internal_formal_parameter_count();
    3075             :   }
    3076             : 
    3077        1680 :   if (type == CreateArgumentsType::kMappedArguments) {
    3078             :     // Mapped arguments (sloppy mode) that are aliased can only be handled
    3079             :     // here if there's no side-effect between the {node} and the {arg_array}.
    3080             :     // TODO(turbofan): Further relax this constraint.
    3081         364 :     if (formal_parameter_count != 0) {
    3082          66 :       Node* effect = NodeProperties::GetEffectInput(node);
    3083          66 :       if (!NodeProperties::NoObservableSideEffectBetween(effect,
    3084          66 :                                                          arguments_list)) {
    3085             :         return NoChange();
    3086             :       }
    3087             :     }
    3088        1316 :   } else if (type == CreateArgumentsType::kRestParameter) {
    3089             :     start_index = formal_parameter_count;
    3090             :   }
    3091             : 
    3092             :   // For call/construct with spread, we need to also install a code
    3093             :   // dependency on the array iterator lookup protector cell to ensure
    3094             :   // that no one messed with the %ArrayIteratorPrototype%.next method.
    3095        3298 :   if (node->opcode() == IrOpcode::kJSCallWithSpread ||
    3096             :       node->opcode() == IrOpcode::kJSConstructWithSpread) {
    3097             :     dependencies()->DependOnProtector(
    3098        1144 :         PropertyCellRef(broker(), factory()->array_iterator_protector()));
    3099             :   }
    3100             : 
    3101             :   // Remove the {arguments_list} input from the {node}.
    3102        1649 :   node->RemoveInput(arity--);
    3103             :   // Check if are spreading to inlined arguments or to the arguments of
    3104             :   // the outermost function.
    3105        1649 :   Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
    3106        1649 :   if (outer_state->opcode() != IrOpcode::kFrameState) {
    3107             :     Operator const* op =
    3108        1892 :         (node->opcode() == IrOpcode::kJSCallWithArrayLike ||
    3109             :          node->opcode() == IrOpcode::kJSCallWithSpread)
    3110         368 :             ? javascript()->CallForwardVarargs(arity + 1, start_index)
    3111        2114 :             : javascript()->ConstructForwardVarargs(arity + 2, start_index);
    3112        1057 :     NodeProperties::ChangeOp(node, op);
    3113        1057 :     return Changed(node);
    3114             :   }
    3115             :   // Get to the actual frame state from which to extract the arguments;
    3116             :   // we can only optimize this in case the {node} was already inlined into
    3117             :   // some other function (and same for the {arg_array}).
    3118         592 :   FrameStateInfo outer_info = FrameStateInfoOf(outer_state->op());
    3119         592 :   if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
    3120             :     // Need to take the parameters from the arguments adaptor.
    3121             :     frame_state = outer_state;
    3122             :   }
    3123             :   // Add the actual parameters to the {node}, skipping the receiver.
    3124             :   Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
    3125        2282 :   for (int i = start_index + 1; i < parameters->InputCount(); ++i) {
    3126             :     node->InsertInput(graph()->zone(), static_cast<int>(++arity),
    3127        1098 :                       parameters->InputAt(i));
    3128             :   }
    3129             : 
    3130        1184 :   if (node->opcode() == IrOpcode::kJSCallWithArrayLike ||
    3131             :       node->opcode() == IrOpcode::kJSCallWithSpread) {
    3132             :     NodeProperties::ChangeOp(
    3133         428 :         node, javascript()->Call(arity + 1, frequency, feedback));
    3134         214 :     Reduction const reduction = ReduceJSCall(node);
    3135         214 :     return reduction.Changed() ? reduction : Changed(node);
    3136             :   } else {
    3137             :     NodeProperties::ChangeOp(
    3138         756 :         node, javascript()->Construct(arity + 2, frequency, feedback));
    3139         378 :     Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
    3140         378 :     Node* frame_state = NodeProperties::GetFrameStateInput(node);
    3141         378 :     Node* context = NodeProperties::GetContextInput(node);
    3142         378 :     Node* effect = NodeProperties::GetEffectInput(node);
    3143         378 :     Node* control = NodeProperties::GetControlInput(node);
    3144             : 
    3145             :     // Check whether the given new target value is a constructor function. The
    3146             :     // replacement {JSConstruct} operator only checks the passed target value
    3147             :     // but relies on the new target value to be implicitly valid.
    3148             :     Node* check =
    3149         378 :         graph()->NewNode(simplified()->ObjectIsConstructor(), new_target);
    3150             :     Node* check_branch =
    3151         378 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    3152         378 :     Node* check_fail = graph()->NewNode(common()->IfFalse(), check_branch);
    3153             :     Node* check_throw = check_fail = graph()->NewNode(
    3154             :         javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
    3155             :         jsgraph()->Constant(static_cast<int>(MessageTemplate::kNotConstructor)),
    3156         756 :         new_target, context, frame_state, effect, check_fail);
    3157         378 :     control = graph()->NewNode(common()->IfTrue(), check_branch);
    3158         378 :     NodeProperties::ReplaceControlInput(node, control);
    3159             : 
    3160             :     // Rewire potential exception edges.
    3161         378 :     Node* on_exception = nullptr;
    3162         378 :     if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    3163             :       // Create appropriate {IfException}  and {IfSuccess} nodes.
    3164             :       Node* if_exception =
    3165          24 :           graph()->NewNode(common()->IfException(), check_throw, check_fail);
    3166          24 :       check_fail = graph()->NewNode(common()->IfSuccess(), check_fail);
    3167             : 
    3168             :       // Join the exception edges.
    3169             :       Node* merge =
    3170          48 :           graph()->NewNode(common()->Merge(2), if_exception, on_exception);
    3171             :       Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception,
    3172          48 :                                     on_exception, merge);
    3173             :       Node* phi =
    3174             :           graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    3175          48 :                            if_exception, on_exception, merge);
    3176          24 :       ReplaceWithValue(on_exception, phi, ephi, merge);
    3177          24 :       merge->ReplaceInput(1, on_exception);
    3178          24 :       ephi->ReplaceInput(1, on_exception);
    3179          24 :       phi->ReplaceInput(1, on_exception);
    3180             :     }
    3181             : 
    3182             :     // The above %ThrowTypeError runtime call is an unconditional throw, making
    3183             :     // it impossible to return a successful completion in this case. We simply
    3184             :     // connect the successful completion to the graph end.
    3185             :     Node* throw_node =
    3186         378 :         graph()->NewNode(common()->Throw(), check_throw, check_fail);
    3187         378 :     NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
    3188             : 
    3189         378 :     Reduction const reduction = ReduceJSConstruct(node);
    3190         378 :     return reduction.Changed() ? reduction : Changed(node);
    3191             :   }
    3192             : }
    3193             : 
    3194             : namespace {
    3195             : 
    3196       14022 : bool ShouldUseCallICFeedback(Node* node) {
    3197             :   HeapObjectMatcher m(node);
    3198       14022 :   if (m.HasValue() || m.IsJSCreateClosure()) {
    3199             :     // Don't use CallIC feedback when we know the function
    3200             :     // being called, i.e. either know the closure itself or
    3201             :     // at least the SharedFunctionInfo.
    3202             :     return false;
    3203       12649 :   } else if (m.IsPhi()) {
    3204             :     // Protect against endless loops here.
    3205        1103 :     Node* control = NodeProperties::GetControlInput(node);
    3206        1103 :     if (control->opcode() == IrOpcode::kLoop) return false;
    3207             :     // Check if {node} is a Phi of nodes which shouldn't
    3208             :     // use CallIC feedback (not looking through loops).
    3209        1050 :     int const value_input_count = m.node()->op()->ValueInputCount();
    3210        2423 :     for (int n = 0; n < value_input_count; ++n) {
    3211        2095 :       if (ShouldUseCallICFeedback(node->InputAt(n))) return true;
    3212             :     }
    3213             :     return false;
    3214             :   }
    3215             :   return true;
    3216             : }
    3217             : 
    3218       25788 : base::Optional<HeapObjectRef> GetHeapObjectFeedback(
    3219       25784 :     JSHeapBroker* broker, const FeedbackNexus& nexus) {
    3220       25788 :   HeapObject object;
    3221       25788 :   if (!nexus.GetFeedback()->GetHeapObject(&object)) return base::nullopt;
    3222       25784 :   return HeapObjectRef(broker, handle(object, broker->isolate()));
    3223             : }
    3224             : 
    3225             : }  // namespace
    3226             : 
    3227     1105179 : Reduction JSCallReducer::ReduceJSCall(Node* node) {
    3228             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    3229     1365699 :   CallParameters const& p = CallParametersOf(node->op());
    3230      682867 :   Node* target = NodeProperties::GetValueInput(node, 0);
    3231      682853 :   Node* control = NodeProperties::GetControlInput(node);
    3232      682860 :   Node* effect = NodeProperties::GetEffectInput(node);
    3233             :   size_t arity = p.arity();
    3234             :   DCHECK_LE(2u, arity);
    3235             : 
    3236             :   // Try to specialize JSCall {node}s with constant {target}s.
    3237             :   HeapObjectMatcher m(target);
    3238      682850 :   if (m.HasValue()) {
    3239      378666 :     ObjectRef target_ref = m.Ref(broker());
    3240      378666 :     if (target_ref.IsJSFunction()) {
    3241      378247 :       JSFunctionRef function = target_ref.AsJSFunction();
    3242      378246 :       function.Serialize();
    3243             : 
    3244             :       // Don't inline cross native context.
    3245      378244 :       if (!function.native_context().equals(native_context())) {
    3246             :         return NoChange();
    3247             :       }
    3248             : 
    3249      378215 :       return ReduceJSCall(node, function.shared());
    3250         420 :     } else if (target_ref.IsJSBoundFunction()) {
    3251         280 :       JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
    3252         280 :       function.Serialize();
    3253             : 
    3254         280 :       ObjectRef bound_this = function.bound_this();
    3255             :       ConvertReceiverMode const convert_mode =
    3256         280 :           bound_this.IsNullOrUndefined()
    3257             :               ? ConvertReceiverMode::kNullOrUndefined
    3258         280 :               : ConvertReceiverMode::kNotNullOrUndefined;
    3259             : 
    3260             :       // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
    3261             :       NodeProperties::ReplaceValueInput(
    3262         560 :           node, jsgraph()->Constant(function.bound_target_function()), 0);
    3263             :       NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
    3264         280 :                                         1);
    3265             : 
    3266             :       // Insert the [[BoundArguments]] for {node}.
    3267         280 :       FixedArrayRef bound_arguments = function.bound_arguments();
    3268         537 :       for (int i = 0; i < bound_arguments.length(); ++i) {
    3269             :         node->InsertInput(graph()->zone(), i + 2,
    3270         771 :                           jsgraph()->Constant(bound_arguments.get(i)));
    3271         257 :         arity++;
    3272             :       }
    3273             : 
    3274             :       NodeProperties::ChangeOp(
    3275         280 :           node, javascript()->Call(arity, p.frequency(), VectorSlotPair(),
    3276         560 :                                    convert_mode));
    3277             : 
    3278             :       // Try to further reduce the JSCall {node}.
    3279         280 :       Reduction const reduction = ReduceJSCall(node);
    3280         280 :       return reduction.Changed() ? reduction : Changed(node);
    3281             :     }
    3282             : 
    3283             :     // Don't mess with other {node}s that have a constant {target}.
    3284             :     // TODO(bmeurer): Also support proxies here.
    3285             :     return NoChange();
    3286             :   }
    3287             : 
    3288             :   // If {target} is the result of a JSCreateClosure operation, we can
    3289             :   // just immediately try to inline based on the SharedFunctionInfo,
    3290             :   // since TurboFan generally doesn't inline cross-context, and hence
    3291             :   // the {target} must have the same native context as the call site.
    3292      304183 :   if (target->opcode() == IrOpcode::kJSCreateClosure) {
    3293       23240 :     CreateClosureParameters const& p = CreateClosureParametersOf(target->op());
    3294       23249 :     return ReduceJSCall(node, SharedFunctionInfoRef(broker(), p.shared_info()));
    3295             :   }
    3296             : 
    3297             :   // If {target} is the result of a JSCreateBoundFunction operation,
    3298             :   // we can just fold the construction and call the bound target
    3299             :   // function directly instead.
    3300      280943 :   if (target->opcode() == IrOpcode::kJSCreateBoundFunction) {
    3301          14 :     Node* bound_target_function = NodeProperties::GetValueInput(target, 0);
    3302          14 :     Node* bound_this = NodeProperties::GetValueInput(target, 1);
    3303             :     int const bound_arguments_length =
    3304          14 :         static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity());
    3305             : 
    3306             :     // Patch the {node} to use [[BoundTargetFunction]] and [[BoundThis]].
    3307          14 :     NodeProperties::ReplaceValueInput(node, bound_target_function, 0);
    3308          14 :     NodeProperties::ReplaceValueInput(node, bound_this, 1);
    3309             : 
    3310             :     // Insert the [[BoundArguments]] for {node}.
    3311          28 :     for (int i = 0; i < bound_arguments_length; ++i) {
    3312          14 :       Node* value = NodeProperties::GetValueInput(target, 2 + i);
    3313          14 :       node->InsertInput(graph()->zone(), 2 + i, value);
    3314          14 :       arity++;
    3315             :     }
    3316             : 
    3317             :     // Update the JSCall operator on {node}.
    3318             :     ConvertReceiverMode const convert_mode =
    3319          14 :         NodeProperties::CanBeNullOrUndefined(broker(), bound_this, effect)
    3320             :             ? ConvertReceiverMode::kAny
    3321          14 :             : ConvertReceiverMode::kNotNullOrUndefined;
    3322             :     NodeProperties::ChangeOp(
    3323          14 :         node, javascript()->Call(arity, p.frequency(), VectorSlotPair(),
    3324          28 :                                  convert_mode));
    3325             : 
    3326             :     // Try to further reduce the JSCall {node}.
    3327          14 :     Reduction const reduction = ReduceJSCall(node);
    3328          14 :     return reduction.Changed() ? reduction : Changed(node);
    3329             :   }
    3330             : 
    3331             :   // Extract feedback from the {node} using the FeedbackNexus.
    3332      280929 :   if (!p.feedback().IsValid()) return NoChange();
    3333      163316 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    3334      163318 :   if (nexus.IsUninitialized()) {
    3335      151387 :     if (flags() & kBailoutOnUninitialized) {
    3336             :       // Introduce a SOFT deopt if the call {node} wasn't executed so far.
    3337             :       return ReduceSoftDeoptimize(
    3338           0 :           node, DeoptimizeReason::kInsufficientTypeFeedbackForCall);
    3339             :     }
    3340             :     return NoChange();
    3341             :   }
    3342             : 
    3343             :   base::Optional<HeapObjectRef> feedback =
    3344       11931 :       GetHeapObjectFeedback(broker(), nexus);
    3345       35793 :   if (feedback.has_value() && ShouldUseCallICFeedback(target) &&
    3346       35023 :       feedback->map().is_callable()) {
    3347        7661 :     Node* target_function = jsgraph()->Constant(*feedback);
    3348             : 
    3349             :     // Check that the {target} is still the {target_function}.
    3350             :     Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
    3351        7661 :                                    target_function);
    3352             :     effect = graph()->NewNode(
    3353             :         simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
    3354       22983 :         effect, control);
    3355             : 
    3356             :     // Specialize the JSCall node to the {target_function}.
    3357        7661 :     NodeProperties::ReplaceValueInput(node, target_function, 0);
    3358        7661 :     NodeProperties::ReplaceEffectInput(node, effect);
    3359             : 
    3360             :     // Try to further reduce the JSCall {node}.
    3361        7661 :     Reduction const reduction = ReduceJSCall(node);
    3362        7661 :     return reduction.Changed() ? reduction : Changed(node);
    3363             :   }
    3364             : 
    3365             :   return NoChange();
    3366             : }
    3367             : 
    3368      401455 : Reduction JSCallReducer::ReduceJSCall(Node* node,
    3369         764 :                                       const SharedFunctionInfoRef& shared) {
    3370             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    3371      401455 :   Node* target = NodeProperties::GetValueInput(node, 0);
    3372             : 
    3373             :   // Do not reduce calls to functions with break points.
    3374      401460 :   if (shared.HasBreakInfo()) return NoChange();
    3375             : 
    3376             :   // Raise a TypeError if the {target} is a "classConstructor".
    3377      802717 :   if (IsClassConstructor(shared.kind())) {
    3378          33 :     NodeProperties::ReplaceValueInputs(node, target);
    3379             :     NodeProperties::ChangeOp(
    3380             :         node, javascript()->CallRuntime(
    3381          33 :                   Runtime::kThrowConstructorNonCallableError, 1));
    3382             :     return Changed(node);
    3383             :   }
    3384             : 
    3385             :   // Check for known builtin functions.
    3386             : 
    3387             :   int builtin_id =
    3388      401324 :       shared.HasBuiltinId() ? shared.builtin_id() : Builtins::kNoBuiltinId;
    3389      401316 :   switch (builtin_id) {
    3390             :     case Builtins::kArrayConstructor:
    3391         216 :       return ReduceArrayConstructor(node);
    3392             :     case Builtins::kBooleanConstructor:
    3393          12 :       return ReduceBooleanConstructor(node);
    3394             :     case Builtins::kFunctionPrototypeApply:
    3395         491 :       return ReduceFunctionPrototypeApply(node);
    3396             :     case Builtins::kFastFunctionPrototypeBind:
    3397         141 :       return ReduceFunctionPrototypeBind(node);
    3398             :     case Builtins::kFunctionPrototypeCall:
    3399        1554 :       return ReduceFunctionPrototypeCall(node);
    3400             :     case Builtins::kFunctionPrototypeHasInstance:
    3401        1535 :       return ReduceFunctionPrototypeHasInstance(node);
    3402             :     case Builtins::kObjectConstructor:
    3403         217 :       return ReduceObjectConstructor(node);
    3404             :     case Builtins::kObjectCreate:
    3405          75 :       return ReduceObjectCreate(node);
    3406             :     case Builtins::kObjectGetPrototypeOf:
    3407         687 :       return ReduceObjectGetPrototypeOf(node);
    3408             :     case Builtins::kObjectIs:
    3409         230 :       return ReduceObjectIs(node);
    3410             :     case Builtins::kObjectPrototypeGetProto:
    3411          88 :       return ReduceObjectPrototypeGetProto(node);
    3412             :     case Builtins::kObjectPrototypeHasOwnProperty:
    3413          68 :       return ReduceObjectPrototypeHasOwnProperty(node);
    3414             :     case Builtins::kObjectPrototypeIsPrototypeOf:
    3415          63 :       return ReduceObjectPrototypeIsPrototypeOf(node);
    3416             :     case Builtins::kReflectApply:
    3417         254 :       return ReduceReflectApply(node);
    3418             :     case Builtins::kReflectConstruct:
    3419         189 :       return ReduceReflectConstruct(node);
    3420             :     case Builtins::kReflectGet:
    3421          35 :       return ReduceReflectGet(node);
    3422             :     case Builtins::kReflectGetPrototypeOf:
    3423          14 :       return ReduceReflectGetPrototypeOf(node);
    3424             :     case Builtins::kReflectHas:
    3425          35 :       return ReduceReflectHas(node);
    3426             :     case Builtins::kArrayForEach:
    3427         340 :       return ReduceArrayForEach(node, shared);
    3428             :     case Builtins::kArrayMap:
    3429         348 :       return ReduceArrayMap(node, shared);
    3430             :     case Builtins::kArrayFilter:
    3431         223 :       return ReduceArrayFilter(node, shared);
    3432             :     case Builtins::kArrayReduce:
    3433         227 :       return ReduceArrayReduce(node, ArrayReduceDirection::kLeft, shared);
    3434             :     case Builtins::kArrayReduceRight:
    3435         150 :       return ReduceArrayReduce(node, ArrayReduceDirection::kRight, shared);
    3436             :     case Builtins::kArrayPrototypeFind:
    3437         168 :       return ReduceArrayFind(node, ArrayFindVariant::kFind, shared);
    3438             :     case Builtins::kArrayPrototypeFindIndex:
    3439         115 :       return ReduceArrayFind(node, ArrayFindVariant::kFindIndex, shared);
    3440             :     case Builtins::kArrayEvery:
    3441         135 :       return ReduceArrayEvery(node, shared);
    3442             :     case Builtins::kArrayIndexOf:
    3443         952 :       return ReduceArrayIndexOfIncludes(SearchVariant::kIndexOf, node);
    3444             :     case Builtins::kArrayIncludes:
    3445          83 :       return ReduceArrayIndexOfIncludes(SearchVariant::kIncludes, node);
    3446             :     case Builtins::kArraySome:
    3447         139 :       return ReduceArraySome(node, shared);
    3448             :     case Builtins::kArrayPrototypePush:
    3449        4663 :       return ReduceArrayPrototypePush(node);
    3450             :     case Builtins::kArrayPrototypePop:
    3451         490 :       return ReduceArrayPrototypePop(node);
    3452             :     case Builtins::kArrayPrototypeShift:
    3453         481 :       return ReduceArrayPrototypeShift(node);
    3454             :     case Builtins::kArrayPrototypeSlice:
    3455         267 :       return ReduceArrayPrototypeSlice(node);
    3456             :     case Builtins::kArrayPrototypeEntries:
    3457           7 :       return ReduceArrayIterator(node, IterationKind::kEntries);
    3458             :     case Builtins::kArrayPrototypeKeys:
    3459           7 :       return ReduceArrayIterator(node, IterationKind::kKeys);
    3460             :     case Builtins::kArrayPrototypeValues:
    3461        1260 :       return ReduceArrayIterator(node, IterationKind::kValues);
    3462             :     case Builtins::kArrayIteratorPrototypeNext:
    3463        1478 :       return ReduceArrayIteratorPrototypeNext(node);
    3464             :     case Builtins::kArrayIsArray:
    3465          59 :       return ReduceArrayIsArray(node);
    3466             :     case Builtins::kArrayBufferIsView:
    3467          16 :       return ReduceArrayBufferIsView(node);
    3468             :     case Builtins::kDataViewPrototypeGetByteLength:
    3469             :       return ReduceArrayBufferViewAccessor(
    3470             :           node, JS_DATA_VIEW_TYPE,
    3471           2 :           AccessBuilder::ForJSArrayBufferViewByteLength());
    3472             :     case Builtins::kDataViewPrototypeGetByteOffset:
    3473             :       return ReduceArrayBufferViewAccessor(
    3474             :           node, JS_DATA_VIEW_TYPE,
    3475           0 :           AccessBuilder::ForJSArrayBufferViewByteOffset());
    3476             :     case Builtins::kDataViewPrototypeGetUint8:
    3477             :       return ReduceDataViewAccess(node, DataViewAccess::kGet,
    3478          52 :                                   ExternalArrayType::kExternalUint8Array);
    3479             :     case Builtins::kDataViewPrototypeGetInt8:
    3480             :       return ReduceDataViewAccess(node, DataViewAccess::kGet,
    3481          60 :                                   ExternalArrayType::kExternalInt8Array);
    3482             :     case Builtins::kDataViewPrototypeGetUint16:
    3483             :       return ReduceDataViewAccess(node, DataViewAccess::kGet,
    3484          36 :                                   ExternalArrayType::kExternalUint16Array);
    3485             :     case Builtins::kDataViewPrototypeGetInt16:
    3486             :       return ReduceDataViewAccess(node, DataViewAccess::kGet,
    3487          36 :                                   ExternalArrayType::kExternalInt16Array);
    3488             :     case Builtins::kDataViewPrototypeGetUint32:
    3489             :       return ReduceDataViewAccess(node, DataViewAccess::kGet,
    3490          29 :                                   ExternalArrayType::kExternalUint32Array);
    3491             :     case Builtins::kDataViewPrototypeGetInt32:
    3492             :       return ReduceDataViewAccess(node, DataViewAccess::kGet,
    3493          29 :                                   ExternalArrayType::kExternalInt32Array);
    3494             :     case Builtins::kDataViewPrototypeGetFloat32:
    3495             :       return ReduceDataViewAccess(node, DataViewAccess::kGet,
    3496          36 :                                   ExternalArrayType::kExternalFloat32Array);
    3497             :     case Builtins::kDataViewPrototypeGetFloat64:
    3498             :       return ReduceDataViewAccess(node, DataViewAccess::kGet,
    3499          36 :                                   ExternalArrayType::kExternalFloat64Array);
    3500             :     case Builtins::kDataViewPrototypeSetUint8:
    3501             :       return ReduceDataViewAccess(node, DataViewAccess::kSet,
    3502          39 :                                   ExternalArrayType::kExternalUint8Array);
    3503             :     case Builtins::kDataViewPrototypeSetInt8:
    3504             :       return ReduceDataViewAccess(node, DataViewAccess::kSet,
    3505          29 :                                   ExternalArrayType::kExternalInt8Array);
    3506             :     case Builtins::kDataViewPrototypeSetUint16:
    3507             :       return ReduceDataViewAccess(node, DataViewAccess::kSet,
    3508          29 :                                   ExternalArrayType::kExternalUint16Array);
    3509             :     case Builtins::kDataViewPrototypeSetInt16:
    3510             :       return ReduceDataViewAccess(node, DataViewAccess::kSet,
    3511          29 :                                   ExternalArrayType::kExternalInt16Array);
    3512             :     case Builtins::kDataViewPrototypeSetUint32:
    3513             :       return ReduceDataViewAccess(node, DataViewAccess::kSet,
    3514          29 :                                   ExternalArrayType::kExternalUint32Array);
    3515             :     case Builtins::kDataViewPrototypeSetInt32:
    3516             :       return ReduceDataViewAccess(node, DataViewAccess::kSet,
    3517          29 :                                   ExternalArrayType::kExternalInt32Array);
    3518             :     case Builtins::kDataViewPrototypeSetFloat32:
    3519             :       return ReduceDataViewAccess(node, DataViewAccess::kSet,
    3520          29 :                                   ExternalArrayType::kExternalFloat32Array);
    3521             :     case Builtins::kDataViewPrototypeSetFloat64:
    3522             :       return ReduceDataViewAccess(node, DataViewAccess::kSet,
    3523          29 :                                   ExternalArrayType::kExternalFloat64Array);
    3524             :     case Builtins::kTypedArrayPrototypeByteLength:
    3525             :       return ReduceArrayBufferViewAccessor(
    3526             :           node, JS_TYPED_ARRAY_TYPE,
    3527           0 :           AccessBuilder::ForJSArrayBufferViewByteLength());
    3528             :     case Builtins::kTypedArrayPrototypeByteOffset:
    3529             :       return ReduceArrayBufferViewAccessor(
    3530             :           node, JS_TYPED_ARRAY_TYPE,
    3531           0 :           AccessBuilder::ForJSArrayBufferViewByteOffset());
    3532             :     case Builtins::kTypedArrayPrototypeLength:
    3533             :       return ReduceArrayBufferViewAccessor(
    3534         306 :           node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength());
    3535             :     case Builtins::kTypedArrayPrototypeToStringTag:
    3536          21 :       return ReduceTypedArrayPrototypeToStringTag(node);
    3537             :     case Builtins::kMathAbs:
    3538         603 :       return ReduceMathUnary(node, simplified()->NumberAbs());
    3539             :     case Builtins::kMathAcos:
    3540           1 :       return ReduceMathUnary(node, simplified()->NumberAcos());
    3541             :     case Builtins::kMathAcosh:
    3542           1 :       return ReduceMathUnary(node, simplified()->NumberAcosh());
    3543             :     case Builtins::kMathAsin:
    3544           1 :       return ReduceMathUnary(node, simplified()->NumberAsin());
    3545             :     case Builtins::kMathAsinh:
    3546           1 :       return ReduceMathUnary(node, simplified()->NumberAsinh());
    3547             :     case Builtins::kMathAtan:
    3548           1 :       return ReduceMathUnary(node, simplified()->NumberAtan());
    3549             :     case Builtins::kMathAtanh:
    3550           0 :       return ReduceMathUnary(node, simplified()->NumberAtanh());
    3551             :     case Builtins::kMathCbrt:
    3552           1 :       return ReduceMathUnary(node, simplified()->NumberCbrt());
    3553             :     case Builtins::kMathCeil:
    3554        7259 :       return ReduceMathUnary(node, simplified()->NumberCeil());
    3555             :     case Builtins::kMathCos:
    3556          19 :       return ReduceMathUnary(node, simplified()->NumberCos());
    3557             :     case Builtins::kMathCosh:
    3558           8 :       return ReduceMathUnary(node, simplified()->NumberCosh());
    3559             :     case Builtins::kMathExp:
    3560          44 :       return ReduceMathUnary(node, simplified()->NumberExp());
    3561             :     case Builtins::kMathExpm1:
    3562          22 :       return ReduceMathUnary(node, simplified()->NumberExpm1());
    3563             :     case Builtins::kMathFloor:
    3564       27370 :       return ReduceMathUnary(node, simplified()->NumberFloor());
    3565             :     case Builtins::kMathFround:
    3566        1384 :       return ReduceMathUnary(node, simplified()->NumberFround());
    3567             :     case Builtins::kMathLog:
    3568         186 :       return ReduceMathUnary(node, simplified()->NumberLog());
    3569             :     case Builtins::kMathLog1p:
    3570           1 :       return ReduceMathUnary(node, simplified()->NumberLog1p());
    3571             :     case Builtins::kMathLog10:
    3572           1 :       return ReduceMathUnary(node, simplified()->NumberLog10());
    3573             :     case Builtins::kMathLog2:
    3574           1 :       return ReduceMathUnary(node, simplified()->NumberLog2());
    3575             :     case Builtins::kMathRound:
    3576        1606 :       return ReduceMathUnary(node, simplified()->NumberRound());
    3577             :     case Builtins::kMathSign:
    3578          38 :       return ReduceMathUnary(node, simplified()->NumberSign());
    3579             :     case Builtins::kMathSin:
    3580          59 :       return ReduceMathUnary(node, simplified()->NumberSin());
    3581             :     case Builtins::kMathSinh:
    3582           8 :       return ReduceMathUnary(node, simplified()->NumberSinh());
    3583             :     case Builtins::kMathSqrt:
    3584          74 :       return ReduceMathUnary(node, simplified()->NumberSqrt());
    3585             :     case Builtins::kMathTan:
    3586          44 :       return ReduceMathUnary(node, simplified()->NumberTan());
    3587             :     case Builtins::kMathTanh:
    3588           8 :       return ReduceMathUnary(node, simplified()->NumberTanh());
    3589             :     case Builtins::kMathTrunc:
    3590        7077 :       return ReduceMathUnary(node, simplified()->NumberTrunc());
    3591             :     case Builtins::kMathAtan2:
    3592          13 :       return ReduceMathBinary(node, simplified()->NumberAtan2());
    3593             :     case Builtins::kMathPow:
    3594        1008 :       return ReduceMathBinary(node, simplified()->NumberPow());
    3595             :     case Builtins::kMathClz32:
    3596          62 :       return ReduceMathClz32(node);
    3597             :     case Builtins::kMathImul:
    3598         870 :       return ReduceMathImul(node);
    3599             :     case Builtins::kMathMax:
    3600             :       return ReduceMathMinMax(node, simplified()->NumberMax(),
    3601         742 :                               jsgraph()->Constant(-V8_INFINITY));
    3602             :     case Builtins::kMathMin:
    3603             :       return ReduceMathMinMax(node, simplified()->NumberMin(),
    3604         786 :                               jsgraph()->Constant(V8_INFINITY));
    3605             :     case Builtins::kNumberIsFinite:
    3606         239 :       return ReduceNumberIsFinite(node);
    3607             :     case Builtins::kNumberIsInteger:
    3608         239 :       return ReduceNumberIsInteger(node);
    3609             :     case Builtins::kNumberIsSafeInteger:
    3610          15 :       return ReduceNumberIsSafeInteger(node);
    3611             :     case Builtins::kNumberIsNaN:
    3612          50 :       return ReduceNumberIsNaN(node);
    3613             :     case Builtins::kNumberParseInt:
    3614         576 :       return ReduceNumberParseInt(node);
    3615             :     case Builtins::kGlobalIsFinite:
    3616          42 :       return ReduceGlobalIsFinite(node);
    3617             :     case Builtins::kGlobalIsNaN:
    3618       14210 :       return ReduceGlobalIsNaN(node);
    3619             :     case Builtins::kMapPrototypeGet:
    3620         114 :       return ReduceMapPrototypeGet(node);
    3621             :     case Builtins::kMapPrototypeHas:
    3622          97 :       return ReduceMapPrototypeHas(node);
    3623             :     case Builtins::kRegExpPrototypeTest:
    3624         513 :       return ReduceRegExpPrototypeTest(node);
    3625             :     case Builtins::kReturnReceiver:
    3626         116 :       return ReduceReturnReceiver(node);
    3627             :     case Builtins::kStringPrototypeIndexOf:
    3628         304 :       return ReduceStringPrototypeIndexOf(node);
    3629             :     case Builtins::kStringPrototypeCharAt:
    3630         719 :       return ReduceStringPrototypeCharAt(node);
    3631             :     case Builtins::kStringPrototypeCharCodeAt:
    3632             :       return ReduceStringPrototypeStringAt(simplified()->StringCharCodeAt(),
    3633        1781 :                                            node);
    3634             :     case Builtins::kStringPrototypeCodePointAt:
    3635             :       return ReduceStringPrototypeStringAt(
    3636         598 :           simplified()->StringCodePointAt(UnicodeEncoding::UTF32), node);
    3637             :     case Builtins::kStringPrototypeSubstring:
    3638        1456 :       return ReduceStringPrototypeSubstring(node);
    3639             :     case Builtins::kStringPrototypeSlice:
    3640          27 :       return ReduceStringPrototypeSlice(node);
    3641             :     case Builtins::kStringPrototypeSubstr:
    3642          32 :       return ReduceStringPrototypeSubstr(node);
    3643             : #ifdef V8_INTL_SUPPORT
    3644             :     case Builtins::kStringPrototypeToLowerCaseIntl:
    3645          95 :       return ReduceStringPrototypeToLowerCaseIntl(node);
    3646             :     case Builtins::kStringPrototypeToUpperCaseIntl:
    3647          35 :       return ReduceStringPrototypeToUpperCaseIntl(node);
    3648             : #endif  // V8_INTL_SUPPORT
    3649             :     case Builtins::kStringFromCharCode:
    3650         231 :       return ReduceStringFromCharCode(node);
    3651             :     case Builtins::kStringFromCodePoint:
    3652         268 :       return ReduceStringFromCodePoint(node);
    3653             :     case Builtins::kStringPrototypeIterator:
    3654          67 :       return ReduceStringPrototypeIterator(node);
    3655             :     case Builtins::kStringIteratorPrototypeNext:
    3656          95 :       return ReduceStringIteratorPrototypeNext(node);
    3657             :     case Builtins::kStringPrototypeConcat:
    3658          67 :       return ReduceStringPrototypeConcat(node);
    3659             :     case Builtins::kTypedArrayPrototypeEntries:
    3660           9 :       return ReduceArrayIterator(node, IterationKind::kEntries);
    3661             :     case Builtins::kTypedArrayPrototypeKeys:
    3662           0 :       return ReduceArrayIterator(node, IterationKind::kKeys);
    3663             :     case Builtins::kTypedArrayPrototypeValues:
    3664          50 :       return ReduceArrayIterator(node, IterationKind::kValues);
    3665             :     case Builtins::kPromiseInternalConstructor:
    3666           6 :       return ReducePromiseInternalConstructor(node);
    3667             :     case Builtins::kPromiseInternalReject:
    3668           3 :       return ReducePromiseInternalReject(node);
    3669             :     case Builtins::kPromiseInternalResolve:
    3670           3 :       return ReducePromiseInternalResolve(node);
    3671             :     case Builtins::kPromisePrototypeCatch:
    3672          52 :       return ReducePromisePrototypeCatch(node);
    3673             :     case Builtins::kPromisePrototypeFinally:
    3674          63 :       return ReducePromisePrototypeFinally(node);
    3675             :     case Builtins::kPromisePrototypeThen:
    3676         100 :       return ReducePromisePrototypeThen(node);
    3677             :     case Builtins::kPromiseResolveTrampoline:
    3678         119 :       return ReducePromiseResolveTrampoline(node);
    3679             :     case Builtins::kMapPrototypeEntries:
    3680             :       return ReduceCollectionIteration(node, CollectionKind::kMap,
    3681          22 :                                        IterationKind::kEntries);
    3682             :     case Builtins::kMapPrototypeKeys:
    3683             :       return ReduceCollectionIteration(node, CollectionKind::kMap,
    3684          15 :                                        IterationKind::kKeys);
    3685             :     case Builtins::kMapPrototypeGetSize:
    3686          97 :       return ReduceCollectionPrototypeSize(node, CollectionKind::kMap);
    3687             :     case Builtins::kMapPrototypeValues:
    3688             :       return ReduceCollectionIteration(node, CollectionKind::kMap,
    3689          35 :                                        IterationKind::kValues);
    3690             :     case Builtins::kMapIteratorPrototypeNext:
    3691             :       return ReduceCollectionIteratorPrototypeNext(
    3692             :           node, OrderedHashMap::kEntrySize, factory()->empty_ordered_hash_map(),
    3693         112 :           FIRST_MAP_ITERATOR_TYPE, LAST_MAP_ITERATOR_TYPE);
    3694             :     case Builtins::kSetPrototypeEntries:
    3695             :       return ReduceCollectionIteration(node, CollectionKind::kSet,
    3696          14 :                                        IterationKind::kEntries);
    3697             :     case Builtins::kSetPrototypeGetSize:
    3698          17 :       return ReduceCollectionPrototypeSize(node, CollectionKind::kSet);
    3699             :     case Builtins::kSetPrototypeValues:
    3700             :       return ReduceCollectionIteration(node, CollectionKind::kSet,
    3701          78 :                                        IterationKind::kValues);
    3702             :     case Builtins::kSetIteratorPrototypeNext:
    3703             :       return ReduceCollectionIteratorPrototypeNext(
    3704             :           node, OrderedHashSet::kEntrySize, factory()->empty_ordered_hash_set(),
    3705         168 :           FIRST_SET_ITERATOR_TYPE, LAST_SET_ITERATOR_TYPE);
    3706             :     case Builtins::kDatePrototypeGetTime:
    3707           0 :       return ReduceDatePrototypeGetTime(node);
    3708             :     case Builtins::kDateNow:
    3709           7 :       return ReduceDateNow(node);
    3710             :     case Builtins::kNumberConstructor:
    3711         505 :       return ReduceNumberConstructor(node);
    3712             :     default:
    3713             :       break;
    3714             :   }
    3715             : 
    3716      621851 :   if (!FLAG_runtime_stats && shared.object()->IsApiFunction()) {
    3717       12613 :     return ReduceCallApiFunction(node, shared);
    3718             :   }
    3719             :   return NoChange();
    3720             : }
    3721             : 
    3722         803 : Reduction JSCallReducer::ReduceJSCallWithArrayLike(Node* node) {
    3723             :   DCHECK_EQ(IrOpcode::kJSCallWithArrayLike, node->opcode());
    3724         803 :   CallFrequency frequency = CallFrequencyOf(node->op());
    3725         803 :   VectorSlotPair feedback;
    3726             :   return ReduceCallOrConstructWithArrayLikeOrSpread(node, 2, frequency,
    3727         803 :                                                     feedback);
    3728             : }
    3729             : 
    3730        1205 : Reduction JSCallReducer::ReduceJSCallWithSpread(Node* node) {
    3731             :   DCHECK_EQ(IrOpcode::kJSCallWithSpread, node->opcode());
    3732        1205 :   CallParameters const& p = CallParametersOf(node->op());
    3733             :   DCHECK_LE(3u, p.arity());
    3734        1205 :   int arity = static_cast<int>(p.arity() - 1);
    3735        1205 :   CallFrequency frequency = p.frequency();
    3736        1205 :   VectorSlotPair feedback = p.feedback();
    3737             :   return ReduceCallOrConstructWithArrayLikeOrSpread(node, arity, frequency,
    3738        1205 :                                                     feedback);
    3739             : }
    3740             : 
    3741       71840 : Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
    3742             :   DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
    3743       44257 :   ConstructParameters const& p = ConstructParametersOf(node->op());
    3744             :   DCHECK_LE(2u, p.arity());
    3745       44257 :   int arity = static_cast<int>(p.arity() - 2);
    3746       54212 :   Node* target = NodeProperties::GetValueInput(node, 0);
    3747       44259 :   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
    3748       44259 :   Node* effect = NodeProperties::GetEffectInput(node);
    3749       44259 :   Node* control = NodeProperties::GetControlInput(node);
    3750             : 
    3751             :   // Extract feedback from the {node} using the FeedbackNexus.
    3752       44259 :   if (p.feedback().IsValid()) {
    3753       44178 :     FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    3754       44178 :     if (nexus.IsUninitialized()) {
    3755       30321 :       if (flags() & kBailoutOnUninitialized) {
    3756             :         // Introduce a SOFT deopt if the construct {node} wasn't executed so
    3757             :         // far.
    3758             :         return ReduceSoftDeoptimize(
    3759       33118 :             node, DeoptimizeReason::kInsufficientTypeFeedbackForConstruct);
    3760             :       }
    3761             :       return NoChange();
    3762             :     }
    3763             : 
    3764             :     base::Optional<HeapObjectRef> feedback =
    3765       13857 :         GetHeapObjectFeedback(broker(), nexus);
    3766       13857 :     if (feedback.has_value() && feedback->IsAllocationSite()) {
    3767             :       // The feedback is an AllocationSite, which means we have called the
    3768             :       // Array function and collected transition (and pretenuring) feedback
    3769             :       // for the resulting arrays.  This has to be kept in sync with the
    3770             :       // implementation in Ignition.
    3771             : 
    3772             :       Node* array_function =
    3773        1106 :           jsgraph()->Constant(native_context().array_function());
    3774             : 
    3775             :       // Check that the {target} is still the {array_function}.
    3776             :       Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
    3777         553 :                                      array_function);
    3778             :       effect = graph()->NewNode(
    3779             :           simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
    3780        1659 :           effect, control);
    3781             : 
    3782             :       // Turn the {node} into a {JSCreateArray} call.
    3783         553 :       NodeProperties::ReplaceEffectInput(node, effect);
    3784        1152 :       for (int i = arity; i > 0; --i) {
    3785             :         NodeProperties::ReplaceValueInput(
    3786         599 :             node, NodeProperties::GetValueInput(node, i), i + 1);
    3787             :       }
    3788         553 :       NodeProperties::ReplaceValueInput(node, array_function, 1);
    3789             :       NodeProperties::ChangeOp(
    3790             :           node, javascript()->CreateArray(
    3791        1659 :                     arity, feedback->AsAllocationSite().object()));
    3792             :       return Changed(node);
    3793       39912 :     } else if (feedback.has_value() &&
    3794       16144 :                !HeapObjectMatcher(new_target).HasValue() &&
    3795       16144 :                feedback->map().is_constructor()) {
    3796        2245 :       Node* new_target_feedback = jsgraph()->Constant(*feedback);
    3797             : 
    3798             :       // Check that the {new_target} is still the {new_target_feedback}.
    3799             :       Node* check = graph()->NewNode(simplified()->ReferenceEqual(), new_target,
    3800        2245 :                                      new_target_feedback);
    3801             :       effect = graph()->NewNode(
    3802             :           simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
    3803        6735 :           effect, control);
    3804             : 
    3805             :       // Specialize the JSConstruct node to the {new_target_feedback}.
    3806        2245 :       NodeProperties::ReplaceValueInput(node, new_target_feedback, arity + 1);
    3807        2245 :       NodeProperties::ReplaceEffectInput(node, effect);
    3808        2245 :       if (target == new_target) {
    3809        2183 :         NodeProperties::ReplaceValueInput(node, new_target_feedback, 0);
    3810             :       }
    3811             : 
    3812             :       // Try to further reduce the JSConstruct {node}.
    3813        2245 :       Reduction const reduction = ReduceJSConstruct(node);
    3814        2245 :       return reduction.Changed() ? reduction : Changed(node);
    3815             :     }
    3816             :   }
    3817             : 
    3818             :   // Try to specialize JSConstruct {node}s with constant {target}s.
    3819             :   HeapObjectMatcher m(target);
    3820       11140 :   if (m.HasValue()) {
    3821       10767 :     HeapObjectRef target_ref = m.Ref(broker()).AsHeapObject();
    3822             : 
    3823             :     // Raise a TypeError if the {target} is not a constructor.
    3824       10767 :     if (!target_ref.map().is_constructor()) {
    3825           7 :       NodeProperties::ReplaceValueInputs(node, target);
    3826             :       NodeProperties::ChangeOp(node,
    3827             :                                javascript()->CallRuntime(
    3828           7 :                                    Runtime::kThrowConstructedNonConstructable));
    3829        1185 :       return Changed(node);
    3830             :     }
    3831             : 
    3832       10760 :     if (target_ref.IsJSFunction()) {
    3833        9943 :       JSFunctionRef function = target_ref.AsJSFunction();
    3834        9943 :       function.Serialize();
    3835             : 
    3836             :       // Do not reduce constructors with break points.
    3837       11072 :       if (function.shared().HasBreakInfo()) return NoChange();
    3838             : 
    3839             :       // Don't inline cross native context.
    3840        9939 :       if (!function.native_context().equals(native_context())) {
    3841             :         return NoChange();
    3842             :       }
    3843             : 
    3844             :       // Check for known builtin functions.
    3845       19878 :       int builtin_id = function.shared().HasBuiltinId()
    3846       12659 :                            ? function.shared().builtin_id()
    3847       12659 :                            : Builtins::kNoBuiltinId;
    3848        9939 :       switch (builtin_id) {
    3849             :         case Builtins::kArrayConstructor: {
    3850             :           // TODO(bmeurer): Deal with Array subclasses here.
    3851             :           // Turn the {node} into a {JSCreateArray} call.
    3852         210 :           for (int i = arity; i > 0; --i) {
    3853             :             NodeProperties::ReplaceValueInput(
    3854         210 :                 node, NodeProperties::GetValueInput(node, i), i + 1);
    3855             :           }
    3856         363 :           NodeProperties::ReplaceValueInput(node, new_target, 1);
    3857             :           NodeProperties::ChangeOp(
    3858         726 :               node, javascript()->CreateArray(arity, Handle<AllocationSite>()));
    3859             :           return Changed(node);
    3860             :         }
    3861             :         case Builtins::kObjectConstructor: {
    3862             :           // If no value is passed, we can immediately lower to a simple
    3863             :           // JSCreate and don't need to do any massaging of the {node}.
    3864         145 :           if (arity == 0) {
    3865         131 :             NodeProperties::ChangeOp(node, javascript()->Create());
    3866             :             return Changed(node);
    3867             :           }
    3868             : 
    3869             :           // Otherwise we can only lower to JSCreate if we know that
    3870             :           // the value parameter is ignored, which is only the case if
    3871             :           // the {new_target} and {target} are definitely not identical.
    3872             :           HeapObjectMatcher mnew_target(new_target);
    3873          42 :           if (mnew_target.HasValue() &&
    3874          42 :               !mnew_target.Ref(broker()).equals(function)) {
    3875             :             // Drop the value inputs.
    3876          21 :             for (int i = arity; i > 0; --i) node->RemoveInput(i);
    3877           7 :             NodeProperties::ChangeOp(node, javascript()->Create());
    3878             :             return Changed(node);
    3879             :           }
    3880             :           break;
    3881             :         }
    3882             :         case Builtins::kPromiseConstructor:
    3883         139 :           return ReducePromiseConstructor(node);
    3884             :         case Builtins::kTypedArrayConstructor:
    3885         485 :           return ReduceTypedArrayConstructor(node, function.shared());
    3886             :         default:
    3887             :           break;
    3888             :       }
    3889         817 :     } else if (target_ref.IsJSBoundFunction()) {
    3890          49 :       JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
    3891          49 :       function.Serialize();
    3892             : 
    3893          49 :       ObjectRef bound_target_function = function.bound_target_function();
    3894          49 :       FixedArrayRef bound_arguments = function.bound_arguments();
    3895             : 
    3896             :       // Patch {node} to use [[BoundTargetFunction]].
    3897             :       NodeProperties::ReplaceValueInput(
    3898          49 :           node, jsgraph()->Constant(bound_target_function), 0);
    3899             : 
    3900             :       // Patch {node} to use [[BoundTargetFunction]]
    3901             :       // as new.target if {new_target} equals {target}.
    3902             :       NodeProperties::ReplaceValueInput(
    3903             :           node,
    3904             :           graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
    3905             :                            graph()->NewNode(simplified()->ReferenceEqual(),
    3906             :                                             target, new_target),
    3907             :                            jsgraph()->Constant(bound_target_function),
    3908             :                            new_target),
    3909         196 :           arity + 1);
    3910             : 
    3911             :       // Insert the [[BoundArguments]] for {node}.
    3912         147 :       for (int i = 0; i < bound_arguments.length(); ++i) {
    3913             :         node->InsertInput(graph()->zone(), i + 1,
    3914         147 :                           jsgraph()->Constant(bound_arguments.get(i)));
    3915          49 :         arity++;
    3916             :       }
    3917             : 
    3918             :       // Update the JSConstruct operator on {node}.
    3919             :       NodeProperties::ChangeOp(
    3920             :           node,
    3921          98 :           javascript()->Construct(arity + 2, p.frequency(), VectorSlotPair()));
    3922             : 
    3923             :       // Try to further reduce the JSConstruct {node}.
    3924          49 :       Reduction const reduction = ReduceJSConstruct(node);
    3925          49 :       return reduction.Changed() ? reduction : Changed(node);
    3926             :     }
    3927             : 
    3928             :     // TODO(bmeurer): Also support optimizing proxies here.
    3929             :   }
    3930             : 
    3931             :   // If {target} is the result of a JSCreateBoundFunction operation,
    3932             :   // we can just fold the construction and construct the bound target
    3933             :   // function directly instead.
    3934        9955 :   if (target->opcode() == IrOpcode::kJSCreateBoundFunction) {
    3935           0 :     Node* bound_target_function = NodeProperties::GetValueInput(target, 0);
    3936             :     int const bound_arguments_length =
    3937           0 :         static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity());
    3938             : 
    3939             :     // Patch the {node} to use [[BoundTargetFunction]].
    3940           0 :     NodeProperties::ReplaceValueInput(node, bound_target_function, 0);
    3941             : 
    3942             :     // Patch {node} to use [[BoundTargetFunction]]
    3943             :     // as new.target if {new_target} equals {target}.
    3944             :     NodeProperties::ReplaceValueInput(
    3945             :         node,
    3946             :         graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
    3947             :                          graph()->NewNode(simplified()->ReferenceEqual(),
    3948             :                                           target, new_target),
    3949             :                          bound_target_function, new_target),
    3950           0 :         arity + 1);
    3951             : 
    3952             :     // Insert the [[BoundArguments]] for {node}.
    3953           0 :     for (int i = 0; i < bound_arguments_length; ++i) {
    3954           0 :       Node* value = NodeProperties::GetValueInput(target, 2 + i);
    3955           0 :       node->InsertInput(graph()->zone(), 1 + i, value);
    3956           0 :       arity++;
    3957             :     }
    3958             : 
    3959             :     // Update the JSConstruct operator on {node}.
    3960             :     NodeProperties::ChangeOp(
    3961             :         node,
    3962           0 :         javascript()->Construct(arity + 2, p.frequency(), VectorSlotPair()));
    3963             : 
    3964             :     // Try to further reduce the JSConstruct {node}.
    3965           0 :     Reduction const reduction = ReduceJSConstruct(node);
    3966           0 :     return reduction.Changed() ? reduction : Changed(node);
    3967             :   }
    3968             : 
    3969             :   return NoChange();
    3970             : }
    3971             : 
    3972             : // ES #sec-string.prototype.indexof
    3973        1171 : Reduction JSCallReducer::ReduceStringPrototypeIndexOf(Node* node) {
    3974             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    3975         304 :   CallParameters const& p = CallParametersOf(node->op());
    3976         304 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    3977             :     return NoChange();
    3978             :   }
    3979             : 
    3980         289 :   Node* effect = NodeProperties::GetEffectInput(node);
    3981         289 :   Node* control = NodeProperties::GetControlInput(node);
    3982         578 :   if (node->op()->ValueInputCount() >= 3) {
    3983         289 :     Node* receiver = NodeProperties::GetValueInput(node, 1);
    3984             :     Node* new_receiver = effect = graph()->NewNode(
    3985         578 :         simplified()->CheckString(p.feedback()), receiver, effect, control);
    3986             : 
    3987         289 :     Node* search_string = NodeProperties::GetValueInput(node, 2);
    3988             :     Node* new_search_string = effect =
    3989             :         graph()->NewNode(simplified()->CheckString(p.feedback()), search_string,
    3990         289 :                          effect, control);
    3991             : 
    3992         289 :     Node* new_position = jsgraph()->ZeroConstant();
    3993         578 :     if (node->op()->ValueInputCount() >= 4) {
    3994         105 :       Node* position = NodeProperties::GetValueInput(node, 3);
    3995             :       new_position = effect = graph()->NewNode(
    3996         105 :           simplified()->CheckSmi(p.feedback()), position, effect, control);
    3997             :     }
    3998             : 
    3999         289 :     NodeProperties::ReplaceEffectInput(node, effect);
    4000             :     RelaxEffectsAndControls(node);
    4001         289 :     node->ReplaceInput(0, new_receiver);
    4002         289 :     node->ReplaceInput(1, new_search_string);
    4003         289 :     node->ReplaceInput(2, new_position);
    4004         289 :     node->TrimInputCount(3);
    4005         289 :     NodeProperties::ChangeOp(node, simplified()->StringIndexOf());
    4006             :     return Changed(node);
    4007             :   }
    4008             :   return NoChange();
    4009             : }
    4010             : 
    4011             : // ES #sec-string.prototype.substring
    4012        7069 : Reduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) {
    4013        2912 :   if (node->op()->ValueInputCount() < 3) return NoChange();
    4014        1456 :   CallParameters const& p = CallParametersOf(node->op());
    4015        1456 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    4016             :     return NoChange();
    4017             :   }
    4018             : 
    4019        1395 :   Node* effect = NodeProperties::GetEffectInput(node);
    4020        1395 :   Node* control = NodeProperties::GetControlInput(node);
    4021        1395 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    4022        1395 :   Node* start = NodeProperties::GetValueInput(node, 2);
    4023        1395 :   Node* end = node->op()->ValueInputCount() > 3
    4024             :                   ? NodeProperties::GetValueInput(node, 3)
    4025        1428 :                   : jsgraph()->UndefinedConstant();
    4026             : 
    4027        1395 :   receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
    4028        1395 :                                        receiver, effect, control);
    4029             : 
    4030             :   start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
    4031        1395 :                                     effect, control);
    4032             : 
    4033        1395 :   Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
    4034             : 
    4035             :   Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
    4036        2790 :                                  jsgraph()->UndefinedConstant());
    4037             :   Node* branch =
    4038        1395 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    4039             : 
    4040        1395 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    4041             :   Node* etrue = effect;
    4042             :   Node* vtrue = length;
    4043             : 
    4044        1395 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    4045             :   Node* efalse = effect;
    4046             :   Node* vfalse = efalse = graph()->NewNode(simplified()->CheckSmi(p.feedback()),
    4047        1395 :                                            end, efalse, if_false);
    4048             : 
    4049        1395 :   control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    4050        1395 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    4051             :   end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    4052        1395 :                          vtrue, vfalse, control);
    4053             :   Node* finalStart =
    4054             :       graph()->NewNode(simplified()->NumberMin(),
    4055             :                        graph()->NewNode(simplified()->NumberMax(), start,
    4056             :                                         jsgraph()->ZeroConstant()),
    4057        4185 :                        length);
    4058             :   Node* finalEnd =
    4059             :       graph()->NewNode(simplified()->NumberMin(),
    4060             :                        graph()->NewNode(simplified()->NumberMax(), end,
    4061             :                                         jsgraph()->ZeroConstant()),
    4062        4185 :                        length);
    4063             : 
    4064             :   Node* from =
    4065        1395 :       graph()->NewNode(simplified()->NumberMin(), finalStart, finalEnd);
    4066        1395 :   Node* to = graph()->NewNode(simplified()->NumberMax(), finalStart, finalEnd);
    4067             : 
    4068             :   Node* value = effect = graph()->NewNode(simplified()->StringSubstring(),
    4069        1395 :                                           receiver, from, to, effect, control);
    4070        1395 :   ReplaceWithValue(node, value, effect, control);
    4071             :   return Replace(value);
    4072             : }
    4073             : 
    4074             : // ES #sec-string.prototype.slice
    4075         234 : Reduction JSCallReducer::ReduceStringPrototypeSlice(Node* node) {
    4076          54 :   if (node->op()->ValueInputCount() < 3) return NoChange();
    4077          27 :   CallParameters const& p = CallParametersOf(node->op());
    4078          27 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    4079             :     return NoChange();
    4080             :   }
    4081             : 
    4082          27 :   Node* effect = NodeProperties::GetEffectInput(node);
    4083          27 :   Node* control = NodeProperties::GetControlInput(node);
    4084          27 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    4085          27 :   Node* start = NodeProperties::GetValueInput(node, 2);
    4086          27 :   Node* end = node->op()->ValueInputCount() > 3
    4087             :                   ? NodeProperties::GetValueInput(node, 3)
    4088          45 :                   : jsgraph()->UndefinedConstant();
    4089             : 
    4090          27 :   receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
    4091          27 :                                        receiver, effect, control);
    4092             : 
    4093             :   start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
    4094          27 :                                     effect, control);
    4095             : 
    4096          27 :   Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
    4097             : 
    4098             :   // Replace {end} argument with {length} if it is undefined.
    4099             :   {
    4100             :     Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
    4101          54 :                                    jsgraph()->UndefinedConstant());
    4102             : 
    4103             :     Node* branch =
    4104          27 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    4105             : 
    4106          27 :     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    4107             :     Node* etrue = effect;
    4108             :     Node* vtrue = length;
    4109             : 
    4110          27 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    4111             :     Node* efalse = effect;
    4112             :     Node* vfalse = efalse = graph()->NewNode(
    4113          27 :         simplified()->CheckSmi(p.feedback()), end, efalse, if_false);
    4114             : 
    4115          27 :     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    4116          27 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    4117             :     end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    4118          27 :                            vtrue, vfalse, control);
    4119             :   }
    4120             : 
    4121             :   Node* from = graph()->NewNode(
    4122             :       common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
    4123             :       graph()->NewNode(simplified()->NumberLessThan(), start,
    4124             :                        jsgraph()->ZeroConstant()),
    4125             :       graph()->NewNode(
    4126             :           simplified()->NumberMax(),
    4127             :           graph()->NewNode(simplified()->NumberAdd(), length, start),
    4128             :           jsgraph()->ZeroConstant()),
    4129         189 :       graph()->NewNode(simplified()->NumberMin(), start, length));
    4130             :   // {from} is always in non-negative Smi range, but our typer cannot
    4131             :   // figure that out yet.
    4132             :   from = effect = graph()->NewNode(common()->TypeGuard(Type::UnsignedSmall()),
    4133          27 :                                    from, effect, control);
    4134             : 
    4135             :   Node* to = graph()->NewNode(
    4136             :       common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
    4137             :       graph()->NewNode(simplified()->NumberLessThan(), end,
    4138             :                        jsgraph()->ZeroConstant()),
    4139             :       graph()->NewNode(simplified()->NumberMax(),
    4140             :                        graph()->NewNode(simplified()->NumberAdd(), length, end),
    4141             :                        jsgraph()->ZeroConstant()),
    4142         189 :       graph()->NewNode(simplified()->NumberMin(), end, length));
    4143             :   // {to} is always in non-negative Smi range, but our typer cannot
    4144             :   // figure that out yet.
    4145             :   to = effect = graph()->NewNode(common()->TypeGuard(Type::UnsignedSmall()), to,
    4146          27 :                                  effect, control);
    4147             : 
    4148             :   Node* result_string = nullptr;
    4149             :   // Return empty string if {from} is smaller than {to}.
    4150             :   {
    4151          27 :     Node* check = graph()->NewNode(simplified()->NumberLessThan(), from, to);
    4152             : 
    4153             :     Node* branch =
    4154          27 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    4155             : 
    4156          27 :     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    4157             :     Node* etrue = effect;
    4158             :     Node* vtrue = etrue = graph()->NewNode(simplified()->StringSubstring(),
    4159          27 :                                            receiver, from, to, etrue, if_true);
    4160             : 
    4161          27 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    4162             :     Node* efalse = effect;
    4163          27 :     Node* vfalse = jsgraph()->EmptyStringConstant();
    4164             : 
    4165          27 :     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    4166          27 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    4167             :     result_string =
    4168             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    4169          27 :                          vtrue, vfalse, control);
    4170             :   }
    4171             : 
    4172          27 :   ReplaceWithValue(node, result_string, effect, control);
    4173             :   return Replace(result_string);
    4174             : }
    4175             : 
    4176             : // ES #sec-string.prototype.substr
    4177         288 : Reduction JSCallReducer::ReduceStringPrototypeSubstr(Node* node) {
    4178          64 :   if (node->op()->ValueInputCount() < 3) return NoChange();
    4179          32 :   CallParameters const& p = CallParametersOf(node->op());
    4180          32 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    4181             :     return NoChange();
    4182             :   }
    4183             : 
    4184          32 :   Node* effect = NodeProperties::GetEffectInput(node);
    4185          32 :   Node* control = NodeProperties::GetControlInput(node);
    4186          32 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    4187          32 :   Node* start = NodeProperties::GetValueInput(node, 2);
    4188          32 :   Node* end = node->op()->ValueInputCount() > 3
    4189             :                   ? NodeProperties::GetValueInput(node, 3)
    4190          64 :                   : jsgraph()->UndefinedConstant();
    4191             : 
    4192          32 :   receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
    4193          32 :                                        receiver, effect, control);
    4194             : 
    4195             :   start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
    4196          32 :                                     effect, control);
    4197             : 
    4198          32 :   Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
    4199             : 
    4200             :   // Replace {end} argument with {length} if it is undefined.
    4201             :   {
    4202             :     Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
    4203          64 :                                    jsgraph()->UndefinedConstant());
    4204             :     Node* branch =
    4205          32 :         graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    4206             : 
    4207          32 :     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    4208             :     Node* etrue = effect;
    4209             :     Node* vtrue = length;
    4210             : 
    4211          32 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    4212             :     Node* efalse = effect;
    4213             :     Node* vfalse = efalse = graph()->NewNode(
    4214          32 :         simplified()->CheckSmi(p.feedback()), end, efalse, if_false);
    4215             : 
    4216          32 :     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    4217          32 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    4218             :     end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    4219          32 :                            vtrue, vfalse, control);
    4220             :   }
    4221             : 
    4222             :   Node* initStart = graph()->NewNode(
    4223             :       common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
    4224             :       graph()->NewNode(simplified()->NumberLessThan(), start,
    4225             :                        jsgraph()->ZeroConstant()),
    4226             :       graph()->NewNode(
    4227             :           simplified()->NumberMax(),
    4228             :           graph()->NewNode(simplified()->NumberAdd(), length, start),
    4229             :           jsgraph()->ZeroConstant()),
    4230         192 :       start);
    4231             :   // The select above guarantees that initStart is non-negative, but
    4232             :   // our typer can't figure that out yet.
    4233             :   initStart = effect = graph()->NewNode(
    4234          32 :       common()->TypeGuard(Type::UnsignedSmall()), initStart, effect, control);
    4235             : 
    4236             :   Node* resultLength = graph()->NewNode(
    4237             :       simplified()->NumberMin(),
    4238             :       graph()->NewNode(simplified()->NumberMax(), end,
    4239             :                        jsgraph()->ZeroConstant()),
    4240         128 :       graph()->NewNode(simplified()->NumberSubtract(), length, initStart));
    4241             : 
    4242             :   // The the select below uses {resultLength} only if {resultLength > 0},
    4243             :   // but our typer can't figure that out yet.
    4244             :   Node* to = effect = graph()->NewNode(
    4245             :       common()->TypeGuard(Type::UnsignedSmall()),
    4246             :       graph()->NewNode(simplified()->NumberAdd(), initStart, resultLength),
    4247          64 :       effect, control);
    4248             : 
    4249             :   Node* result_string = nullptr;
    4250             :   // Return empty string if {from} is smaller than {to}.
    4251             :   {
    4252             :     Node* check = graph()->NewNode(simplified()->NumberLessThan(),
    4253          64 :                                    jsgraph()->ZeroConstant(), resultLength);
    4254             : 
    4255             :     Node* branch =
    4256          32 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    4257             : 
    4258          32 :     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    4259             :     Node* etrue = effect;
    4260             :     Node* vtrue = etrue =
    4261             :         graph()->NewNode(simplified()->StringSubstring(), receiver, initStart,
    4262          32 :                          to, etrue, if_true);
    4263             : 
    4264          32 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    4265             :     Node* efalse = effect;
    4266          32 :     Node* vfalse = jsgraph()->EmptyStringConstant();
    4267             : 
    4268          32 :     control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    4269          32 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    4270             :     result_string =
    4271             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    4272          32 :                          vtrue, vfalse, control);
    4273             :   }
    4274             : 
    4275          32 :   ReplaceWithValue(node, result_string, effect, control);
    4276             :   return Replace(result_string);
    4277             : }
    4278             : 
    4279         196 : Reduction JSCallReducer::ReduceJSConstructWithArrayLike(Node* node) {
    4280             :   DCHECK_EQ(IrOpcode::kJSConstructWithArrayLike, node->opcode());
    4281         196 :   CallFrequency frequency = CallFrequencyOf(node->op());
    4282         196 :   VectorSlotPair feedback;
    4283             :   return ReduceCallOrConstructWithArrayLikeOrSpread(node, 1, frequency,
    4284         196 :                                                     feedback);
    4285             : }
    4286             : 
    4287         997 : Reduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) {
    4288             :   DCHECK_EQ(IrOpcode::kJSConstructWithSpread, node->opcode());
    4289         997 :   ConstructParameters const& p = ConstructParametersOf(node->op());
    4290             :   DCHECK_LE(3u, p.arity());
    4291         997 :   int arity = static_cast<int>(p.arity() - 2);
    4292         997 :   CallFrequency frequency = p.frequency();
    4293         997 :   VectorSlotPair feedback = p.feedback();
    4294             :   return ReduceCallOrConstructWithArrayLikeOrSpread(node, arity, frequency,
    4295         997 :                                                     feedback);
    4296             : }
    4297             : 
    4298         116 : Reduction JSCallReducer::ReduceReturnReceiver(Node* node) {
    4299             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    4300         116 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    4301         116 :   ReplaceWithValue(node, receiver);
    4302         116 :   return Replace(receiver);
    4303             : }
    4304             : 
    4305           0 : Reduction JSCallReducer::ReduceSoftDeoptimize(Node* node,
    4306             :                                               DeoptimizeReason reason) {
    4307           0 :   Node* effect = NodeProperties::GetEffectInput(node);
    4308           0 :   Node* control = NodeProperties::GetControlInput(node);
    4309           0 :   Node* frame_state = NodeProperties::FindFrameStateBefore(node);
    4310             :   Node* deoptimize = graph()->NewNode(
    4311             :       common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
    4312           0 :       frame_state, effect, control);
    4313             :   // TODO(bmeurer): This should be on the AdvancedReducer somehow.
    4314           0 :   NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
    4315           0 :   Revisit(graph()->end());
    4316           0 :   node->TrimInputCount(0);
    4317           0 :   NodeProperties::ChangeOp(node, common()->Dead());
    4318           0 :   return Changed(node);
    4319             : }
    4320             : 
    4321             : // ES6 section 22.1.3.18 Array.prototype.push ( )
    4322       28373 : Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
    4323             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    4324        4663 :   CallParameters const& p = CallParametersOf(node->op());
    4325        4663 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    4326             :     return NoChange();
    4327             :   }
    4328             : 
    4329        9150 :   int const num_values = node->op()->ValueInputCount() - 2;
    4330        4575 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    4331        4575 :   Node* effect = NodeProperties::GetEffectInput(node);
    4332        4575 :   Node* control = NodeProperties::GetControlInput(node);
    4333             : 
    4334             :   ZoneHandleSet<Map> receiver_maps;
    4335             :   NodeProperties::InferReceiverMapsResult result =
    4336             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    4337        4575 :                                         &receiver_maps);
    4338        4575 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    4339             :   DCHECK_NE(0, receiver_maps.size());
    4340             : 
    4341             :   ElementsKind kind;
    4342        4557 :   if (!CanInlineArrayResizingBuiltin(broker(), receiver_maps, &kind, true)) {
    4343             :     return NoChange();
    4344             :   }
    4345             : 
    4346             :   dependencies()->DependOnProtector(
    4347        1944 :       PropertyCellRef(broker(), factory()->no_elements_protector()));
    4348             : 
    4349             :   // If the {receiver_maps} information is not reliable, we need
    4350             :   // to check that the {receiver} still has one of these maps.
    4351        1944 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    4352             :     effect =
    4353             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    4354         432 :                                                  receiver_maps, p.feedback()),
    4355         864 :                          receiver, effect, control);
    4356             :   }
    4357             : 
    4358             :   // Collect the value inputs to push.
    4359        1944 :   std::vector<Node*> values(num_values);
    4360        4267 :   for (int i = 0; i < num_values; ++i) {
    4361        4646 :     values[i] = NodeProperties::GetValueInput(node, 2 + i);
    4362             :   }
    4363             : 
    4364        6211 :   for (auto& value : values) {
    4365        2323 :     if (IsSmiElementsKind(kind)) {
    4366        1226 :       value = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()),
    4367        3678 :                                         value, effect, control);
    4368        1097 :     } else if (IsDoubleElementsKind(kind)) {
    4369         379 :       value = effect = graph()->NewNode(simplified()->CheckNumber(p.feedback()),
    4370        1137 :                                         value, effect, control);
    4371             :       // Make sure we do not store signaling NaNs into double arrays.
    4372         758 :       value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
    4373             :     }
    4374             :   }
    4375             : 
    4376             :   // Load the "length" property of the {receiver}.
    4377             :   Node* length = effect = graph()->NewNode(
    4378        1944 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    4379        5832 :       effect, control);
    4380             :   Node* value = length;
    4381             : 
    4382             :   // Check if we have any {values} to push.
    4383        1944 :   if (num_values > 0) {
    4384             :     // Compute the resulting "length" of the {receiver}.
    4385             :     Node* new_length = value = graph()->NewNode(
    4386        5688 :         simplified()->NumberAdd(), length, jsgraph()->Constant(num_values));
    4387             : 
    4388             :     // Load the elements backing store of the {receiver}.
    4389             :     Node* elements = effect = graph()->NewNode(
    4390             :         simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
    4391        5688 :         effect, control);
    4392             :     Node* elements_length = effect = graph()->NewNode(
    4393             :         simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), elements,
    4394        5688 :         effect, control);
    4395             : 
    4396             :     GrowFastElementsMode mode =
    4397        1896 :         IsDoubleElementsKind(kind) ? GrowFastElementsMode::kDoubleElements
    4398        1896 :                                    : GrowFastElementsMode::kSmiOrObjectElements;
    4399             :     elements = effect = graph()->NewNode(
    4400        1896 :         simplified()->MaybeGrowFastElements(mode, p.feedback()), receiver,
    4401             :         elements,
    4402             :         graph()->NewNode(simplified()->NumberAdd(), length,
    4403        1896 :                          jsgraph()->Constant(num_values - 1)),
    4404        7584 :         elements_length, effect, control);
    4405             : 
    4406             :     // Update the JSArray::length field. Since this is observable,
    4407             :     // there must be no other check after this.
    4408             :     effect = graph()->NewNode(
    4409        1896 :         simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
    4410        5688 :         receiver, new_length, effect, control);
    4411             : 
    4412             :     // Append the {values} to the {elements}.
    4413        4219 :     for (int i = 0; i < num_values; ++i) {
    4414        4646 :       Node* value = values[i];
    4415             :       Node* index = graph()->NewNode(simplified()->NumberAdd(), length,
    4416        6969 :                                      jsgraph()->Constant(i));
    4417             :       effect = graph()->NewNode(
    4418        2323 :           simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(kind)),
    4419        6969 :           elements, index, value, effect, control);
    4420             :     }
    4421             :   }
    4422             : 
    4423        1944 :   ReplaceWithValue(node, value, effect, control);
    4424             :   return Replace(value);
    4425             : }
    4426             : 
    4427             : // ES6 section 22.1.3.17 Array.prototype.pop ( )
    4428        3210 : Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
    4429             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    4430         490 :   CallParameters const& p = CallParametersOf(node->op());
    4431         490 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    4432             :     return NoChange();
    4433             :   }
    4434             : 
    4435         478 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    4436         478 :   Node* effect = NodeProperties::GetEffectInput(node);
    4437         478 :   Node* control = NodeProperties::GetControlInput(node);
    4438             : 
    4439             :   ZoneHandleSet<Map> receiver_maps;
    4440             :   NodeProperties::InferReceiverMapsResult result =
    4441             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    4442         478 :                                         &receiver_maps);
    4443         478 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    4444             :   DCHECK_NE(0, receiver_maps.size());
    4445             : 
    4446             :   ElementsKind kind;
    4447         478 :   if (!CanInlineArrayResizingBuiltin(broker(), receiver_maps, &kind)) {
    4448             :     return NoChange();
    4449             :   }
    4450             : 
    4451             :   dependencies()->DependOnProtector(
    4452         294 :       PropertyCellRef(broker(), factory()->no_elements_protector()));
    4453             : 
    4454             :   // If the {receiver_maps} information is not reliable, we need
    4455             :   // to check that the {receiver} still has one of these maps.
    4456         294 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    4457             :     effect =
    4458             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    4459          85 :                                                  receiver_maps, p.feedback()),
    4460         170 :                          receiver, effect, control);
    4461             :   }
    4462             : 
    4463             :   // Load the "length" property of the {receiver}.
    4464             :   Node* length = effect = graph()->NewNode(
    4465         294 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    4466         882 :       effect, control);
    4467             : 
    4468             :   // Check if the {receiver} has any elements.
    4469             :   Node* check = graph()->NewNode(simplified()->NumberEqual(), length,
    4470         588 :                                  jsgraph()->ZeroConstant());
    4471             :   Node* branch =
    4472         294 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    4473             : 
    4474         294 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    4475             :   Node* etrue = effect;
    4476         294 :   Node* vtrue = jsgraph()->UndefinedConstant();
    4477             : 
    4478         294 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    4479             :   Node* efalse = effect;
    4480             :   Node* vfalse;
    4481             :   {
    4482             :     // TODO(tebbi): We should trim the backing store if the capacity is too
    4483             :     // big, as implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
    4484             : 
    4485             :     // Load the elements backing store from the {receiver}.
    4486             :     Node* elements = efalse = graph()->NewNode(
    4487             :         simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
    4488         882 :         efalse, if_false);
    4489             : 
    4490             :     // Ensure that we aren't popping from a copy-on-write backing store.
    4491         294 :     if (IsSmiOrObjectElementsKind(kind)) {
    4492             :       elements = efalse =
    4493             :           graph()->NewNode(simplified()->EnsureWritableFastElements(), receiver,
    4494         229 :                            elements, efalse, if_false);
    4495             :     }
    4496             : 
    4497             :     // Compute the new {length}.
    4498             :     length = graph()->NewNode(simplified()->NumberSubtract(), length,
    4499         588 :                               jsgraph()->OneConstant());
    4500             : 
    4501             :     // Store the new {length} to the {receiver}.
    4502             :     efalse = graph()->NewNode(
    4503         294 :         simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
    4504         882 :         receiver, length, efalse, if_false);
    4505             : 
    4506             :     // Load the last entry from the {elements}.
    4507             :     vfalse = efalse = graph()->NewNode(
    4508         294 :         simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(kind)),
    4509         882 :         elements, length, efalse, if_false);
    4510             : 
    4511             :     // Store a hole to the element we just removed from the {receiver}.
    4512             :     efalse = graph()->NewNode(
    4513             :         simplified()->StoreElement(
    4514         588 :             AccessBuilder::ForFixedArrayElement(GetHoleyElementsKind(kind))),
    4515        1176 :         elements, length, jsgraph()->TheHoleConstant(), efalse, if_false);
    4516             :   }
    4517             : 
    4518         294 :   control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    4519         294 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    4520             :   Node* value = graph()->NewNode(
    4521         294 :       common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control);
    4522             : 
    4523             :   // Convert the hole to undefined. Do this last, so that we can optimize
    4524             :   // conversion operator via some smart strength reduction in many cases.
    4525         588 :   if (IsHoleyElementsKind(kind)) {
    4526             :     value =
    4527          63 :         graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
    4528             :   }
    4529             : 
    4530         294 :   ReplaceWithValue(node, value, effect, control);
    4531             :   return Replace(value);
    4532             : }
    4533             : 
    4534             : // ES6 section 22.1.3.22 Array.prototype.shift ( )
    4535        5935 : Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
    4536             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    4537         481 :   CallParameters const& p = CallParametersOf(node->op());
    4538         481 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    4539             :     return NoChange();
    4540             :   }
    4541             : 
    4542         476 :   Node* target = NodeProperties::GetValueInput(node, 0);
    4543         476 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    4544         476 :   Node* context = NodeProperties::GetContextInput(node);
    4545         476 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    4546         476 :   Node* effect = NodeProperties::GetEffectInput(node);
    4547         476 :   Node* control = NodeProperties::GetControlInput(node);
    4548             : 
    4549             :   ZoneHandleSet<Map> receiver_maps;
    4550             :   NodeProperties::InferReceiverMapsResult result =
    4551             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    4552         476 :                                         &receiver_maps);
    4553         476 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    4554             :   DCHECK_NE(0, receiver_maps.size());
    4555             : 
    4556             :   ElementsKind kind;
    4557         460 :   if (!CanInlineArrayResizingBuiltin(broker(), receiver_maps, &kind)) {
    4558             :     return NoChange();
    4559             :   }
    4560             : 
    4561             :   dependencies()->DependOnProtector(
    4562         251 :       PropertyCellRef(broker(), factory()->no_elements_protector()));
    4563             : 
    4564             :   // If the {receiver_maps} information is not reliable, we need
    4565             :   // to check that the {receiver} still has one of these maps.
    4566         251 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    4567             :     effect =
    4568             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    4569          92 :                                                  receiver_maps, p.feedback()),
    4570         184 :                          receiver, effect, control);
    4571             :   }
    4572             : 
    4573             :   // Load length of the {receiver}.
    4574             :   Node* length = effect = graph()->NewNode(
    4575         251 :       simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
    4576         753 :       effect, control);
    4577             : 
    4578             :   // Return undefined if {receiver} has no elements.
    4579             :   Node* check0 = graph()->NewNode(simplified()->NumberEqual(), length,
    4580         502 :                                   jsgraph()->ZeroConstant());
    4581             :   Node* branch0 =
    4582         251 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
    4583             : 
    4584         251 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    4585             :   Node* etrue0 = effect;
    4586         251 :   Node* vtrue0 = jsgraph()->UndefinedConstant();
    4587             : 
    4588         251 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    4589             :   Node* efalse0 = effect;
    4590             :   Node* vfalse0;
    4591             :   {
    4592             :     // Check if we should take the fast-path.
    4593             :     Node* check1 =
    4594             :         graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
    4595         502 :                          jsgraph()->Constant(JSArray::kMaxCopyElements));
    4596             :     Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    4597         251 :                                      check1, if_false0);
    4598             : 
    4599         251 :     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    4600             :     Node* etrue1 = efalse0;
    4601             :     Node* vtrue1;
    4602             :     {
    4603             :       Node* elements = etrue1 = graph()->NewNode(
    4604             :           simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
    4605         753 :           receiver, etrue1, if_true1);
    4606             : 
    4607             :       // Load the first element here, which we return below.
    4608             :       vtrue1 = etrue1 = graph()->NewNode(
    4609         251 :           simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(kind)),
    4610        1004 :           elements, jsgraph()->ZeroConstant(), etrue1, if_true1);
    4611             : 
    4612             :       // Ensure that we aren't shifting a copy-on-write backing store.
    4613         251 :       if (IsSmiOrObjectElementsKind(kind)) {
    4614             :         elements = etrue1 =
    4615             :             graph()->NewNode(simplified()->EnsureWritableFastElements(),
    4616         204 :                              receiver, elements, etrue1, if_true1);
    4617             :       }
    4618             : 
    4619             :       // Shift the remaining {elements} by one towards the start.
    4620         251 :       Node* loop = graph()->NewNode(common()->Loop(2), if_true1, if_true1);
    4621             :       Node* eloop =
    4622         251 :           graph()->NewNode(common()->EffectPhi(2), etrue1, etrue1, loop);
    4623         251 :       Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
    4624         251 :       NodeProperties::MergeControlToEnd(graph(), common(), terminate);
    4625             :       Node* index = graph()->NewNode(
    4626             :           common()->Phi(MachineRepresentation::kTagged, 2),
    4627             :           jsgraph()->OneConstant(),
    4628         753 :           jsgraph()->Constant(JSArray::kMaxCopyElements - 1), loop);
    4629             : 
    4630             :       {
    4631             :         Node* check2 =
    4632         251 :             graph()->NewNode(simplified()->NumberLessThan(), index, length);
    4633         251 :         Node* branch2 = graph()->NewNode(common()->Branch(), check2, loop);
    4634             : 
    4635         251 :         if_true1 = graph()->NewNode(common()->IfFalse(), branch2);
    4636             :         etrue1 = eloop;
    4637             : 
    4638         251 :         Node* control = graph()->NewNode(common()->IfTrue(), branch2);
    4639             :         Node* effect = etrue1;
    4640             : 
    4641         251 :         ElementAccess const access = AccessBuilder::ForFixedArrayElement(kind);
    4642             :         Node* value = effect =
    4643             :             graph()->NewNode(simplified()->LoadElement(access), elements, index,
    4644         251 :                              effect, control);
    4645             :         effect =
    4646             :             graph()->NewNode(simplified()->StoreElement(access), elements,
    4647             :                              graph()->NewNode(simplified()->NumberSubtract(),
    4648             :                                               index, jsgraph()->OneConstant()),
    4649         753 :                              value, effect, control);
    4650             : 
    4651         251 :         loop->ReplaceInput(1, control);
    4652         251 :         eloop->ReplaceInput(1, effect);
    4653             :         index->ReplaceInput(1,
    4654             :                             graph()->NewNode(simplified()->NumberAdd(), index,
    4655         753 :                                              jsgraph()->OneConstant()));
    4656             :       }
    4657             : 
    4658             :       // Compute the new {length}.
    4659             :       length = graph()->NewNode(simplified()->NumberSubtract(), length,
    4660         502 :                                 jsgraph()->OneConstant());
    4661             : 
    4662             :       // Store the new {length} to the {receiver}.
    4663             :       etrue1 = graph()->NewNode(
    4664         251 :           simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
    4665         753 :           receiver, length, etrue1, if_true1);
    4666             : 
    4667             :       // Store a hole to the element we just removed from the {receiver}.
    4668             :       etrue1 = graph()->NewNode(
    4669             :           simplified()->StoreElement(
    4670         502 :               AccessBuilder::ForFixedArrayElement(GetHoleyElementsKind(kind))),
    4671        1004 :           elements, length, jsgraph()->TheHoleConstant(), etrue1, if_true1);
    4672             :     }
    4673             : 
    4674         251 :     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    4675             :     Node* efalse1 = efalse0;
    4676             :     Node* vfalse1;
    4677             :     {
    4678             :       // Call the generic C++ implementation.
    4679             :       const int builtin_index = Builtins::kArrayShift;
    4680             :       auto call_descriptor = Linkage::GetCEntryStubCallDescriptor(
    4681             :           graph()->zone(), 1, BuiltinArguments::kNumExtraArgsWithReceiver,
    4682             :           Builtins::name(builtin_index), node->op()->properties(),
    4683         502 :           CallDescriptor::kNeedsFrameState);
    4684             :       Node* stub_code =
    4685         251 :           jsgraph()->CEntryStubConstant(1, kDontSaveFPRegs, kArgvOnStack, true);
    4686         251 :       Address builtin_entry = Builtins::CppEntryOf(builtin_index);
    4687             :       Node* entry =
    4688         502 :           jsgraph()->ExternalConstant(ExternalReference::Create(builtin_entry));
    4689             :       Node* argc =
    4690         251 :           jsgraph()->Constant(BuiltinArguments::kNumExtraArgsWithReceiver);
    4691             :       if_false1 = efalse1 = vfalse1 =
    4692             :           graph()->NewNode(common()->Call(call_descriptor), stub_code, receiver,
    4693             :                            jsgraph()->PaddingConstant(), argc, target,
    4694             :                            jsgraph()->UndefinedConstant(), entry, argc, context,
    4695         502 :                            frame_state, efalse1, if_false1);
    4696             :     }
    4697             : 
    4698         251 :     if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
    4699             :     efalse0 =
    4700         251 :         graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
    4701             :     vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    4702         251 :                                vtrue1, vfalse1, if_false0);
    4703             :     }
    4704             : 
    4705         251 :     control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
    4706         251 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
    4707             :     Node* value =
    4708             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    4709         251 :                          vtrue0, vfalse0, control);
    4710             : 
    4711             :     // Convert the hole to undefined. Do this last, so that we can optimize
    4712             :     // conversion operator via some smart strength reduction in many cases.
    4713         502 :     if (IsHoleyElementsKind(kind)) {
    4714             :       value =
    4715          53 :           graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
    4716             :     }
    4717             : 
    4718         251 :     ReplaceWithValue(node, value, effect, control);
    4719             :     return Replace(value);
    4720             : }
    4721             : 
    4722             : // ES6 section 22.1.3.23 Array.prototype.slice ( )
    4723        2047 : Reduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) {
    4724         267 :   if (!FLAG_turbo_inline_array_builtins) return NoChange();
    4725             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    4726         267 :   CallParameters const& p = CallParametersOf(node->op());
    4727         267 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    4728             :     return NoChange();
    4729             :   }
    4730             : 
    4731         252 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    4732         252 :   Node* start = node->op()->ValueInputCount() > 2
    4733             :                     ? NodeProperties::GetValueInput(node, 2)
    4734         453 :                     : jsgraph()->ZeroConstant();
    4735         252 :   Node* end = node->op()->ValueInputCount() > 3
    4736             :                   ? NodeProperties::GetValueInput(node, 3)
    4737         486 :                   : jsgraph()->UndefinedConstant();
    4738         252 :   Node* context = NodeProperties::GetContextInput(node);
    4739         252 :   Node* effect = NodeProperties::GetEffectInput(node);
    4740         252 :   Node* control = NodeProperties::GetControlInput(node);
    4741             : 
    4742             :   // Optimize for the case where we simply clone the {receiver},
    4743             :   // i.e. when the {start} is zero and the {end} is undefined
    4744             :   // (meaning it will be set to {receiver}s "length" property).
    4745         713 :   if (!NumberMatcher(start).Is(0) ||
    4746         461 :       !HeapObjectMatcher(end).Is(factory()->undefined_value())) {
    4747             :     return NoChange();
    4748             :   }
    4749             : 
    4750             :   // Try to determine the {receiver} maps.
    4751             :   ZoneHandleSet<Map> receiver_maps;
    4752             :   NodeProperties::InferReceiverMapsResult result =
    4753             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    4754         209 :                                         &receiver_maps);
    4755         209 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    4756             : 
    4757             :   // We cannot optimize unless the Array[@@species] lookup chain is intact.
    4758         209 :   if (!isolate()->IsArraySpeciesLookupChainIntact()) return NoChange();
    4759             : 
    4760             :   // Check that the maps are of JSArray (and more).
    4761             :   // TODO(turbofan): Consider adding special case for the common pattern
    4762             :   // `slice.call(arguments)`, for example jQuery makes heavy use of that.
    4763             :   bool can_be_holey = false;
    4764         197 :   for (Handle<Map> map : receiver_maps) {
    4765             :     MapRef receiver_map(broker(), map);
    4766         118 :     if (!receiver_map.supports_fast_array_iteration()) return NoChange();
    4767             : 
    4768         230 :     if (IsHoleyElementsKind(receiver_map.elements_kind())) {
    4769             :       can_be_holey = true;
    4770             :     }
    4771             :   }
    4772             : 
    4773             :   // Install code dependency on the Array[@@species] protector.
    4774             :   dependencies()->DependOnProtector(
    4775          79 :       PropertyCellRef(broker(), factory()->array_species_protector()));
    4776             : 
    4777             :   // Install code dependency on the array protector for holey arrays.
    4778          79 :   if (can_be_holey) {
    4779             :     dependencies()->DependOnProtector(
    4780           5 :         PropertyCellRef(broker(), factory()->no_elements_protector()));
    4781             :   }
    4782             : 
    4783             :   // If we have unreliable maps, we need a map check, as there might be
    4784             :   // side-effects caused by the evaluation of the {node}s parameters.
    4785          79 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    4786             :     effect =
    4787             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    4788           0 :                                                  receiver_maps, p.feedback()),
    4789           0 :                          receiver, effect, control);
    4790             :   }
    4791             : 
    4792             :   // TODO(turbofan): We can do even better here, either adding a CloneArray
    4793             :   // simplified operator, whose output type indicates that it's an Array,
    4794             :   // saving subsequent checks, or yet better, by introducing new operators
    4795             :   // CopySmiOrObjectElements / CopyDoubleElements and inlining the JSArray
    4796             :   // allocation in here. That way we'd even get escape analysis and scalar
    4797             :   // replacement to help in some cases.
    4798             :   Callable callable =
    4799          79 :       Builtins::CallableFor(isolate(), Builtins::kCloneFastJSArray);
    4800             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    4801             :       graph()->zone(), callable.descriptor(),
    4802             :       callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
    4803         158 :       Operator::kNoThrow | Operator::kNoDeopt);
    4804             : 
    4805             :   // Calls to Builtins::kCloneFastJSArray produce COW arrays
    4806             :   // if the original array is COW
    4807             :   Node* clone = effect = graph()->NewNode(
    4808             :       common()->Call(call_descriptor), jsgraph()->HeapConstant(callable.code()),
    4809         237 :       receiver, context, effect, control);
    4810             : 
    4811          79 :   ReplaceWithValue(node, clone, effect, control);
    4812             :   return Replace(clone);
    4813             : }
    4814             : 
    4815             : // ES6 section 22.1.2.2 Array.isArray ( arg )
    4816          59 : Reduction JSCallReducer::ReduceArrayIsArray(Node* node) {
    4817             :   // We certainly know that undefined is not an array.
    4818         118 :   if (node->op()->ValueInputCount() < 3) {
    4819           0 :     Node* value = jsgraph()->FalseConstant();
    4820           0 :     ReplaceWithValue(node, value);
    4821             :     return Replace(value);
    4822             :   }
    4823             : 
    4824          59 :   Node* effect = NodeProperties::GetEffectInput(node);
    4825          59 :   Node* control = NodeProperties::GetControlInput(node);
    4826          59 :   Node* context = NodeProperties::GetContextInput(node);
    4827          59 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    4828          59 :   Node* object = NodeProperties::GetValueInput(node, 2);
    4829          59 :   node->ReplaceInput(0, object);
    4830          59 :   node->ReplaceInput(1, context);
    4831          59 :   node->ReplaceInput(2, frame_state);
    4832          59 :   node->ReplaceInput(3, effect);
    4833          59 :   node->ReplaceInput(4, control);
    4834          59 :   node->TrimInputCount(5);
    4835          59 :   NodeProperties::ChangeOp(node, javascript()->ObjectIsArray());
    4836             :   return Changed(node);
    4837             : }
    4838             : 
    4839        4001 : Reduction JSCallReducer::ReduceArrayIterator(Node* node, IterationKind kind) {
    4840             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    4841        1333 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    4842        1333 :   Node* context = NodeProperties::GetContextInput(node);
    4843        1333 :   Node* effect = NodeProperties::GetEffectInput(node);
    4844        1334 :   Node* control = NodeProperties::GetControlInput(node);
    4845             : 
    4846             :   // Check if we know that {receiver} is a valid JSReceiver.
    4847             :   ZoneHandleSet<Map> receiver_maps;
    4848             :   NodeProperties::InferReceiverMapsResult result =
    4849             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    4850        1334 :                                         &receiver_maps);
    4851        1333 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    4852             :   DCHECK_NE(0, receiver_maps.size());
    4853        2668 :   for (Handle<Map> map : receiver_maps) {
    4854             :     MapRef receiver_map(broker(), map);
    4855        1335 :     if (!receiver_map.IsJSReceiverMap()) return NoChange();
    4856             :   }
    4857             : 
    4858             :   // Morph the {node} into a JSCreateArrayIterator with the given {kind}.
    4859             :   RelaxControls(node);
    4860        1334 :   node->ReplaceInput(0, receiver);
    4861        1334 :   node->ReplaceInput(1, context);
    4862        1334 :   node->ReplaceInput(2, effect);
    4863        1334 :   node->ReplaceInput(3, control);
    4864        1334 :   node->TrimInputCount(4);
    4865        1333 :   NodeProperties::ChangeOp(node, javascript()->CreateArrayIterator(kind));
    4866             :   return Changed(node);
    4867             : }
    4868             : 
    4869             : namespace {
    4870             : 
    4871        1304 : bool InferIteratedObjectMaps(JSHeapBroker* broker, Node* iterator,
    4872             :                              ZoneHandleSet<Map>* iterated_object_maps) {
    4873             :   DCHECK_EQ(IrOpcode::kJSCreateArrayIterator, iterator->opcode());
    4874        1304 :   Node* iterated_object = NodeProperties::GetValueInput(iterator, 0);
    4875        1305 :   Node* effect = NodeProperties::GetEffectInput(iterator);
    4876             : 
    4877             :   NodeProperties::InferReceiverMapsResult result =
    4878             :       NodeProperties::InferReceiverMaps(broker, iterated_object, effect,
    4879        1305 :                                         iterated_object_maps);
    4880        1304 :   return result != NodeProperties::kNoReceiverMaps;
    4881             : }
    4882             : 
    4883             : }  // namespace
    4884             : 
    4885             : // ES #sec-%arrayiteratorprototype%.next
    4886       10575 : Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
    4887             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    4888        2955 :   CallParameters const& p = CallParametersOf(node->op());
    4889        2948 :   Node* iterator = NodeProperties::GetValueInput(node, 1);
    4890        1478 :   Node* context = NodeProperties::GetContextInput(node);
    4891        1477 :   Node* effect = NodeProperties::GetEffectInput(node);
    4892        1477 :   Node* control = NodeProperties::GetControlInput(node);
    4893             : 
    4894        1478 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    4895             :     return NoChange();
    4896             :   }
    4897             : 
    4898             :   // Check if the {iterator} is a JSCreateArrayIterator.
    4899        1470 :   if (iterator->opcode() != IrOpcode::kJSCreateArrayIterator) return NoChange();
    4900             :   IterationKind const iteration_kind =
    4901        1305 :       CreateArrayIteratorParametersOf(iterator->op()).kind();
    4902             : 
    4903             :   // Try to infer the [[IteratedObject]] maps from the {iterator}.
    4904             :   ZoneHandleSet<Map> iterated_object_maps;
    4905        1305 :   if (!InferIteratedObjectMaps(broker(), iterator, &iterated_object_maps)) {
    4906             :     return NoChange();
    4907             :   }
    4908             :   DCHECK_NE(0, iterated_object_maps.size());
    4909             : 
    4910             :   // Check that various {iterated_object_maps} have compatible elements kinds.
    4911             :   ElementsKind elements_kind =
    4912        1305 :       MapRef(broker(), iterated_object_maps[0]).elements_kind();
    4913        1304 :   if (IsFixedTypedArrayElementsKind(elements_kind)) {
    4914             :     // TurboFan doesn't support loading from BigInt typed arrays yet.
    4915          65 :     if (elements_kind == BIGUINT64_ELEMENTS ||
    4916             :         elements_kind == BIGINT64_ELEMENTS) {
    4917             :       return NoChange();
    4918             :     }
    4919         114 :     for (Handle<Map> map : iterated_object_maps) {
    4920             :       MapRef iterated_object_map(broker(), map);
    4921          57 :       if (iterated_object_map.elements_kind() != elements_kind) {
    4922           0 :         return NoChange();
    4923             :       }
    4924             :     }
    4925             :   } else {
    4926        1240 :     if (!CanInlineArrayIteratingBuiltin(broker(), iterated_object_maps,
    4927        1239 :                                         &elements_kind)) {
    4928             :       return NoChange();
    4929             :     }
    4930             :   }
    4931             : 
    4932             :   // Install code dependency on the array protector for holey arrays.
    4933        2034 :   if (IsHoleyElementsKind(elements_kind)) {
    4934             :     dependencies()->DependOnProtector(
    4935          25 :         PropertyCellRef(broker(), factory()->no_elements_protector()));
    4936             :   }
    4937             : 
    4938             :   // Load the (current) {iterated_object} from the {iterator}.
    4939             :   Node* iterated_object = effect =
    4940             :       graph()->NewNode(simplified()->LoadField(
    4941             :                            AccessBuilder::ForJSArrayIteratorIteratedObject()),
    4942        3051 :                        iterator, effect, control);
    4943             : 
    4944             :   // Ensure that the {iterated_object} map didn't change.
    4945             :   effect = graph()->NewNode(
    4946             :       simplified()->CheckMaps(CheckMapsFlag::kNone, iterated_object_maps,
    4947        1017 :                               p.feedback()),
    4948        2034 :       iterated_object, effect, control);
    4949             : 
    4950        2034 :   if (IsFixedTypedArrayElementsKind(elements_kind)) {
    4951             :     // See if we can skip the detaching check.
    4952          57 :     if (isolate()->IsArrayBufferDetachingIntact()) {
    4953             :       // Add a code dependency so we are deoptimized in case an ArrayBuffer
    4954             :       // gets detached.
    4955             :       dependencies()->DependOnProtector(PropertyCellRef(
    4956          18 :           broker(), factory()->array_buffer_detaching_protector()));
    4957             :     } else {
    4958             :       // Bail out if the {iterated_object}s JSArrayBuffer was detached.
    4959             :       Node* buffer = effect = graph()->NewNode(
    4960             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
    4961         117 :           iterated_object, effect, control);
    4962             :       Node* buffer_bit_field = effect = graph()->NewNode(
    4963             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
    4964         117 :           buffer, effect, control);
    4965             :       Node* check = graph()->NewNode(
    4966             :           simplified()->NumberEqual(),
    4967             :           graph()->NewNode(
    4968             :               simplified()->NumberBitwiseAnd(), buffer_bit_field,
    4969             :               jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
    4970         156 :           jsgraph()->ZeroConstant());
    4971             :       effect = graph()->NewNode(
    4972             :           simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached,
    4973             :                                 p.feedback()),
    4974          39 :           check, effect, control);
    4975             :     }
    4976             :   }
    4977             : 
    4978             :   // Load the [[NextIndex]] from the {iterator} and leverage the fact
    4979             :   // that we definitely know that it's in Unsigned32 range since the
    4980             :   // {iterated_object} is either a JSArray or a JSTypedArray. For the
    4981             :   // latter case we even know that it's a Smi in UnsignedSmall range.
    4982        1017 :   FieldAccess index_access = AccessBuilder::ForJSArrayIteratorNextIndex();
    4983        2032 :   if (IsFixedTypedArrayElementsKind(elements_kind)) {
    4984          57 :     index_access.type = TypeCache::Get()->kJSTypedArrayLengthType;
    4985          57 :     index_access.machine_type = MachineType::TaggedSigned();
    4986          57 :     index_access.write_barrier_kind = kNoWriteBarrier;
    4987             :   } else {
    4988         959 :     index_access.type = TypeCache::Get()->kJSArrayLengthType;
    4989             :   }
    4990             :   Node* index = effect = graph()->NewNode(simplified()->LoadField(index_access),
    4991        1017 :                                           iterator, effect, control);
    4992             : 
    4993             :   // Load the elements of the {iterated_object}. While it feels
    4994             :   // counter-intuitive to place the elements pointer load before
    4995             :   // the condition below, as it might not be needed (if the {index}
    4996             :   // is out of bounds for the {iterated_object}), it's better this
    4997             :   // way as it allows the LoadElimination to eliminate redundant
    4998             :   // reloads of the elements pointer.
    4999             :   Node* elements = effect = graph()->NewNode(
    5000             :       simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
    5001        3050 :       iterated_object, effect, control);
    5002             : 
    5003             :   // Load the length of the {iterated_object}. Due to the map checks we
    5004             :   // already know something about the length here, which we can leverage
    5005             :   // to generate Word32 operations below without additional checking.
    5006             :   FieldAccess length_access =
    5007        1017 :       IsFixedTypedArrayElementsKind(elements_kind)
    5008             :           ? AccessBuilder::ForJSTypedArrayLength()
    5009        1017 :           : AccessBuilder::ForJSArrayLength(elements_kind);
    5010             :   Node* length = effect = graph()->NewNode(
    5011        1016 :       simplified()->LoadField(length_access), iterated_object, effect, control);
    5012             : 
    5013             :   // Check whether {index} is within the valid range for the {iterated_object}.
    5014        1017 :   Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, length);
    5015             :   Node* branch =
    5016        1017 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    5017             : 
    5018             :   Node* done_true;
    5019             :   Node* value_true;
    5020             :   Node* etrue = effect;
    5021        1017 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    5022             :   {
    5023             :     // We know that the {index} is range of the {length} now.
    5024             :     index = etrue = graph()->NewNode(
    5025             :         common()->TypeGuard(
    5026        1017 :             Type::Range(0.0, length_access.type.Max() - 1.0, graph()->zone())),
    5027        3049 :         index, etrue, if_true);
    5028             : 
    5029        1017 :     done_true = jsgraph()->FalseConstant();
    5030        1017 :     if (iteration_kind == IterationKind::kKeys) {
    5031             :       // Just return the {index}.
    5032             :       value_true = index;
    5033             :     } else {
    5034             :       DCHECK(iteration_kind == IterationKind::kEntries ||
    5035             :              iteration_kind == IterationKind::kValues);
    5036             : 
    5037        2020 :       if (IsFixedTypedArrayElementsKind(elements_kind)) {
    5038             :         Node* base_ptr = etrue = graph()->NewNode(
    5039             :             simplified()->LoadField(
    5040             :                 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
    5041         171 :             elements, etrue, if_true);
    5042             :         Node* external_ptr = etrue = graph()->NewNode(
    5043             :             simplified()->LoadField(
    5044             :                 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
    5045         171 :             elements, etrue, if_true);
    5046             : 
    5047          57 :         ExternalArrayType array_type = kExternalInt8Array;
    5048          57 :         switch (elements_kind) {
    5049             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
    5050             :   case TYPE##_ELEMENTS:                           \
    5051             :     array_type = kExternal##Type##Array;          \
    5052             :     break;
    5053          25 :           TYPED_ARRAYS(TYPED_ARRAY_CASE)
    5054             :           default:
    5055           0 :             UNREACHABLE();
    5056             : #undef TYPED_ARRAY_CASE
    5057             :         }
    5058             : 
    5059             :         Node* buffer = etrue =
    5060             :             graph()->NewNode(simplified()->LoadField(
    5061             :                                  AccessBuilder::ForJSArrayBufferViewBuffer()),
    5062         171 :                              iterated_object, etrue, if_true);
    5063             : 
    5064             :         value_true = etrue =
    5065             :             graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
    5066          57 :                              base_ptr, external_ptr, index, etrue, if_true);
    5067             :       } else {
    5068             :         value_true = etrue = graph()->NewNode(
    5069             :             simplified()->LoadElement(
    5070         953 :                 AccessBuilder::ForFixedArrayElement(elements_kind)),
    5071        2858 :             elements, index, etrue, if_true);
    5072             : 
    5073             :         // Convert hole to undefined if needed.
    5074         953 :         if (elements_kind == HOLEY_ELEMENTS ||
    5075             :             elements_kind == HOLEY_SMI_ELEMENTS) {
    5076             :           value_true = graph()->NewNode(
    5077          25 :               simplified()->ConvertTaggedHoleToUndefined(), value_true);
    5078         928 :         } else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
    5079             :           // TODO(6587): avoid deopt if not all uses of value are truncated.
    5080             :           CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
    5081             :           value_true = etrue = graph()->NewNode(
    5082             :               simplified()->CheckFloat64Hole(mode, p.feedback()), value_true,
    5083           0 :               etrue, if_true);
    5084             :         }
    5085             :       }
    5086             : 
    5087        1010 :       if (iteration_kind == IterationKind::kEntries) {
    5088             :         // Allocate elements for key/value pair
    5089             :         value_true = etrue =
    5090             :             graph()->NewNode(javascript()->CreateKeyValueArray(), index,
    5091          14 :                              value_true, context, etrue);
    5092             :       } else {
    5093             :         DCHECK_EQ(IterationKind::kValues, iteration_kind);
    5094             :       }
    5095             :     }
    5096             : 
    5097             :     // Increment the [[NextIndex]] field in the {iterator}. The TypeGuards
    5098             :     // above guarantee that the {next_index} is in the UnsignedSmall range.
    5099             :     Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
    5100        2034 :                                         jsgraph()->OneConstant());
    5101             :     etrue = graph()->NewNode(simplified()->StoreField(index_access), iterator,
    5102        1017 :                              next_index, etrue, if_true);
    5103             :   }
    5104             : 
    5105             :   Node* done_false;
    5106             :   Node* value_false;
    5107             :   Node* efalse = effect;
    5108        1017 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    5109             :   {
    5110             :     // iterator.[[NextIndex]] >= array.length, stop iterating.
    5111        1017 :     done_false = jsgraph()->TrueConstant();
    5112        1017 :     value_false = jsgraph()->UndefinedConstant();
    5113             : 
    5114        2034 :     if (!IsFixedTypedArrayElementsKind(elements_kind)) {
    5115             :       // Mark the {iterator} as exhausted by setting the [[NextIndex]] to a
    5116             :       // value that will never pass the length check again (aka the maximum
    5117             :       // value possible for the specific iterated object). Note that this is
    5118             :       // different from what the specification says, which is changing the
    5119             :       // [[IteratedObject]] field to undefined, but that makes it difficult
    5120             :       // to eliminate the map checks and "length" accesses in for..of loops.
    5121             :       //
    5122             :       // This is not necessary for JSTypedArray's, since the length of those
    5123             :       // cannot change later and so if we were ever out of bounds for them
    5124             :       // we will stay out-of-bounds forever.
    5125        1920 :       Node* end_index = jsgraph()->Constant(index_access.type.Max());
    5126             :       efalse = graph()->NewNode(simplified()->StoreField(index_access),
    5127         960 :                                 iterator, end_index, efalse, if_false);
    5128             :     }
    5129             :   }
    5130             : 
    5131        1017 :   control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    5132        1017 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    5133             :   Node* value =
    5134             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    5135        1017 :                        value_true, value_false, control);
    5136             :   Node* done =
    5137             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    5138        1017 :                        done_true, done_false, control);
    5139             : 
    5140             :   // Create IteratorResult object.
    5141             :   value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
    5142        1017 :                                     value, done, context, effect);
    5143        1017 :   ReplaceWithValue(node, value, effect, control);
    5144             :   return Replace(value);
    5145             : }
    5146             : 
    5147             : // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
    5148             : // ES6 section 21.1.3.3 String.prototype.codePointAt ( pos )
    5149        2379 : Reduction JSCallReducer::ReduceStringPrototypeStringAt(
    5150        4238 :     const Operator* string_access_operator, Node* node) {
    5151             :   DCHECK(string_access_operator->opcode() == IrOpcode::kStringCharCodeAt ||
    5152             :          string_access_operator->opcode() == IrOpcode::kStringCodePointAt);
    5153             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5154        2379 :   CallParameters const& p = CallParametersOf(node->op());
    5155        2379 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5156             :     return NoChange();
    5157             :   }
    5158             : 
    5159        1795 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    5160        1795 :   Node* index = node->op()->ValueInputCount() >= 3
    5161             :                     ? NodeProperties::GetValueInput(node, 2)
    5162        1859 :                     : jsgraph()->ZeroConstant();
    5163        1795 :   Node* effect = NodeProperties::GetEffectInput(node);
    5164        1795 :   Node* control = NodeProperties::GetControlInput(node);
    5165             : 
    5166             :   // Ensure that the {receiver} is actually a String.
    5167        1795 :   receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
    5168        1795 :                                        receiver, effect, control);
    5169             : 
    5170             :   // Determine the {receiver} length.
    5171             :   Node* receiver_length =
    5172        1795 :       graph()->NewNode(simplified()->StringLength(), receiver);
    5173             : 
    5174             :   // Check that the {index} is within range.
    5175             :   index = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
    5176        1795 :                                     index, receiver_length, effect, control);
    5177             : 
    5178             :   // Return the character from the {receiver} as single character string.
    5179        1795 :   Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
    5180             :   Node* value = effect = graph()->NewNode(string_access_operator, receiver,
    5181             :                                           masked_index, effect, control);
    5182             : 
    5183        1795 :   ReplaceWithValue(node, value, effect, control);
    5184             :   return Replace(value);
    5185             : }
    5186             : 
    5187             : // ES section 21.1.3.1 String.prototype.charAt ( pos )
    5188        1265 : Reduction JSCallReducer::ReduceStringPrototypeCharAt(Node* node) {
    5189             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5190         719 :   CallParameters const& p = CallParametersOf(node->op());
    5191         719 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5192             :     return NoChange();
    5193             :   }
    5194             : 
    5195         513 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    5196         513 :   Node* index = node->op()->ValueInputCount() >= 3
    5197             :                     ? NodeProperties::GetValueInput(node, 2)
    5198         546 :                     : jsgraph()->ZeroConstant();
    5199         513 :   Node* effect = NodeProperties::GetEffectInput(node);
    5200         513 :   Node* control = NodeProperties::GetControlInput(node);
    5201             : 
    5202             :   // Ensure that the {receiver} is actually a String.
    5203         513 :   receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
    5204         513 :                                        receiver, effect, control);
    5205             : 
    5206             :   // Determine the {receiver} length.
    5207             :   Node* receiver_length =
    5208         513 :       graph()->NewNode(simplified()->StringLength(), receiver);
    5209             : 
    5210             :   // Check that the {index} is within range.
    5211             :   index = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
    5212         513 :                                     index, receiver_length, effect, control);
    5213             : 
    5214             :   // Return the character from the {receiver} as single character string.
    5215         513 :   Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
    5216             :   Node* value = effect =
    5217             :       graph()->NewNode(simplified()->StringCharCodeAt(), receiver, masked_index,
    5218         513 :                        effect, control);
    5219         513 :   value = graph()->NewNode(simplified()->StringFromSingleCharCode(), value);
    5220             : 
    5221         513 :   ReplaceWithValue(node, value, effect, control);
    5222             :   return Replace(value);
    5223             : }
    5224             : 
    5225             : #ifdef V8_INTL_SUPPORT
    5226             : 
    5227          95 : Reduction JSCallReducer::ReduceStringPrototypeToLowerCaseIntl(Node* node) {
    5228             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5229          95 :   CallParameters const& p = CallParametersOf(node->op());
    5230          95 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5231             :     return NoChange();
    5232             :   }
    5233          95 :   Node* effect = NodeProperties::GetEffectInput(node);
    5234          95 :   Node* control = NodeProperties::GetControlInput(node);
    5235             : 
    5236             :   Node* receiver = effect =
    5237          95 :       graph()->NewNode(simplified()->CheckString(p.feedback()),
    5238         190 :                        NodeProperties::GetValueInput(node, 1), effect, control);
    5239             : 
    5240          95 :   NodeProperties::ReplaceEffectInput(node, effect);
    5241             :   RelaxEffectsAndControls(node);
    5242          95 :   node->ReplaceInput(0, receiver);
    5243          95 :   node->TrimInputCount(1);
    5244          95 :   NodeProperties::ChangeOp(node, simplified()->StringToLowerCaseIntl());
    5245             :   NodeProperties::SetType(node, Type::String());
    5246             :   return Changed(node);
    5247             : }
    5248             : 
    5249          35 : Reduction JSCallReducer::ReduceStringPrototypeToUpperCaseIntl(Node* node) {
    5250             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5251          35 :   CallParameters const& p = CallParametersOf(node->op());
    5252          35 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5253             :     return NoChange();
    5254             :   }
    5255          35 :   Node* effect = NodeProperties::GetEffectInput(node);
    5256          35 :   Node* control = NodeProperties::GetControlInput(node);
    5257             : 
    5258             :   Node* receiver = effect =
    5259          35 :       graph()->NewNode(simplified()->CheckString(p.feedback()),
    5260          70 :                        NodeProperties::GetValueInput(node, 1), effect, control);
    5261             : 
    5262          35 :   NodeProperties::ReplaceEffectInput(node, effect);
    5263             :   RelaxEffectsAndControls(node);
    5264          35 :   node->ReplaceInput(0, receiver);
    5265          35 :   node->TrimInputCount(1);
    5266          35 :   NodeProperties::ChangeOp(node, simplified()->StringToUpperCaseIntl());
    5267             :   NodeProperties::SetType(node, Type::String());
    5268             :   return Changed(node);
    5269             : }
    5270             : 
    5271             : #endif  // V8_INTL_SUPPORT
    5272             : 
    5273             : // ES #sec-string.fromcharcode
    5274         457 : Reduction JSCallReducer::ReduceStringFromCharCode(Node* node) {
    5275             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5276         231 :   CallParameters const& p = CallParametersOf(node->op());
    5277         231 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5278             :     return NoChange();
    5279             :   }
    5280         226 :   if (node->op()->ValueInputCount() == 3) {
    5281         224 :     Node* effect = NodeProperties::GetEffectInput(node);
    5282         224 :     Node* control = NodeProperties::GetControlInput(node);
    5283         224 :     Node* input = NodeProperties::GetValueInput(node, 2);
    5284             : 
    5285             :     input = effect = graph()->NewNode(
    5286             :         simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
    5287         224 :                                           p.feedback()),
    5288         224 :         input, effect, control);
    5289             : 
    5290             :     Node* value =
    5291         224 :         graph()->NewNode(simplified()->StringFromSingleCharCode(), input);
    5292         224 :     ReplaceWithValue(node, value, effect);
    5293             :     return Replace(value);
    5294             :   }
    5295             :   return NoChange();
    5296             : }
    5297             : 
    5298             : // ES #sec-string.fromcodepoint
    5299         642 : Reduction JSCallReducer::ReduceStringFromCodePoint(Node* node) {
    5300             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5301         268 :   CallParameters const& p = CallParametersOf(node->op());
    5302         268 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5303             :     return NoChange();
    5304             :   }
    5305         227 :   if (node->op()->ValueInputCount() == 3) {
    5306         147 :     Node* effect = NodeProperties::GetEffectInput(node);
    5307         147 :     Node* control = NodeProperties::GetControlInput(node);
    5308         147 :     Node* input = NodeProperties::GetValueInput(node, 2);
    5309             : 
    5310             :     input = effect =
    5311         147 :         graph()->NewNode(simplified()->CheckBounds(p.feedback()), input,
    5312         294 :                          jsgraph()->Constant(0x10FFFF + 1), effect, control);
    5313             : 
    5314             :     Node* value = graph()->NewNode(
    5315         147 :         simplified()->StringFromSingleCodePoint(UnicodeEncoding::UTF32), input);
    5316         147 :     ReplaceWithValue(node, value, effect);
    5317             :     return Replace(value);
    5318             :   }
    5319             :   return NoChange();
    5320             : }
    5321             : 
    5322         134 : Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) {
    5323          67 :   CallParameters const& p = CallParametersOf(node->op());
    5324          67 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5325             :     return NoChange();
    5326             :   }
    5327          67 :   Node* effect = NodeProperties::GetEffectInput(node);
    5328          67 :   Node* control = NodeProperties::GetControlInput(node);
    5329             :   Node* receiver = effect =
    5330          67 :       graph()->NewNode(simplified()->CheckString(p.feedback()),
    5331         134 :                        NodeProperties::GetValueInput(node, 1), effect, control);
    5332             :   Node* iterator = effect =
    5333             :       graph()->NewNode(javascript()->CreateStringIterator(), receiver,
    5334          67 :                        jsgraph()->NoContextConstant(), effect);
    5335          67 :   ReplaceWithValue(node, iterator, effect, control);
    5336             :   return Replace(iterator);
    5337             : }
    5338             : 
    5339         475 : Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) {
    5340          95 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    5341          95 :   Node* effect = NodeProperties::GetEffectInput(node);
    5342          95 :   Node* control = NodeProperties::GetControlInput(node);
    5343          95 :   Node* context = NodeProperties::GetContextInput(node);
    5344          95 :   if (NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
    5345             :                                              JS_STRING_ITERATOR_TYPE)) {
    5346             :     Node* string = effect = graph()->NewNode(
    5347             :         simplified()->LoadField(AccessBuilder::ForJSStringIteratorString()),
    5348         285 :         receiver, effect, control);
    5349             :     Node* index = effect = graph()->NewNode(
    5350             :         simplified()->LoadField(AccessBuilder::ForJSStringIteratorIndex()),
    5351         285 :         receiver, effect, control);
    5352          95 :     Node* length = graph()->NewNode(simplified()->StringLength(), string);
    5353             : 
    5354             :     // branch0: if (index < length)
    5355             :     Node* check0 =
    5356          95 :         graph()->NewNode(simplified()->NumberLessThan(), index, length);
    5357             :     Node* branch0 =
    5358          95 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
    5359             : 
    5360             :     Node* etrue0 = effect;
    5361          95 :     Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    5362             :     Node* done_true;
    5363             :     Node* vtrue0;
    5364             :     {
    5365          95 :       done_true = jsgraph()->FalseConstant();
    5366             :       Node* codepoint = etrue0 = graph()->NewNode(
    5367             :           simplified()->StringCodePointAt(UnicodeEncoding::UTF16), string,
    5368          95 :           index, etrue0, if_true0);
    5369             :       vtrue0 = graph()->NewNode(
    5370             :           simplified()->StringFromSingleCodePoint(UnicodeEncoding::UTF16),
    5371          95 :           codepoint);
    5372             : 
    5373             :       // Update iterator.[[NextIndex]]
    5374             :       Node* char_length =
    5375          95 :           graph()->NewNode(simplified()->StringLength(), vtrue0);
    5376          95 :       index = graph()->NewNode(simplified()->NumberAdd(), index, char_length);
    5377             :       etrue0 = graph()->NewNode(
    5378             :           simplified()->StoreField(AccessBuilder::ForJSStringIteratorIndex()),
    5379         285 :           receiver, index, etrue0, if_true0);
    5380             :     }
    5381             : 
    5382          95 :     Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    5383             :     Node* done_false;
    5384             :     Node* vfalse0;
    5385             :     {
    5386          95 :       vfalse0 = jsgraph()->UndefinedConstant();
    5387          95 :       done_false = jsgraph()->TrueConstant();
    5388             :     }
    5389             : 
    5390          95 :     control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
    5391          95 :     effect = graph()->NewNode(common()->EffectPhi(2), etrue0, effect, control);
    5392             :     Node* value =
    5393             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    5394          95 :                          vtrue0, vfalse0, control);
    5395             :     Node* done =
    5396             :         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    5397          95 :                          done_true, done_false, control);
    5398             : 
    5399             :     value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
    5400          95 :                                       value, done, context, effect);
    5401             : 
    5402          95 :     ReplaceWithValue(node, value, effect, control);
    5403             :     return Replace(value);
    5404             :   }
    5405             :   return NoChange();
    5406             : }
    5407             : 
    5408             : // ES #sec-string.prototype.concat
    5409         146 : Reduction JSCallReducer::ReduceStringPrototypeConcat(Node* node) {
    5410         134 :   if (node->op()->ValueInputCount() < 2 || node->op()->ValueInputCount() > 3) {
    5411             :     return NoChange();
    5412             :   }
    5413          43 :   CallParameters const& p = CallParametersOf(node->op());
    5414          43 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5415             :     return NoChange();
    5416             :   }
    5417             : 
    5418          43 :   Node* effect = NodeProperties::GetEffectInput(node);
    5419          43 :   Node* control = NodeProperties::GetControlInput(node);
    5420             :   Node* receiver = effect =
    5421          43 :       graph()->NewNode(simplified()->CheckString(p.feedback()),
    5422          86 :                        NodeProperties::GetValueInput(node, 1), effect, control);
    5423             : 
    5424          86 :   if (node->op()->ValueInputCount() < 3) {
    5425          43 :     ReplaceWithValue(node, receiver, effect, control);
    5426             :     return Replace(receiver);
    5427             :   }
    5428             : 
    5429             :   Node* argument = effect =
    5430             :       graph()->NewNode(simplified()->CheckString(p.feedback()),
    5431          72 :                        NodeProperties::GetValueInput(node, 2), effect, control);
    5432             :   Node* receiver_length =
    5433          36 :       graph()->NewNode(simplified()->StringLength(), receiver);
    5434             :   Node* argument_length =
    5435          36 :       graph()->NewNode(simplified()->StringLength(), argument);
    5436             :   Node* length = graph()->NewNode(simplified()->NumberAdd(), receiver_length,
    5437          36 :                                   argument_length);
    5438             :   length = effect = graph()->NewNode(
    5439             :       simplified()->CheckBounds(p.feedback()), length,
    5440          72 :       jsgraph()->Constant(String::kMaxLength + 1), effect, control);
    5441             : 
    5442             :   Node* value = graph()->NewNode(simplified()->StringConcat(), length, receiver,
    5443          36 :                                  argument);
    5444             : 
    5445             :   ReplaceWithValue(node, value, effect, control);
    5446             :   return Replace(value);
    5447             : }
    5448             : 
    5449         599 : Node* JSCallReducer::CreateArtificialFrameState(
    5450             :     Node* node, Node* outer_frame_state, int parameter_count,
    5451             :     BailoutId bailout_id, FrameStateType frame_state_type,
    5452           0 :     const SharedFunctionInfoRef& shared, Node* context) {
    5453             :   const FrameStateFunctionInfo* state_info =
    5454             :       common()->CreateFrameStateFunctionInfo(
    5455        1198 :           frame_state_type, parameter_count + 1, 0, shared.object());
    5456             : 
    5457             :   const Operator* op = common()->FrameState(
    5458         599 :       bailout_id, OutputFrameStateCombine::Ignore(), state_info);
    5459         599 :   const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
    5460             :   Node* node0 = graph()->NewNode(op0);
    5461             :   std::vector<Node*> params;
    5462         599 :   params.reserve(parameter_count + 1);
    5463        2441 :   for (int parameter = 0; parameter < parameter_count + 1; ++parameter) {
    5464        3729 :     params.push_back(node->InputAt(1 + parameter));
    5465             :   }
    5466             :   const Operator* op_param = common()->StateValues(
    5467        1797 :       static_cast<int>(params.size()), SparseInputMask::Dense());
    5468             :   Node* params_node = graph()->NewNode(
    5469        1797 :       op_param, static_cast<int>(params.size()), &params.front());
    5470         599 :   if (!context) {
    5471           0 :     context = jsgraph()->UndefinedConstant();
    5472             :   }
    5473             :   return graph()->NewNode(op, params_node, node0, node0, context,
    5474         599 :                           node->InputAt(0), outer_frame_state);
    5475             : }
    5476             : 
    5477        1621 : Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
    5478             :   DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
    5479         139 :   ConstructParameters const& p = ConstructParametersOf(node->op());
    5480         139 :   int arity = static_cast<int>(p.arity() - 2);
    5481             :   // We only inline when we have the executor.
    5482         139 :   if (arity < 1) return NoChange();
    5483         138 :   Node* target = NodeProperties::GetValueInput(node, 0);
    5484         138 :   Node* executor = NodeProperties::GetValueInput(node, 1);
    5485         138 :   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
    5486             : 
    5487         138 :   Node* context = NodeProperties::GetContextInput(node);
    5488         138 :   Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
    5489         138 :   Node* effect = NodeProperties::GetEffectInput(node);
    5490         138 :   Node* control = NodeProperties::GetControlInput(node);
    5491             : 
    5492         138 :   if (!FLAG_experimental_inline_promise_constructor) return NoChange();
    5493         138 :   if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
    5494             : 
    5495             :   // Only handle builtins Promises, not subclasses.
    5496         115 :   if (target != new_target) return NoChange();
    5497             : 
    5498             :   dependencies()->DependOnProtector(
    5499         114 :       PropertyCellRef(broker(), factory()->promise_hook_protector()));
    5500             : 
    5501             :   SharedFunctionInfoRef promise_shared =
    5502         114 :       native_context().promise_function().shared();
    5503             : 
    5504             :   // Insert a construct stub frame into the chain of frame states. This will
    5505             :   // reconstruct the proper frame when deoptimizing within the constructor.
    5506             :   // For the frame state, we only provide the executor parameter, even if more
    5507             :   // arugments were passed. This is not observable from JS.
    5508             :   DCHECK_EQ(1, promise_shared.internal_formal_parameter_count());
    5509             :   Node* constructor_frame_state = CreateArtificialFrameState(
    5510             :       node, outer_frame_state, 1, BailoutId::ConstructStubInvoke(),
    5511         114 :       FrameStateType::kConstructStub, promise_shared, context);
    5512             : 
    5513             :   // The deopt continuation of this frame state is never called; the frame state
    5514             :   // is only necessary to obtain the right stack trace.
    5515             :   const std::vector<Node*> checkpoint_parameters({
    5516         114 :       jsgraph()->UndefinedConstant(), /* receiver */
    5517         114 :       jsgraph()->UndefinedConstant(), /* promise */
    5518         114 :       jsgraph()->UndefinedConstant(), /* reject function */
    5519         114 :       jsgraph()->TheHoleConstant()    /* exception */
    5520         570 :   });
    5521             :   int checkpoint_parameters_size =
    5522         228 :       static_cast<int>(checkpoint_parameters.size());
    5523             :   Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    5524             :       jsgraph(), promise_shared,
    5525             :       Builtins::kPromiseConstructorLazyDeoptContinuation, target, context,
    5526             :       checkpoint_parameters.data(), checkpoint_parameters_size,
    5527         114 :       constructor_frame_state, ContinuationFrameStateMode::LAZY);
    5528             : 
    5529             :   // Check if executor is callable
    5530         114 :   Node* check_fail = nullptr;
    5531         114 :   Node* check_throw = nullptr;
    5532             :   WireInCallbackIsCallableCheck(executor, context, frame_state, effect,
    5533         114 :                                 &control, &check_fail, &check_throw);
    5534             : 
    5535             :   // Create the resulting JSPromise.
    5536             :   Node* promise = effect =
    5537         114 :       graph()->NewNode(javascript()->CreatePromise(), context, effect);
    5538             : 
    5539             :   // 8. CreatePromiseResolvingFunctions
    5540             :   // Allocate a promise context for the closures below.
    5541             :   Node* promise_context = effect = graph()->NewNode(
    5542             :       javascript()->CreateFunctionContext(
    5543         342 :           handle(native_context().object()->scope_info(), isolate()),
    5544             :           PromiseBuiltins::kPromiseContextLength - Context::MIN_CONTEXT_SLOTS,
    5545             :           FUNCTION_SCOPE),
    5546         342 :       context, effect, control);
    5547             :   effect = graph()->NewNode(
    5548             :       simplified()->StoreField(
    5549             :           AccessBuilder::ForContextSlot(PromiseBuiltins::kPromiseSlot)),
    5550         342 :       promise_context, promise, effect, control);
    5551             :   effect = graph()->NewNode(
    5552             :       simplified()->StoreField(
    5553             :           AccessBuilder::ForContextSlot(PromiseBuiltins::kAlreadyResolvedSlot)),
    5554         456 :       promise_context, jsgraph()->FalseConstant(), effect, control);
    5555             :   effect = graph()->NewNode(
    5556             :       simplified()->StoreField(
    5557             :           AccessBuilder::ForContextSlot(PromiseBuiltins::kDebugEventSlot)),
    5558         456 :       promise_context, jsgraph()->TrueConstant(), effect, control);
    5559             : 
    5560             :   // Allocate the closure for the resolve case.
    5561             :   SharedFunctionInfoRef resolve_shared =
    5562         114 :       native_context().promise_capability_default_resolve_shared_fun();
    5563             :   Node* resolve = effect = graph()->NewNode(
    5564             :       javascript()->CreateClosure(
    5565             :           resolve_shared.object(), factory()->many_closures_cell(),
    5566         228 :           handle(resolve_shared.object()->GetCode(), isolate())),
    5567         570 :       promise_context, effect, control);
    5568             : 
    5569             :   // Allocate the closure for the reject case.
    5570             :   SharedFunctionInfoRef reject_shared =
    5571         114 :       native_context().promise_capability_default_reject_shared_fun();
    5572             :   Node* reject = effect = graph()->NewNode(
    5573             :       javascript()->CreateClosure(
    5574             :           reject_shared.object(), factory()->many_closures_cell(),
    5575         228 :           handle(reject_shared.object()->GetCode(), isolate())),
    5576         570 :       promise_context, effect, control);
    5577             : 
    5578             :   const std::vector<Node*> checkpoint_parameters_continuation(
    5579         228 :       {jsgraph()->UndefinedConstant() /* receiver */, promise, reject});
    5580             :   int checkpoint_parameters_continuation_size =
    5581         228 :       static_cast<int>(checkpoint_parameters_continuation.size());
    5582             :   // This continuation just returns the created promise and takes care of
    5583             :   // exceptions thrown by the executor.
    5584             :   frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    5585             :       jsgraph(), promise_shared,
    5586             :       Builtins::kPromiseConstructorLazyDeoptContinuation, target, context,
    5587             :       checkpoint_parameters_continuation.data(),
    5588             :       checkpoint_parameters_continuation_size, constructor_frame_state,
    5589         114 :       ContinuationFrameStateMode::LAZY_WITH_CATCH);
    5590             : 
    5591             :   // 9. Call executor with both resolving functions
    5592             :   effect = control = graph()->NewNode(
    5593             :       javascript()->Call(4, p.frequency(), VectorSlotPair(),
    5594             :                          ConvertReceiverMode::kNullOrUndefined,
    5595             :                          SpeculationMode::kDisallowSpeculation),
    5596             :       executor, jsgraph()->UndefinedConstant(), resolve, reject, context,
    5597         456 :       frame_state, effect, control);
    5598             : 
    5599             :   Node* exception_effect = effect;
    5600         114 :   Node* exception_control = control;
    5601             :   {
    5602             :     Node* reason = exception_effect = exception_control = graph()->NewNode(
    5603         228 :         common()->IfException(), exception_control, exception_effect);
    5604             :     // 10a. Call reject if the call to executor threw.
    5605             :     exception_effect = exception_control = graph()->NewNode(
    5606             :         javascript()->Call(3, p.frequency(), VectorSlotPair(),
    5607             :                            ConvertReceiverMode::kNullOrUndefined,
    5608             :                            SpeculationMode::kDisallowSpeculation),
    5609             :         reject, jsgraph()->UndefinedConstant(), reason, context, frame_state,
    5610         342 :         exception_effect, exception_control);
    5611             : 
    5612             :     // Rewire potential exception edges.
    5613         114 :     Node* on_exception = nullptr;
    5614         114 :     if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    5615             :       RewirePostCallbackExceptionEdges(check_throw, on_exception,
    5616             :                                        exception_effect, &check_fail,
    5617          40 :                                        &exception_control);
    5618             :     }
    5619             :   }
    5620             : 
    5621             :   Node* success_effect = effect;
    5622         114 :   Node* success_control = control;
    5623             :   {
    5624         114 :     success_control = graph()->NewNode(common()->IfSuccess(), success_control);
    5625             :   }
    5626             : 
    5627             :   control =
    5628         342 :       graph()->NewNode(common()->Merge(2), success_control, exception_control);
    5629             :   effect = graph()->NewNode(common()->EffectPhi(2), success_effect,
    5630         114 :                             exception_effect, control);
    5631             : 
    5632             :   // Wire up the branch for the case when IsCallable fails for the executor.
    5633             :   // Since {check_throw} is an unconditional throw, it's impossible to
    5634             :   // return a successful completion. Therefore, we simply connect the successful
    5635             :   // completion to the graph end.
    5636             :   Node* throw_node =
    5637         228 :       graph()->NewNode(common()->Throw(), check_throw, check_fail);
    5638         114 :   NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
    5639             : 
    5640         114 :   ReplaceWithValue(node, promise, effect, control);
    5641             :   return Replace(promise);
    5642             : }
    5643             : 
    5644             : // V8 Extras: v8.createPromise(parent)
    5645          18 : Reduction JSCallReducer::ReducePromiseInternalConstructor(Node* node) {
    5646             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5647           6 :   Node* context = NodeProperties::GetContextInput(node);
    5648           6 :   Node* effect = NodeProperties::GetEffectInput(node);
    5649             : 
    5650             :   // Check that promises aren't being observed through (debug) hooks.
    5651           6 :   if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
    5652             : 
    5653             :   dependencies()->DependOnProtector(
    5654           6 :       PropertyCellRef(broker(), factory()->promise_hook_protector()));
    5655             : 
    5656             :   // Create a new pending promise.
    5657             :   Node* value = effect =
    5658           6 :       graph()->NewNode(javascript()->CreatePromise(), context, effect);
    5659             : 
    5660           6 :   ReplaceWithValue(node, value, effect);
    5661             :   return Replace(value);
    5662             : }
    5663             : 
    5664             : // V8 Extras: v8.rejectPromise(promise, reason)
    5665           9 : Reduction JSCallReducer::ReducePromiseInternalReject(Node* node) {
    5666             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5667           3 :   Node* promise = node->op()->ValueInputCount() >= 2
    5668             :                       ? NodeProperties::GetValueInput(node, 2)
    5669           3 :                       : jsgraph()->UndefinedConstant();
    5670           3 :   Node* reason = node->op()->ValueInputCount() >= 3
    5671             :                      ? NodeProperties::GetValueInput(node, 3)
    5672           3 :                      : jsgraph()->UndefinedConstant();
    5673           3 :   Node* debug_event = jsgraph()->TrueConstant();
    5674           3 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    5675           3 :   Node* context = NodeProperties::GetContextInput(node);
    5676           3 :   Node* effect = NodeProperties::GetEffectInput(node);
    5677           3 :   Node* control = NodeProperties::GetControlInput(node);
    5678             : 
    5679             :   // Reject the {promise} using the given {reason}, and trigger debug logic.
    5680             :   Node* value = effect =
    5681             :       graph()->NewNode(javascript()->RejectPromise(), promise, reason,
    5682           3 :                        debug_event, context, frame_state, effect, control);
    5683             : 
    5684           3 :   ReplaceWithValue(node, value, effect, control);
    5685           3 :   return Replace(value);
    5686             : }
    5687             : 
    5688             : // V8 Extras: v8.resolvePromise(promise, resolution)
    5689           6 : Reduction JSCallReducer::ReducePromiseInternalResolve(Node* node) {
    5690             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5691           3 :   Node* promise = node->op()->ValueInputCount() >= 2
    5692             :                       ? NodeProperties::GetValueInput(node, 2)
    5693           3 :                       : jsgraph()->UndefinedConstant();
    5694           3 :   Node* resolution = node->op()->ValueInputCount() >= 3
    5695             :                          ? NodeProperties::GetValueInput(node, 3)
    5696           3 :                          : jsgraph()->UndefinedConstant();
    5697           3 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    5698           3 :   Node* context = NodeProperties::GetContextInput(node);
    5699           3 :   Node* effect = NodeProperties::GetEffectInput(node);
    5700           3 :   Node* control = NodeProperties::GetControlInput(node);
    5701             : 
    5702             :   // Resolve the {promise} using the given {resolution}.
    5703             :   Node* value = effect =
    5704             :       graph()->NewNode(javascript()->ResolvePromise(), promise, resolution,
    5705           3 :                        context, frame_state, effect, control);
    5706             : 
    5707           3 :   ReplaceWithValue(node, value, effect, control);
    5708           3 :   return Replace(value);
    5709             : }
    5710             : 
    5711             : // ES section #sec-promise.prototype.catch
    5712         265 : Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
    5713             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5714          84 :   CallParameters const& p = CallParametersOf(node->op());
    5715          52 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5716             :     return NoChange();
    5717             :   }
    5718          52 :   int arity = static_cast<int>(p.arity() - 2);
    5719          52 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    5720          52 :   Node* effect = NodeProperties::GetEffectInput(node);
    5721          52 :   Node* control = NodeProperties::GetControlInput(node);
    5722             : 
    5723             :   // Check that the Promise.then protector is intact. This protector guards
    5724             :   // that all JSPromise instances whose [[Prototype]] is the initial
    5725             :   // %PromisePrototype% yield the initial %PromisePrototype%.then method
    5726             :   // when looking up "then".
    5727          52 :   if (!isolate()->IsPromiseThenLookupChainIntact()) return NoChange();
    5728             : 
    5729             :   // Check if we know something about {receiver} already.
    5730             :   ZoneHandleSet<Map> receiver_maps;
    5731             :   NodeProperties::InferReceiverMapsResult result =
    5732             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    5733          39 :                                         &receiver_maps);
    5734          39 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    5735             :   DCHECK_NE(0, receiver_maps.size());
    5736             : 
    5737             :   // Check whether all {receiver_maps} are JSPromise maps and
    5738             :   // have the initial Promise.prototype as their [[Prototype]].
    5739          71 :   for (Handle<Map> map : receiver_maps) {
    5740             :     MapRef receiver_map(broker(), map);
    5741          46 :     if (!receiver_map.IsJSPromiseMap()) return NoChange();
    5742          39 :     receiver_map.SerializePrototype();
    5743          39 :     if (!receiver_map.prototype().equals(
    5744          39 :             native_context().promise_prototype())) {
    5745             :       return NoChange();
    5746             :     }
    5747             :   }
    5748             : 
    5749             :   dependencies()->DependOnProtector(
    5750          32 :       PropertyCellRef(broker(), factory()->promise_then_protector()));
    5751             : 
    5752             :   // If the {receiver_maps} aren't reliable, we need to repeat the
    5753             :   // map check here, guarded by the CALL_IC.
    5754          32 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    5755             :     effect =
    5756             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    5757           0 :                                                  receiver_maps, p.feedback()),
    5758           0 :                          receiver, effect, control);
    5759             :   }
    5760             : 
    5761             :   // Massage the {node} to call "then" instead by first removing all inputs
    5762             :   // following the onRejected parameter, and then filling up the parameters
    5763             :   // to two inputs from the left with undefined.
    5764          64 :   Node* target = jsgraph()->Constant(native_context().promise_then());
    5765          32 :   NodeProperties::ReplaceValueInput(node, target, 0);
    5766          32 :   NodeProperties::ReplaceEffectInput(node, effect);
    5767          32 :   for (; arity > 1; --arity) node->RemoveInput(3);
    5768          39 :   for (; arity < 2; ++arity) {
    5769          78 :     node->InsertInput(graph()->zone(), 2, jsgraph()->UndefinedConstant());
    5770             :   }
    5771             :   NodeProperties::ChangeOp(
    5772          32 :       node, javascript()->Call(2 + arity, p.frequency(), p.feedback(),
    5773             :                                ConvertReceiverMode::kNotNullOrUndefined,
    5774          64 :                                p.speculation_mode()));
    5775          32 :   Reduction const reduction = ReducePromisePrototypeThen(node);
    5776          32 :   return reduction.Changed() ? reduction : Changed(node);
    5777             : }
    5778             : 
    5779             : // ES section #sec-promise.prototype.finally
    5780         564 : Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
    5781             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5782         169 :   CallParameters const& p = CallParametersOf(node->op());
    5783          63 :   int arity = static_cast<int>(p.arity() - 2);
    5784          63 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    5785             :   Node* on_finally = arity >= 1 ? NodeProperties::GetValueInput(node, 2)
    5786          77 :                                 : jsgraph()->UndefinedConstant();
    5787          63 :   Node* effect = NodeProperties::GetEffectInput(node);
    5788          63 :   Node* control = NodeProperties::GetControlInput(node);
    5789          63 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5790             :     return NoChange();
    5791             :   }
    5792             : 
    5793             :   // Check that promises aren't being observed through (debug) hooks.
    5794          63 :   if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
    5795             : 
    5796             :   // Check that the Promise#then protector is intact. This protector guards
    5797             :   // that all JSPromise instances whose [[Prototype]] is the initial
    5798             :   // %PromisePrototype% yield the initial %PromisePrototype%.then method
    5799             :   // when looking up "then".
    5800          63 :   if (!isolate()->IsPromiseThenLookupChainIntact()) return NoChange();
    5801             : 
    5802             :   // Also check that the @@species protector is intact, which guards the
    5803             :   // lookup of "constructor" on JSPromise instances, whoch [[Prototype]] is
    5804             :   // the initial %PromisePrototype%, and the Symbol.species lookup on the
    5805             :   // %PromisePrototype%.
    5806          50 :   if (!isolate()->IsPromiseSpeciesLookupChainIntact()) return NoChange();
    5807             : 
    5808             :   // Check if we know something about {receiver} already.
    5809             :   ZoneHandleSet<Map> receiver_maps;
    5810             :   NodeProperties::InferReceiverMapsResult result =
    5811             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    5812          50 :                                         &receiver_maps);
    5813          50 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    5814             :   DCHECK_NE(0, receiver_maps.size());
    5815             : 
    5816             :   // Check whether all {receiver_maps} are JSPromise maps and
    5817             :   // have the initial Promise.prototype as their [[Prototype]].
    5818          93 :   for (Handle<Map> map : receiver_maps) {
    5819             :     MapRef receiver_map(broker(), map);
    5820          57 :     if (!receiver_map.IsJSPromiseMap()) return NoChange();
    5821          50 :     receiver_map.SerializePrototype();
    5822          50 :     if (!receiver_map.prototype().equals(
    5823          50 :             native_context().promise_prototype())) {
    5824             :       return NoChange();
    5825             :     }
    5826             :   }
    5827             : 
    5828             :   dependencies()->DependOnProtector(
    5829          43 :       PropertyCellRef(broker(), factory()->promise_hook_protector()));
    5830             :   dependencies()->DependOnProtector(
    5831          43 :       PropertyCellRef(broker(), factory()->promise_then_protector()));
    5832             :   dependencies()->DependOnProtector(
    5833          43 :       PropertyCellRef(broker(), factory()->promise_species_protector()));
    5834             : 
    5835             :   // If the {receiver_maps} aren't reliable, we need to repeat the
    5836             :   // map check here, guarded by the CALL_IC.
    5837          43 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
    5838             :     effect =
    5839             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    5840           0 :                                                  receiver_maps, p.feedback()),
    5841           0 :                          receiver, effect, control);
    5842             :   }
    5843             : 
    5844             :   // Check if {on_finally} is callable, and if so wrap it into appropriate
    5845             :   // closures that perform the finalization.
    5846          43 :   Node* check = graph()->NewNode(simplified()->ObjectIsCallable(), on_finally);
    5847             :   Node* branch =
    5848          43 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    5849             : 
    5850          43 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    5851             :   Node* etrue = effect;
    5852             :   Node* catch_true;
    5853             :   Node* then_true;
    5854             :   {
    5855          86 :     Node* context = jsgraph()->Constant(native_context());
    5856             :     Node* constructor =
    5857          86 :         jsgraph()->Constant(native_context().promise_function());
    5858             : 
    5859             :     // Allocate shared context for the closures below.
    5860             :     context = etrue = graph()->NewNode(
    5861             :         javascript()->CreateFunctionContext(
    5862         129 :             handle(native_context().object()->scope_info(), isolate()),
    5863             :             PromiseBuiltins::kPromiseFinallyContextLength -
    5864             :                 Context::MIN_CONTEXT_SLOTS,
    5865             :             FUNCTION_SCOPE),
    5866          86 :         context, etrue, if_true);
    5867             :     etrue = graph()->NewNode(
    5868             :         simplified()->StoreField(
    5869             :             AccessBuilder::ForContextSlot(PromiseBuiltins::kOnFinallySlot)),
    5870         129 :         context, on_finally, etrue, if_true);
    5871             :     etrue = graph()->NewNode(
    5872             :         simplified()->StoreField(
    5873             :             AccessBuilder::ForContextSlot(PromiseBuiltins::kConstructorSlot)),
    5874         129 :         context, constructor, etrue, if_true);
    5875             : 
    5876             :     // Allocate the closure for the reject case.
    5877             :     SharedFunctionInfoRef catch_finally =
    5878          43 :         native_context().promise_catch_finally_shared_fun();
    5879             :     catch_true = etrue = graph()->NewNode(
    5880             :         javascript()->CreateClosure(
    5881             :             catch_finally.object(), factory()->many_closures_cell(),
    5882          86 :             handle(catch_finally.object()->GetCode(), isolate())),
    5883         172 :         context, etrue, if_true);
    5884             : 
    5885             :     // Allocate the closure for the fulfill case.
    5886             :     SharedFunctionInfoRef then_finally =
    5887          43 :         native_context().promise_then_finally_shared_fun();
    5888             :     then_true = etrue = graph()->NewNode(
    5889             :         javascript()->CreateClosure(
    5890             :             then_finally.object(), factory()->many_closures_cell(),
    5891          86 :             handle(then_finally.object()->GetCode(), isolate())),
    5892         172 :         context, etrue, if_true);
    5893             :   }
    5894             : 
    5895          43 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    5896             :   Node* efalse = effect;
    5897             :   Node* catch_false = on_finally;
    5898             :   Node* then_false = on_finally;
    5899             : 
    5900          43 :   control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    5901          43 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    5902             :   Node* catch_finally =
    5903             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    5904          43 :                        catch_true, catch_false, control);
    5905             :   Node* then_finally =
    5906             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    5907          43 :                        then_true, then_false, control);
    5908             : 
    5909             :   // At this point we definitely know that {receiver} has one of the
    5910             :   // {receiver_maps}, so insert a MapGuard as a hint for the lowering
    5911             :   // of the call to "then" below.
    5912             :   effect = graph()->NewNode(simplified()->MapGuard(receiver_maps), receiver,
    5913          43 :                             effect, control);
    5914             : 
    5915             :   // Massage the {node} to call "then" instead by first removing all inputs
    5916             :   // following the onFinally parameter, and then replacing the only parameter
    5917             :   // input with the {on_finally} value.
    5918          86 :   Node* target = jsgraph()->Constant(native_context().promise_then());
    5919          43 :   NodeProperties::ReplaceValueInput(node, target, 0);
    5920          43 :   NodeProperties::ReplaceEffectInput(node, effect);
    5921          43 :   NodeProperties::ReplaceControlInput(node, control);
    5922          43 :   for (; arity > 2; --arity) node->RemoveInput(2);
    5923          50 :   for (; arity < 2; ++arity)
    5924          50 :     node->InsertInput(graph()->zone(), 2, then_finally);
    5925          43 :   node->ReplaceInput(2, then_finally);
    5926          43 :   node->ReplaceInput(3, catch_finally);
    5927             :   NodeProperties::ChangeOp(
    5928          43 :       node, javascript()->Call(2 + arity, p.frequency(), p.feedback(),
    5929             :                                ConvertReceiverMode::kNotNullOrUndefined,
    5930          86 :                                p.speculation_mode()));
    5931          43 :   Reduction const reduction = ReducePromisePrototypeThen(node);
    5932          43 :   return reduction.Changed() ? reduction : Changed(node);
    5933             : }
    5934             : 
    5935        1952 : Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
    5936             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    5937         175 :   CallParameters const& p = CallParametersOf(node->op());
    5938         175 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    5939             :     return NoChange();
    5940             :   }
    5941             : 
    5942         175 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    5943         175 :   Node* on_fulfilled = node->op()->ValueInputCount() > 2
    5944             :                            ? NodeProperties::GetValueInput(node, 2)
    5945         189 :                            : jsgraph()->UndefinedConstant();
    5946         175 :   Node* on_rejected = node->op()->ValueInputCount() > 3
    5947             :                           ? NodeProperties::GetValueInput(node, 3)
    5948         244 :                           : jsgraph()->UndefinedConstant();
    5949         175 :   Node* context = NodeProperties::GetContextInput(node);
    5950         175 :   Node* effect = NodeProperties::GetEffectInput(node);
    5951         175 :   Node* control = NodeProperties::GetControlInput(node);
    5952         175 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    5953             : 
    5954             :   // Check that promises aren't being observed through (debug) hooks.
    5955         175 :   if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
    5956             : 
    5957             :   // Check if the @@species protector is intact. The @@species protector
    5958             :   // guards the "constructor" lookup on all JSPromise instances and the
    5959             :   // initial Promise.prototype, as well as the  Symbol.species lookup on
    5960             :   // the Promise constructor.
    5961         171 :   if (!isolate()->IsPromiseSpeciesLookupChainIntact()) return NoChange();
    5962             : 
    5963             :   // Check if we know something about {receiver} already.
    5964             :   ZoneHandleSet<Map> receiver_maps;
    5965             :   NodeProperties::InferReceiverMapsResult infer_receiver_maps_result =
    5966             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    5967         168 :                                         &receiver_maps);
    5968         168 :   if (infer_receiver_maps_result == NodeProperties::kNoReceiverMaps) {
    5969             :     return NoChange();
    5970             :   }
    5971             :   DCHECK_NE(0, receiver_maps.size());
    5972             : 
    5973             :   // Check whether all {receiver_maps} are JSPromise maps and
    5974             :   // have the initial Promise.prototype as their [[Prototype]].
    5975         336 :   for (Handle<Map> map : receiver_maps) {
    5976             :     MapRef receiver_map(broker(), map);
    5977         168 :     if (!receiver_map.IsJSPromiseMap()) return NoChange();
    5978         168 :     receiver_map.SerializePrototype();
    5979         168 :     if (!receiver_map.prototype().equals(
    5980         168 :             native_context().promise_prototype())) {
    5981             :       return NoChange();
    5982             :     }
    5983             :   }
    5984             : 
    5985             :   dependencies()->DependOnProtector(
    5986         168 :       PropertyCellRef(broker(), factory()->promise_hook_protector()));
    5987             :   dependencies()->DependOnProtector(
    5988         168 :       PropertyCellRef(broker(), factory()->promise_species_protector()));
    5989             : 
    5990             :   // If the {receiver_maps} aren't reliable, we need to repeat the
    5991             :   // map check here, guarded by the CALL_IC.
    5992         168 :   if (infer_receiver_maps_result == NodeProperties::kUnreliableReceiverMaps) {
    5993             :     effect =
    5994             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    5995           0 :                                                  receiver_maps, p.feedback()),
    5996           0 :                          receiver, effect, control);
    5997             :   }
    5998             : 
    5999             :   // Check that {on_fulfilled} is callable.
    6000             :   on_fulfilled = graph()->NewNode(
    6001             :       common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
    6002             :       graph()->NewNode(simplified()->ObjectIsCallable(), on_fulfilled),
    6003         504 :       on_fulfilled, jsgraph()->UndefinedConstant());
    6004             : 
    6005             :   // Check that {on_rejected} is callable.
    6006             :   on_rejected = graph()->NewNode(
    6007             :       common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
    6008             :       graph()->NewNode(simplified()->ObjectIsCallable(), on_rejected),
    6009         504 :       on_rejected, jsgraph()->UndefinedConstant());
    6010             : 
    6011             :   // Create the resulting JSPromise.
    6012             :   Node* result = effect =
    6013         168 :       graph()->NewNode(javascript()->CreatePromise(), context, effect);
    6014             : 
    6015             :   // Chain {result} onto {receiver}.
    6016             :   result = effect = graph()->NewNode(
    6017             :       javascript()->PerformPromiseThen(), receiver, on_fulfilled, on_rejected,
    6018         168 :       result, context, frame_state, effect, control);
    6019             : 
    6020             :   // At this point we know that {result} is going to have the
    6021             :   // initial Promise map, since even if {PerformPromiseThen}
    6022             :   // above called into the host rejection tracker, the {result}
    6023             :   // doesn't escape to user JavaScript. So bake this information
    6024             :   // into the graph such that subsequent passes can use the
    6025             :   // information for further optimizations.
    6026         168 :   MapRef result_map = native_context().promise_function().initial_map();
    6027             :   effect = graph()->NewNode(
    6028             :       simplified()->MapGuard(ZoneHandleSet<Map>(result_map.object())), result,
    6029         504 :       effect, control);
    6030             : 
    6031         168 :   ReplaceWithValue(node, result, effect, control);
    6032             :   return Replace(result);
    6033             : }
    6034             : 
    6035             : // ES section #sec-promise.resolve
    6036         502 : Reduction JSCallReducer::ReducePromiseResolveTrampoline(Node* node) {
    6037             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    6038         119 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6039         119 :   Node* value = node->op()->ValueInputCount() > 2
    6040             :                     ? NodeProperties::GetValueInput(node, 2)
    6041         145 :                     : jsgraph()->UndefinedConstant();
    6042         119 :   Node* context = NodeProperties::GetContextInput(node);
    6043         119 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    6044         119 :   Node* effect = NodeProperties::GetEffectInput(node);
    6045         119 :   Node* control = NodeProperties::GetControlInput(node);
    6046             : 
    6047             :   // Check if we know something about {receiver} already.
    6048             :   ZoneHandleSet<Map> receiver_maps;
    6049             :   NodeProperties::InferReceiverMapsResult infer_receiver_maps_result =
    6050             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    6051         119 :                                         &receiver_maps);
    6052         119 :   if (infer_receiver_maps_result == NodeProperties::kNoReceiverMaps) {
    6053             :     return NoChange();
    6054             :   }
    6055             :   DCHECK_NE(0, receiver_maps.size());
    6056             : 
    6057             :   // Only reduce when all {receiver_maps} are JSReceiver maps.
    6058         238 :   for (Handle<Map> map : receiver_maps) {
    6059             :     MapRef receiver_map(broker(), map);
    6060         119 :     if (!receiver_map.IsJSReceiverMap()) return NoChange();
    6061             :   }
    6062             : 
    6063             :   // Morph the {node} into a JSPromiseResolve operation.
    6064         119 :   node->ReplaceInput(0, receiver);
    6065         119 :   node->ReplaceInput(1, value);
    6066         119 :   node->ReplaceInput(2, context);
    6067         119 :   node->ReplaceInput(3, frame_state);
    6068         119 :   node->ReplaceInput(4, effect);
    6069         119 :   node->ReplaceInput(5, control);
    6070         119 :   node->TrimInputCount(6);
    6071         119 :   NodeProperties::ChangeOp(node, javascript()->PromiseResolve());
    6072             :   return Changed(node);
    6073             : }
    6074             : 
    6075             : // ES #sec-typedarray-constructors
    6076         485 : Reduction JSCallReducer::ReduceTypedArrayConstructor(
    6077        2380 :     Node* node, const SharedFunctionInfoRef& shared) {
    6078             :   DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
    6079         485 :   ConstructParameters const& p = ConstructParametersOf(node->op());
    6080         485 :   int arity = static_cast<int>(p.arity() - 2);
    6081         485 :   Node* target = NodeProperties::GetValueInput(node, 0);
    6082             :   Node* arg1 = (arity >= 1) ? NodeProperties::GetValueInput(node, 1)
    6083         492 :                             : jsgraph()->UndefinedConstant();
    6084             :   Node* arg2 = (arity >= 2) ? NodeProperties::GetValueInput(node, 2)
    6085         925 :                             : jsgraph()->UndefinedConstant();
    6086             :   Node* arg3 = (arity >= 3) ? NodeProperties::GetValueInput(node, 3)
    6087         963 :                             : jsgraph()->UndefinedConstant();
    6088         485 :   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
    6089         485 :   Node* context = NodeProperties::GetContextInput(node);
    6090         485 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    6091         485 :   Node* effect = NodeProperties::GetEffectInput(node);
    6092         485 :   Node* control = NodeProperties::GetControlInput(node);
    6093             : 
    6094             :   // Insert a construct stub frame into the chain of frame states. This will
    6095             :   // reconstruct the proper frame when deoptimizing within the constructor.
    6096             :   frame_state = CreateArtificialFrameState(
    6097             :       node, frame_state, arity, BailoutId::ConstructStubInvoke(),
    6098         485 :       FrameStateType::kConstructStub, shared, context);
    6099             : 
    6100             :   // This continuation just returns the newly created JSTypedArray. We
    6101             :   // pass the_hole as the receiver, just like the builtin construct stub
    6102             :   // does in this case.
    6103         485 :   Node* const parameters[] = {jsgraph()->TheHoleConstant()};
    6104             :   int const num_parameters = static_cast<int>(arraysize(parameters));
    6105             :   frame_state = CreateJavaScriptBuiltinContinuationFrameState(
    6106             :       jsgraph(), shared, Builtins::kGenericConstructorLazyDeoptContinuation,
    6107             :       target, context, parameters, num_parameters, frame_state,
    6108         485 :       ContinuationFrameStateMode::LAZY);
    6109             : 
    6110             :   Node* result =
    6111             :       graph()->NewNode(javascript()->CreateTypedArray(), target, new_target,
    6112         485 :                        arg1, arg2, arg3, context, frame_state, effect, control);
    6113         485 :   return Replace(result);
    6114             : }
    6115             : 
    6116             : // ES #sec-get-%typedarray%.prototype-@@tostringtag
    6117         588 : Reduction JSCallReducer::ReduceTypedArrayPrototypeToStringTag(Node* node) {
    6118          21 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6119          21 :   Node* effect = NodeProperties::GetEffectInput(node);
    6120          21 :   Node* control = NodeProperties::GetControlInput(node);
    6121             : 
    6122          21 :   NodeVector values(graph()->zone());
    6123          21 :   NodeVector effects(graph()->zone());
    6124          21 :   NodeVector controls(graph()->zone());
    6125             : 
    6126          21 :   Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
    6127             :   control =
    6128          63 :       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
    6129             : 
    6130          42 :   values.push_back(jsgraph()->UndefinedConstant());
    6131          21 :   effects.push_back(effect);
    6132          84 :   controls.push_back(graph()->NewNode(common()->IfTrue(), control));
    6133             : 
    6134          63 :   control = graph()->NewNode(common()->IfFalse(), control);
    6135             :   Node* receiver_map = effect =
    6136             :       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
    6137          63 :                        receiver, effect, control);
    6138             :   Node* receiver_bit_field2 = effect = graph()->NewNode(
    6139             :       simplified()->LoadField(AccessBuilder::ForMapBitField2()), receiver_map,
    6140          63 :       effect, control);
    6141             :   Node* receiver_elements_kind = graph()->NewNode(
    6142             :       simplified()->NumberShiftRightLogical(),
    6143             :       graph()->NewNode(simplified()->NumberBitwiseAnd(), receiver_bit_field2,
    6144             :                        jsgraph()->Constant(Map::ElementsKindBits::kMask)),
    6145          84 :       jsgraph()->Constant(Map::ElementsKindBits::kShift));
    6146             : 
    6147             :   // Offset the elements kind by FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
    6148             :   // so that the branch cascade below is turned into a simple table
    6149             :   // switch by the ControlFlowOptimizer later.
    6150             :   receiver_elements_kind = graph()->NewNode(
    6151             :       simplified()->NumberSubtract(), receiver_elements_kind,
    6152          42 :       jsgraph()->Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND));
    6153             : 
    6154             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)                      \
    6155             :   do {                                                                 \
    6156             :     Node* check = graph()->NewNode(                                    \
    6157             :         simplified()->NumberEqual(), receiver_elements_kind,           \
    6158             :         jsgraph()->Constant(TYPE##_ELEMENTS -                          \
    6159             :                             FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND));   \
    6160             :     control = graph()->NewNode(common()->Branch(), check, control);    \
    6161             :     values.push_back(jsgraph()->HeapConstant(                          \
    6162             :         factory()->InternalizeUtf8String(#Type "Array")));             \
    6163             :     effects.push_back(effect);                                         \
    6164             :     controls.push_back(graph()->NewNode(common()->IfTrue(), control)); \
    6165             :     control = graph()->NewNode(common()->IfFalse(), control);          \
    6166             :   } while (false);
    6167        3003 :   TYPED_ARRAYS(TYPED_ARRAY_CASE)
    6168             : #undef TYPED_ARRAY_CASE
    6169             : 
    6170          42 :   values.push_back(jsgraph()->UndefinedConstant());
    6171          21 :   effects.push_back(effect);
    6172          21 :   controls.push_back(control);
    6173             : 
    6174          42 :   int const count = static_cast<int>(controls.size());
    6175          42 :   control = graph()->NewNode(common()->Merge(count), count, &controls.front());
    6176          21 :   effects.push_back(control);
    6177             :   effect =
    6178          63 :       graph()->NewNode(common()->EffectPhi(count), count + 1, &effects.front());
    6179          21 :   values.push_back(control);
    6180             :   Node* value =
    6181             :       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
    6182          42 :                        count + 1, &values.front());
    6183          21 :   ReplaceWithValue(node, value, effect, control);
    6184          21 :   return Replace(value);
    6185             : }
    6186             : 
    6187             : // ES #sec-number.isfinite
    6188         239 : Reduction JSCallReducer::ReduceNumberIsFinite(Node* node) {
    6189         478 :   if (node->op()->ValueInputCount() < 3) {
    6190           0 :     Node* value = jsgraph()->FalseConstant();
    6191         239 :     ReplaceWithValue(node, value);
    6192             :     return Replace(value);
    6193             :   }
    6194         239 :   Node* input = NodeProperties::GetValueInput(node, 2);
    6195         239 :   Node* value = graph()->NewNode(simplified()->ObjectIsFiniteNumber(), input);
    6196             :   ReplaceWithValue(node, value);
    6197             :   return Replace(value);
    6198             : }
    6199             : 
    6200             : // ES #sec-number.isfinite
    6201         239 : Reduction JSCallReducer::ReduceNumberIsInteger(Node* node) {
    6202         478 :   if (node->op()->ValueInputCount() < 3) {
    6203           0 :     Node* value = jsgraph()->FalseConstant();
    6204         239 :     ReplaceWithValue(node, value);
    6205             :     return Replace(value);
    6206             :   }
    6207         239 :   Node* input = NodeProperties::GetValueInput(node, 2);
    6208         239 :   Node* value = graph()->NewNode(simplified()->ObjectIsInteger(), input);
    6209             :   ReplaceWithValue(node, value);
    6210             :   return Replace(value);
    6211             : }
    6212             : 
    6213             : // ES #sec-number.issafeinteger
    6214          15 : Reduction JSCallReducer::ReduceNumberIsSafeInteger(Node* node) {
    6215          30 :   if (node->op()->ValueInputCount() < 3) {
    6216           0 :     Node* value = jsgraph()->FalseConstant();
    6217          15 :     ReplaceWithValue(node, value);
    6218             :     return Replace(value);
    6219             :   }
    6220          15 :   Node* input = NodeProperties::GetValueInput(node, 2);
    6221          15 :   Node* value = graph()->NewNode(simplified()->ObjectIsSafeInteger(), input);
    6222             :   ReplaceWithValue(node, value);
    6223             :   return Replace(value);
    6224             : }
    6225             : 
    6226             : // ES #sec-number.isnan
    6227          57 : Reduction JSCallReducer::ReduceNumberIsNaN(Node* node) {
    6228         100 :   if (node->op()->ValueInputCount() < 3) {
    6229           7 :     Node* value = jsgraph()->FalseConstant();
    6230          50 :     ReplaceWithValue(node, value);
    6231             :     return Replace(value);
    6232             :   }
    6233          43 :   Node* input = NodeProperties::GetValueInput(node, 2);
    6234          43 :   Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input);
    6235             :   ReplaceWithValue(node, value);
    6236             :   return Replace(value);
    6237             : }
    6238             : 
    6239         456 : Reduction JSCallReducer::ReduceMapPrototypeGet(Node* node) {
    6240             :   // We only optimize if we have target, receiver and key parameters.
    6241         114 :   if (node->op()->ValueInputCount() != 3) return NoChange();
    6242         114 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6243         114 :   Node* effect = NodeProperties::GetEffectInput(node);
    6244         114 :   Node* control = NodeProperties::GetControlInput(node);
    6245         114 :   Node* key = NodeProperties::GetValueInput(node, 2);
    6246             : 
    6247         114 :   if (!NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
    6248         114 :                                               JS_MAP_TYPE))
    6249             :     return NoChange();
    6250             : 
    6251             :   Node* table = effect = graph()->NewNode(
    6252             :       simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
    6253         342 :       effect, control);
    6254             : 
    6255             :   Node* entry = effect = graph()->NewNode(
    6256         114 :       simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
    6257             : 
    6258             :   Node* check = graph()->NewNode(simplified()->NumberEqual(), entry,
    6259         228 :                                  jsgraph()->MinusOneConstant());
    6260             : 
    6261         114 :   Node* branch = graph()->NewNode(common()->Branch(), check, control);
    6262             : 
    6263             :   // Key not found.
    6264         114 :   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    6265             :   Node* etrue = effect;
    6266         114 :   Node* vtrue = jsgraph()->UndefinedConstant();
    6267             : 
    6268             :   // Key found.
    6269         114 :   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    6270             :   Node* efalse = effect;
    6271             :   Node* vfalse = efalse = graph()->NewNode(
    6272             :       simplified()->LoadElement(AccessBuilder::ForOrderedHashMapEntryValue()),
    6273         342 :       table, entry, efalse, if_false);
    6274             : 
    6275         114 :   control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    6276             :   Node* value = graph()->NewNode(
    6277         114 :       common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control);
    6278         114 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    6279             : 
    6280         114 :   ReplaceWithValue(node, value, effect, control);
    6281             :   return Replace(value);
    6282             : }
    6283             : 
    6284         291 : Reduction JSCallReducer::ReduceMapPrototypeHas(Node* node) {
    6285             :   // We only optimize if we have target, receiver and key parameters.
    6286          97 :   if (node->op()->ValueInputCount() != 3) return NoChange();
    6287          97 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6288          97 :   Node* effect = NodeProperties::GetEffectInput(node);
    6289          97 :   Node* control = NodeProperties::GetControlInput(node);
    6290          97 :   Node* key = NodeProperties::GetValueInput(node, 2);
    6291             : 
    6292          97 :   if (!NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
    6293          97 :                                               JS_MAP_TYPE))
    6294             :     return NoChange();
    6295             : 
    6296             :   Node* table = effect = graph()->NewNode(
    6297             :       simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
    6298         291 :       effect, control);
    6299             : 
    6300             :   Node* index = effect = graph()->NewNode(
    6301          97 :       simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
    6302             : 
    6303             :   Node* value = graph()->NewNode(simplified()->NumberEqual(), index,
    6304         194 :                                  jsgraph()->MinusOneConstant());
    6305          97 :   value = graph()->NewNode(simplified()->BooleanNot(), value);
    6306             : 
    6307          97 :   ReplaceWithValue(node, value, effect, control);
    6308             :   return Replace(value);
    6309             : }
    6310             : 
    6311             : namespace {
    6312             : 
    6313         278 : InstanceType InstanceTypeForCollectionKind(CollectionKind kind) {
    6314         278 :   switch (kind) {
    6315             :     case CollectionKind::kMap:
    6316             :       return JS_MAP_TYPE;
    6317             :     case CollectionKind::kSet:
    6318         109 :       return JS_SET_TYPE;
    6319             :   }
    6320           0 :   UNREACHABLE();
    6321             : }
    6322             : 
    6323             : }  // namespace
    6324             : 
    6325         164 : Reduction JSCallReducer::ReduceCollectionIteration(
    6326         164 :     Node* node, CollectionKind collection_kind, IterationKind iteration_kind) {
    6327             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    6328         164 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6329         164 :   Node* context = NodeProperties::GetContextInput(node);
    6330         164 :   Node* effect = NodeProperties::GetEffectInput(node);
    6331         164 :   Node* control = NodeProperties::GetControlInput(node);
    6332         164 :   if (NodeProperties::HasInstanceTypeWitness(
    6333             :           broker(), receiver, effect,
    6334         164 :           InstanceTypeForCollectionKind(collection_kind))) {
    6335             :     Node* js_create_iterator = effect = graph()->NewNode(
    6336             :         javascript()->CreateCollectionIterator(collection_kind, iteration_kind),
    6337         164 :         receiver, context, effect, control);
    6338         164 :     ReplaceWithValue(node, js_create_iterator, effect);
    6339             :     return Replace(js_create_iterator);
    6340             :   }
    6341             :   return NoChange();
    6342             : }
    6343             : 
    6344         114 : Reduction JSCallReducer::ReduceCollectionPrototypeSize(
    6345         114 :     Node* node, CollectionKind collection_kind) {
    6346             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    6347         114 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6348         114 :   Node* effect = NodeProperties::GetEffectInput(node);
    6349         114 :   Node* control = NodeProperties::GetControlInput(node);
    6350         114 :   if (NodeProperties::HasInstanceTypeWitness(
    6351             :           broker(), receiver, effect,
    6352         114 :           InstanceTypeForCollectionKind(collection_kind))) {
    6353             :     Node* table = effect = graph()->NewNode(
    6354             :         simplified()->LoadField(AccessBuilder::ForJSCollectionTable()),
    6355         342 :         receiver, effect, control);
    6356             :     Node* value = effect = graph()->NewNode(
    6357             :         simplified()->LoadField(
    6358             :             AccessBuilder::ForOrderedHashMapOrSetNumberOfElements()),
    6359         342 :         table, effect, control);
    6360         114 :     ReplaceWithValue(node, value, effect, control);
    6361             :     return Replace(value);
    6362             :   }
    6363             :   return NoChange();
    6364             : }
    6365             : 
    6366         280 : Reduction JSCallReducer::ReduceCollectionIteratorPrototypeNext(
    6367             :     Node* node, int entry_size, Handle<HeapObject> empty_collection,
    6368             :     InstanceType collection_iterator_instance_type_first,
    6369        3157 :     InstanceType collection_iterator_instance_type_last) {
    6370             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    6371         280 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6372         280 :   Node* context = NodeProperties::GetContextInput(node);
    6373         280 :   Node* effect = NodeProperties::GetEffectInput(node);
    6374         280 :   Node* control = NodeProperties::GetControlInput(node);
    6375             : 
    6376             :   // A word of warning to begin with: This whole method might look a bit
    6377             :   // strange at times, but that's mostly because it was carefully handcrafted
    6378             :   // to allow for full escape analysis and scalar replacement of both the
    6379             :   // collection iterator object and the iterator results, including the
    6380             :   // key-value arrays in case of Set/Map entry iteration.
    6381             :   //
    6382             :   // TODO(turbofan): Currently the escape analysis (and the store-load
    6383             :   // forwarding) is unable to eliminate the allocations for the key-value
    6384             :   // arrays in case of Set/Map entry iteration, and we should investigate
    6385             :   // how to update the escape analysis / arrange the graph in a way that
    6386             :   // this becomes possible.
    6387             : 
    6388             :   // Infer the {receiver} instance type.
    6389             :   InstanceType receiver_instance_type;
    6390             :   ZoneHandleSet<Map> receiver_maps;
    6391             :   NodeProperties::InferReceiverMapsResult result =
    6392             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    6393         280 :                                         &receiver_maps);
    6394         280 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    6395             :   DCHECK_NE(0, receiver_maps.size());
    6396             :   receiver_instance_type = receiver_maps[0]->instance_type();
    6397         560 :   for (size_t i = 1; i < receiver_maps.size(); ++i) {
    6398           0 :     if (receiver_maps[i]->instance_type() != receiver_instance_type) {
    6399             :       return NoChange();
    6400             :     }
    6401             :   }
    6402         560 :   if (receiver_instance_type < collection_iterator_instance_type_first ||
    6403         280 :       receiver_instance_type > collection_iterator_instance_type_last) {
    6404             :     return NoChange();
    6405             :   }
    6406             : 
    6407             :   // Transition the JSCollectionIterator {receiver} if necessary
    6408             :   // (i.e. there were certain mutations while we're iterating).
    6409             :   {
    6410             :     Node* done_loop;
    6411             :     Node* done_eloop;
    6412             :     Node* loop = control =
    6413         280 :         graph()->NewNode(common()->Loop(2), control, control);
    6414             :     Node* eloop = effect =
    6415         280 :         graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    6416         280 :     Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
    6417         280 :     NodeProperties::MergeControlToEnd(graph(), common(), terminate);
    6418             : 
    6419             :     // Check if reached the final table of the {receiver}.
    6420             :     Node* table = effect = graph()->NewNode(
    6421             :         simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
    6422         840 :         receiver, effect, control);
    6423             :     Node* next_table = effect =
    6424             :         graph()->NewNode(simplified()->LoadField(
    6425             :                              AccessBuilder::ForOrderedHashMapOrSetNextTable()),
    6426         840 :                          table, effect, control);
    6427         280 :     Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), next_table);
    6428             :     control =
    6429         280 :         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    6430             : 
    6431             :     // Abort the {loop} when we reach the final table.
    6432         280 :     done_loop = graph()->NewNode(common()->IfTrue(), control);
    6433             :     done_eloop = effect;
    6434             : 
    6435             :     // Migrate to the {next_table} otherwise.
    6436         280 :     control = graph()->NewNode(common()->IfFalse(), control);
    6437             : 
    6438             :     // Self-heal the {receiver}s index.
    6439             :     Node* index = effect = graph()->NewNode(
    6440             :         simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
    6441         840 :         receiver, effect, control);
    6442             :     Callable const callable =
    6443         280 :         Builtins::CallableFor(isolate(), Builtins::kOrderedHashTableHealIndex);
    6444             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
    6445             :         graph()->zone(), callable.descriptor(),
    6446             :         callable.descriptor().GetStackParameterCount(),
    6447         560 :         CallDescriptor::kNoFlags, Operator::kEliminatable);
    6448             :     index = effect =
    6449             :         graph()->NewNode(common()->Call(call_descriptor),
    6450             :                          jsgraph()->HeapConstant(callable.code()), table, index,
    6451         840 :                          jsgraph()->NoContextConstant(), effect);
    6452             : 
    6453             :     index = effect = graph()->NewNode(
    6454         280 :         common()->TypeGuard(TypeCache::Get()->kFixedArrayLengthType), index,
    6455         280 :         effect, control);
    6456             : 
    6457             :     // Update the {index} and {table} on the {receiver}.
    6458             :     effect = graph()->NewNode(
    6459             :         simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorIndex()),
    6460         840 :         receiver, index, effect, control);
    6461             :     effect = graph()->NewNode(
    6462             :         simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorTable()),
    6463         840 :         receiver, next_table, effect, control);
    6464             : 
    6465             :     // Tie the knot.
    6466         280 :     loop->ReplaceInput(1, control);
    6467         280 :     eloop->ReplaceInput(1, effect);
    6468             : 
    6469             :     control = done_loop;
    6470             :     effect = done_eloop;
    6471             :   }
    6472             : 
    6473             :   // Get current index and table from the JSCollectionIterator {receiver}.
    6474             :   Node* index = effect = graph()->NewNode(
    6475             :       simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
    6476         840 :       receiver, effect, control);
    6477             :   Node* table = effect = graph()->NewNode(
    6478             :       simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
    6479         840 :       receiver, effect, control);
    6480             : 
    6481             :   // Create the {JSIteratorResult} first to ensure that we always have
    6482             :   // a dominating Allocate node for the allocation folding phase.
    6483             :   Node* iterator_result = effect = graph()->NewNode(
    6484             :       javascript()->CreateIterResultObject(), jsgraph()->UndefinedConstant(),
    6485         840 :       jsgraph()->TrueConstant(), context, effect);
    6486             : 
    6487             :   // Look for the next non-holey key, starting from {index} in the {table}.
    6488             :   Node* controls[2];
    6489             :   Node* effects[3];
    6490             :   {
    6491             :     // Compute the currently used capacity.
    6492             :     Node* number_of_buckets = effect = graph()->NewNode(
    6493             :         simplified()->LoadField(
    6494             :             AccessBuilder::ForOrderedHashMapOrSetNumberOfBuckets()),
    6495         840 :         table, effect, control);
    6496             :     Node* number_of_elements = effect = graph()->NewNode(
    6497             :         simplified()->LoadField(
    6498             :             AccessBuilder::ForOrderedHashMapOrSetNumberOfElements()),
    6499         840 :         table, effect, control);
    6500             :     Node* number_of_deleted_elements = effect = graph()->NewNode(
    6501             :         simplified()->LoadField(
    6502             :             AccessBuilder::ForOrderedHashMapOrSetNumberOfDeletedElements()),
    6503         840 :         table, effect, control);
    6504             :     Node* used_capacity =
    6505             :         graph()->NewNode(simplified()->NumberAdd(), number_of_elements,
    6506         280 :                          number_of_deleted_elements);
    6507             : 
    6508             :     // Skip holes and update the {index}.
    6509         280 :     Node* loop = graph()->NewNode(common()->Loop(2), control, control);
    6510             :     Node* eloop =
    6511         280 :         graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    6512         280 :     Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
    6513         280 :     NodeProperties::MergeControlToEnd(graph(), common(), terminate);
    6514             :     Node* iloop = graph()->NewNode(
    6515         280 :         common()->Phi(MachineRepresentation::kTagged, 2), index, index, loop);
    6516             : 
    6517             :     Node* index = effect = graph()->NewNode(
    6518         280 :         common()->TypeGuard(TypeCache::Get()->kFixedArrayLengthType), iloop,
    6519         280 :         eloop, control);
    6520             :     {
    6521             :       Node* check0 = graph()->NewNode(simplified()->NumberLessThan(), index,
    6522         280 :                                       used_capacity);
    6523             :       Node* branch0 =
    6524         280 :           graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, loop);
    6525             : 
    6526         280 :       Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    6527             :       Node* efalse0 = effect;
    6528             :       {
    6529             :         // Mark the {receiver} as exhausted.
    6530             :         efalse0 = graph()->NewNode(
    6531             :             simplified()->StoreField(
    6532             :                 AccessBuilder::ForJSCollectionIteratorTable()),
    6533             :             receiver, jsgraph()->HeapConstant(empty_collection), efalse0,
    6534         840 :             if_false0);
    6535             : 
    6536         280 :         controls[0] = if_false0;
    6537         280 :         effects[0] = efalse0;
    6538             :       }
    6539             : 
    6540         280 :       Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    6541             :       Node* etrue0 = effect;
    6542             :       {
    6543             :         // Load the key of the entry.
    6544             :         STATIC_ASSERT(OrderedHashMap::HashTableStartIndex() ==
    6545             :                       OrderedHashSet::HashTableStartIndex());
    6546             :         Node* entry_start_position = graph()->NewNode(
    6547             :             simplified()->NumberAdd(),
    6548             :             graph()->NewNode(
    6549             :                 simplified()->NumberAdd(),
    6550             :                 graph()->NewNode(simplified()->NumberMultiply(), index,
    6551             :                                  jsgraph()->Constant(entry_size)),
    6552             :                 number_of_buckets),
    6553        1400 :             jsgraph()->Constant(OrderedHashMap::HashTableStartIndex()));
    6554             :         Node* entry_key = etrue0 = graph()->NewNode(
    6555             :             simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
    6556         840 :             table, entry_start_position, etrue0, if_true0);
    6557             : 
    6558             :         // Advance the index.
    6559             :         index = graph()->NewNode(simplified()->NumberAdd(), index,
    6560         560 :                                  jsgraph()->OneConstant());
    6561             : 
    6562             :         Node* check1 =
    6563             :             graph()->NewNode(simplified()->ReferenceEqual(), entry_key,
    6564         560 :                              jsgraph()->TheHoleConstant());
    6565             :         Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
    6566         280 :                                          check1, if_true0);
    6567             : 
    6568             :         {
    6569             :           // Abort loop with resulting value.
    6570         280 :           Node* control = graph()->NewNode(common()->IfFalse(), branch1);
    6571             :           Node* effect = etrue0;
    6572             :           Node* value = effect =
    6573             :               graph()->NewNode(common()->TypeGuard(Type::NonInternal()),
    6574         280 :                                entry_key, effect, control);
    6575         280 :           Node* done = jsgraph()->FalseConstant();
    6576             : 
    6577             :           // Advance the index on the {receiver}.
    6578             :           effect = graph()->NewNode(
    6579             :               simplified()->StoreField(
    6580             :                   AccessBuilder::ForJSCollectionIteratorIndex()),
    6581         840 :               receiver, index, effect, control);
    6582             : 
    6583             :           // The actual {value} depends on the {receiver} iteration type.
    6584         280 :           switch (receiver_instance_type) {
    6585             :             case JS_MAP_KEY_ITERATOR_TYPE:
    6586             :             case JS_SET_VALUE_ITERATOR_TYPE:
    6587             :               break;
    6588             : 
    6589             :             case JS_SET_KEY_VALUE_ITERATOR_TYPE:
    6590             :               value = effect =
    6591             :                   graph()->NewNode(javascript()->CreateKeyValueArray(), value,
    6592          35 :                                    value, context, effect);
    6593          35 :               break;
    6594             : 
    6595             :             case JS_MAP_VALUE_ITERATOR_TYPE:
    6596             :               value = effect = graph()->NewNode(
    6597             :                   simplified()->LoadElement(
    6598             :                       AccessBuilder::ForFixedArrayElement()),
    6599             :                   table,
    6600             :                   graph()->NewNode(
    6601             :                       simplified()->NumberAdd(), entry_start_position,
    6602             :                       jsgraph()->Constant(OrderedHashMap::kValueOffset)),
    6603         175 :                   effect, control);
    6604          35 :               break;
    6605             : 
    6606             :             case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
    6607             :               value = effect = graph()->NewNode(
    6608             :                   simplified()->LoadElement(
    6609             :                       AccessBuilder::ForFixedArrayElement()),
    6610             :                   table,
    6611             :                   graph()->NewNode(
    6612             :                       simplified()->NumberAdd(), entry_start_position,
    6613             :                       jsgraph()->Constant(OrderedHashMap::kValueOffset)),
    6614         210 :                   effect, control);
    6615             :               value = effect =
    6616             :                   graph()->NewNode(javascript()->CreateKeyValueArray(),
    6617          42 :                                    entry_key, value, context, effect);
    6618          42 :               break;
    6619             : 
    6620             :             default:
    6621           0 :               UNREACHABLE();
    6622             :               break;
    6623             :           }
    6624             : 
    6625             :           // Store final {value} and {done} into the {iterator_result}.
    6626             :           effect =
    6627             :               graph()->NewNode(simplified()->StoreField(
    6628             :                                    AccessBuilder::ForJSIteratorResultValue()),
    6629         840 :                                iterator_result, value, effect, control);
    6630             :           effect =
    6631             :               graph()->NewNode(simplified()->StoreField(
    6632             :                                    AccessBuilder::ForJSIteratorResultDone()),
    6633         840 :                                iterator_result, done, effect, control);
    6634             : 
    6635         280 :           controls[1] = control;
    6636         280 :           effects[1] = effect;
    6637             :         }
    6638             : 
    6639             :         // Continue with next loop index.
    6640         560 :         loop->ReplaceInput(1, graph()->NewNode(common()->IfTrue(), branch1));
    6641         280 :         eloop->ReplaceInput(1, etrue0);
    6642         280 :         iloop->ReplaceInput(1, index);
    6643             :       }
    6644             :     }
    6645             : 
    6646         560 :     control = effects[2] = graph()->NewNode(common()->Merge(2), 2, controls);
    6647         560 :     effect = graph()->NewNode(common()->EffectPhi(2), 3, effects);
    6648             :   }
    6649             : 
    6650             :   // Yield the final {iterator_result}.
    6651         280 :   ReplaceWithValue(node, iterator_result, effect, control);
    6652             :   return Replace(iterator_result);
    6653             : }
    6654             : 
    6655          16 : Reduction JSCallReducer::ReduceArrayBufferIsView(Node* node) {
    6656          16 :   Node* value = node->op()->ValueInputCount() >= 3
    6657             :                     ? NodeProperties::GetValueInput(node, 2)
    6658          16 :                     : jsgraph()->UndefinedConstant();
    6659             :   RelaxEffectsAndControls(node);
    6660          16 :   node->ReplaceInput(0, value);
    6661          16 :   node->TrimInputCount(1);
    6662          16 :   NodeProperties::ChangeOp(node, simplified()->ObjectIsArrayBufferView());
    6663          16 :   return Changed(node);
    6664             : }
    6665             : 
    6666         308 : Reduction JSCallReducer::ReduceArrayBufferViewAccessor(
    6667        1005 :     Node* node, InstanceType instance_type, FieldAccess const& access) {
    6668         308 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6669         308 :   Node* effect = NodeProperties::GetEffectInput(node);
    6670         308 :   Node* control = NodeProperties::GetControlInput(node);
    6671             : 
    6672         308 :   if (NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
    6673         308 :                                              instance_type)) {
    6674             :     // Load the {receiver}s field.
    6675             :     Node* value = effect = graph()->NewNode(simplified()->LoadField(access),
    6676         308 :                                             receiver, effect, control);
    6677             : 
    6678             :     // See if we can skip the detaching check.
    6679         308 :     if (isolate()->IsArrayBufferDetachingIntact()) {
    6680             :       // Add a code dependency so we are deoptimized in case an ArrayBuffer
    6681             :       // gets detached.
    6682             :       dependencies()->DependOnProtector(PropertyCellRef(
    6683         227 :           broker(), factory()->array_buffer_detaching_protector()));
    6684             :     } else {
    6685             :       // Check whether {receiver}s JSArrayBuffer was detached.
    6686             :       Node* buffer = effect = graph()->NewNode(
    6687             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
    6688         243 :           receiver, effect, control);
    6689             :       Node* buffer_bit_field = effect = graph()->NewNode(
    6690             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
    6691         243 :           buffer, effect, control);
    6692             :       Node* check = graph()->NewNode(
    6693             :           simplified()->NumberEqual(),
    6694             :           graph()->NewNode(
    6695             :               simplified()->NumberBitwiseAnd(), buffer_bit_field,
    6696             :               jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
    6697         324 :           jsgraph()->ZeroConstant());
    6698             : 
    6699             :       // TODO(turbofan): Ideally we would bail out here if the {receiver}s
    6700             :       // JSArrayBuffer was detached, but there's no way to guard against
    6701             :       // deoptimization loops right now, since the JSCall {node} is usually
    6702             :       // created from a LOAD_IC inlining, and so there's no CALL_IC slot
    6703             :       // from which we could use the speculation bit.
    6704             :       value = graph()->NewNode(
    6705             :           common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
    6706         162 :           check, value, jsgraph()->ZeroConstant());
    6707             :     }
    6708             : 
    6709         308 :     ReplaceWithValue(node, value, effect, control);
    6710             :     return Replace(value);
    6711             :   }
    6712             :   return NoChange();
    6713             : }
    6714             : 
    6715             : namespace {
    6716         556 : uint32_t ExternalArrayElementSize(const ExternalArrayType element_type) {
    6717         556 :   switch (element_type) {
    6718             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
    6719             :   case kExternal##Type##Array:                    \
    6720             :     DCHECK_LE(sizeof(ctype), 8);                  \
    6721             :     return sizeof(ctype);
    6722          65 :     TYPED_ARRAYS(TYPED_ARRAY_CASE)
    6723             :     default:
    6724           0 :       UNREACHABLE();
    6725             : #undef TYPED_ARRAY_CASE
    6726             :   }
    6727             : }
    6728             : }  // namespace
    6729             : 
    6730        2466 : Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access,
    6731        2741 :                                               ExternalArrayType element_type) {
    6732         556 :   size_t const element_size = ExternalArrayElementSize(element_type);
    6733        1112 :   CallParameters const& p = CallParametersOf(node->op());
    6734         556 :   Node* effect = NodeProperties::GetEffectInput(node);
    6735         556 :   Node* control = NodeProperties::GetControlInput(node);
    6736         556 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6737         556 :   Node* offset = node->op()->ValueInputCount() > 2
    6738             :                      ? NodeProperties::GetValueInput(node, 2)
    6739         557 :                      : jsgraph()->ZeroConstant();
    6740             :   Node* value = (access == DataViewAccess::kGet)
    6741             :                     ? nullptr
    6742         242 :                     : (node->op()->ValueInputCount() > 3
    6743             :                            ? NodeProperties::GetValueInput(node, 3)
    6744         798 :                            : jsgraph()->ZeroConstant());
    6745             :   Node* is_little_endian = (access == DataViewAccess::kGet)
    6746         314 :                                ? (node->op()->ValueInputCount() > 3
    6747             :                                       ? NodeProperties::GetValueInput(node, 3)
    6748             :                                       : jsgraph()->FalseConstant())
    6749         242 :                                : (node->op()->ValueInputCount() > 4
    6750             :                                       ? NodeProperties::GetValueInput(node, 4)
    6751        1264 :                                       : jsgraph()->FalseConstant());
    6752             : 
    6753         556 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    6754             :     return NoChange();
    6755             :   }
    6756             : 
    6757             :   // Only do stuff if the {receiver} is really a DataView.
    6758         466 :   if (NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
    6759             :                                              JS_DATA_VIEW_TYPE)) {
    6760             :     Node* byte_offset;
    6761             : 
    6762             :     // Check that the {offset} is within range for the {receiver}.
    6763             :     HeapObjectMatcher m(receiver);
    6764         465 :     if (m.HasValue()) {
    6765             :       // We only deal with DataViews here whose [[ByteLength]] is at least
    6766             :       // {element_size}, as for all other DataViews it'll be out-of-bounds.
    6767         217 :       JSDataViewRef dataview = m.Ref(broker()).AsJSDataView();
    6768         217 :       if (dataview.byte_length() < element_size) return NoChange();
    6769             : 
    6770             :       // Check that the {offset} is within range of the {byte_length}.
    6771             :       Node* byte_length =
    6772         434 :           jsgraph()->Constant(dataview.byte_length() - (element_size - 1));
    6773             :       offset = effect =
    6774         217 :           graph()->NewNode(simplified()->CheckBounds(p.feedback()), offset,
    6775         217 :                            byte_length, effect, control);
    6776             : 
    6777             :       // Load the [[ByteOffset]] from the {dataview}.
    6778         434 :       byte_offset = jsgraph()->Constant(dataview.byte_offset());
    6779             :     } else {
    6780             :       // We only deal with DataViews here that have Smi [[ByteLength]]s.
    6781             :       Node* byte_length = effect =
    6782             :           graph()->NewNode(simplified()->LoadField(
    6783             :                                AccessBuilder::ForJSArrayBufferViewByteLength()),
    6784         744 :                            receiver, effect, control);
    6785             : 
    6786         248 :       if (element_size > 1) {
    6787             :         // For non-byte accesses we also need to check that the {offset}
    6788             :         // plus the {element_size}-1 fits within the given {byte_length}.
    6789             :         // So to keep this as a single check on the {offset}, we subtract
    6790             :         // the {element_size}-1 from the {byte_length} here (clamped to
    6791             :         // positive safe integer range), and perform a check against that
    6792             :         // with the {offset} below.
    6793             :         byte_length = graph()->NewNode(
    6794             :             simplified()->NumberMax(), jsgraph()->ZeroConstant(),
    6795             :             graph()->NewNode(simplified()->NumberSubtract(), byte_length,
    6796         860 :                              jsgraph()->Constant(element_size - 1)));
    6797             :       }
    6798             : 
    6799             :       // Check that the {offset} is within range of the {byte_length}.
    6800             :       offset = effect =
    6801         248 :           graph()->NewNode(simplified()->CheckBounds(p.feedback()), offset,
    6802         248 :                            byte_length, effect, control);
    6803             : 
    6804             :       // Also load the [[ByteOffset]] from the {receiver}.
    6805             :       byte_offset = effect =
    6806             :           graph()->NewNode(simplified()->LoadField(
    6807             :                                AccessBuilder::ForJSArrayBufferViewByteOffset()),
    6808         744 :                            receiver, effect, control);
    6809             :     }
    6810             : 
    6811             :     // Coerce {is_little_endian} to boolean.
    6812             :     is_little_endian =
    6813         465 :         graph()->NewNode(simplified()->ToBoolean(), is_little_endian);
    6814             : 
    6815             :     // Coerce {value} to Number.
    6816         465 :     if (access == DataViewAccess::kSet) {
    6817             :       value = effect = graph()->NewNode(
    6818             :           simplified()->SpeculativeToNumber(
    6819         197 :               NumberOperationHint::kNumberOrOddball, p.feedback()),
    6820         197 :           value, effect, control);
    6821             :     }
    6822             : 
    6823             :     // Get the underlying buffer and check that it has not been detached.
    6824             :     Node* buffer = effect = graph()->NewNode(
    6825             :         simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
    6826        1395 :         receiver, effect, control);
    6827             : 
    6828         465 :     if (isolate()->IsArrayBufferDetachingIntact()) {
    6829             :       // Add a code dependency so we are deoptimized in case an ArrayBuffer
    6830             :       // gets detached.
    6831             :       dependencies()->DependOnProtector(PropertyCellRef(
    6832         385 :           broker(), factory()->array_buffer_detaching_protector()));
    6833             :     } else {
    6834             :       // Bail out if the {buffer} was detached.
    6835             :       Node* buffer_bit_field = effect = graph()->NewNode(
    6836             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
    6837         240 :           buffer, effect, control);
    6838             :       Node* check = graph()->NewNode(
    6839             :           simplified()->NumberEqual(),
    6840             :           graph()->NewNode(
    6841             :               simplified()->NumberBitwiseAnd(), buffer_bit_field,
    6842             :               jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
    6843         320 :           jsgraph()->ZeroConstant());
    6844             :       effect = graph()->NewNode(
    6845             :           simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached,
    6846          80 :                                 p.feedback()),
    6847          80 :           check, effect, control);
    6848             :     }
    6849             : 
    6850             :     // Get the buffer's backing store.
    6851             :     Node* backing_store = effect = graph()->NewNode(
    6852             :         simplified()->LoadField(AccessBuilder::ForJSArrayBufferBackingStore()),
    6853        1395 :         buffer, effect, control);
    6854             : 
    6855         465 :     switch (access) {
    6856             :       case DataViewAccess::kGet:
    6857             :         // Perform the load.
    6858             :         value = effect =
    6859             :             graph()->NewNode(simplified()->LoadDataViewElement(element_type),
    6860             :                              buffer, backing_store, byte_offset, offset,
    6861         268 :                              is_little_endian, effect, control);
    6862         268 :         break;
    6863             :       case DataViewAccess::kSet:
    6864             :         // Perform the store.
    6865             :         effect =
    6866             :             graph()->NewNode(simplified()->StoreDataViewElement(element_type),
    6867             :                              buffer, backing_store, byte_offset, offset, value,
    6868         197 :                              is_little_endian, effect, control);
    6869         197 :         value = jsgraph()->UndefinedConstant();
    6870         197 :         break;
    6871             :     }
    6872             : 
    6873             :     // Continue on the regular path.
    6874         465 :     ReplaceWithValue(node, value, effect, control);
    6875             :     return Changed(value);
    6876             :   }
    6877             : 
    6878             :   return NoChange();
    6879             : }
    6880             : 
    6881             : // ES6 section 18.2.2 isFinite ( number )
    6882          78 : Reduction JSCallReducer::ReduceGlobalIsFinite(Node* node) {
    6883          42 :   CallParameters const& p = CallParametersOf(node->op());
    6884          42 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    6885             :     return NoChange();
    6886             :   }
    6887          72 :   if (node->op()->ValueInputCount() < 3) {
    6888           0 :     Node* value = jsgraph()->FalseConstant();
    6889          36 :     ReplaceWithValue(node, value);
    6890             :     return Replace(value);
    6891             :   }
    6892             : 
    6893          36 :   Node* effect = NodeProperties::GetEffectInput(node);
    6894          36 :   Node* control = NodeProperties::GetControlInput(node);
    6895          36 :   Node* input = NodeProperties::GetValueInput(node, 2);
    6896             : 
    6897             :   input = effect =
    6898             :       graph()->NewNode(simplified()->SpeculativeToNumber(
    6899          36 :                            NumberOperationHint::kNumberOrOddball, p.feedback()),
    6900          36 :                        input, effect, control);
    6901          36 :   Node* value = graph()->NewNode(simplified()->NumberIsFinite(), input);
    6902             :   ReplaceWithValue(node, value, effect);
    6903             :   return Replace(value);
    6904             : }
    6905             : 
    6906             : // ES6 section 18.2.3 isNaN ( number )
    6907       28269 : Reduction JSCallReducer::ReduceGlobalIsNaN(Node* node) {
    6908       14210 :   CallParameters const& p = CallParametersOf(node->op());
    6909       14210 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    6910             :     return NoChange();
    6911             :   }
    6912       28116 :   if (node->op()->ValueInputCount() < 3) {
    6913           1 :     Node* value = jsgraph()->TrueConstant();
    6914       14058 :     ReplaceWithValue(node, value);
    6915             :     return Replace(value);
    6916             :   }
    6917             : 
    6918       14057 :   Node* effect = NodeProperties::GetEffectInput(node);
    6919       14057 :   Node* control = NodeProperties::GetControlInput(node);
    6920       14057 :   Node* input = NodeProperties::GetValueInput(node, 2);
    6921             : 
    6922             :   input = effect =
    6923             :       graph()->NewNode(simplified()->SpeculativeToNumber(
    6924       14057 :                            NumberOperationHint::kNumberOrOddball, p.feedback()),
    6925       14057 :                        input, effect, control);
    6926       14057 :   Node* value = graph()->NewNode(simplified()->NumberIsNaN(), input);
    6927             :   ReplaceWithValue(node, value, effect);
    6928             :   return Replace(value);
    6929             : }
    6930             : 
    6931             : // ES6 section 20.3.4.10 Date.prototype.getTime ( )
    6932           0 : Reduction JSCallReducer::ReduceDatePrototypeGetTime(Node* node) {
    6933           0 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    6934           0 :   Node* effect = NodeProperties::GetEffectInput(node);
    6935           0 :   Node* control = NodeProperties::GetControlInput(node);
    6936           0 :   if (NodeProperties::HasInstanceTypeWitness(broker(), receiver, effect,
    6937             :                                              JS_DATE_TYPE)) {
    6938             :     Node* value = effect = graph()->NewNode(
    6939             :         simplified()->LoadField(AccessBuilder::ForJSDateValue()), receiver,
    6940           0 :         effect, control);
    6941           0 :     ReplaceWithValue(node, value, effect, control);
    6942             :     return Replace(value);
    6943             :   }
    6944             :   return NoChange();
    6945             : }
    6946             : 
    6947             : // ES6 section 20.3.3.1 Date.now ( )
    6948           7 : Reduction JSCallReducer::ReduceDateNow(Node* node) {
    6949           7 :   Node* effect = NodeProperties::GetEffectInput(node);
    6950           7 :   Node* control = NodeProperties::GetControlInput(node);
    6951             :   Node* value = effect =
    6952           7 :       graph()->NewNode(simplified()->DateNow(), effect, control);
    6953           7 :   ReplaceWithValue(node, value, effect, control);
    6954           7 :   return Replace(value);
    6955             : }
    6956             : 
    6957             : // ES6 section 20.1.2.13 Number.parseInt ( string, radix )
    6958        1087 : Reduction JSCallReducer::ReduceNumberParseInt(Node* node) {
    6959             :   // We certainly know that undefined is not an array.
    6960        1152 :   if (node->op()->ValueInputCount() < 3) {
    6961           1 :     Node* value = jsgraph()->NaNConstant();
    6962           1 :     ReplaceWithValue(node, value);
    6963             :     return Replace(value);
    6964             :   }
    6965             : 
    6966             :   int arg_count = node->op()->ValueInputCount();
    6967         575 :   Node* effect = NodeProperties::GetEffectInput(node);
    6968         575 :   Node* control = NodeProperties::GetControlInput(node);
    6969         575 :   Node* context = NodeProperties::GetContextInput(node);
    6970         575 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    6971         575 :   Node* object = NodeProperties::GetValueInput(node, 2);
    6972             :   Node* radix = arg_count >= 4 ? NodeProperties::GetValueInput(node, 3)
    6973        1085 :                                : jsgraph()->UndefinedConstant();
    6974         575 :   node->ReplaceInput(0, object);
    6975         575 :   node->ReplaceInput(1, radix);
    6976         575 :   node->ReplaceInput(2, context);
    6977         575 :   node->ReplaceInput(3, frame_state);
    6978         575 :   node->ReplaceInput(4, effect);
    6979         575 :   node->ReplaceInput(5, control);
    6980         575 :   node->TrimInputCount(6);
    6981         575 :   NodeProperties::ChangeOp(node, javascript()->ParseInt());
    6982             :   return Changed(node);
    6983             : }
    6984             : 
    6985        4083 : Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
    6986         513 :   if (FLAG_force_slow_path) return NoChange();
    6987        1026 :   if (node->op()->ValueInputCount() < 3) return NoChange();
    6988         513 :   CallParameters const& p = CallParametersOf(node->op());
    6989         513 :   if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    6990             :     return NoChange();
    6991             :   }
    6992             : 
    6993         513 :   Node* effect = NodeProperties::GetEffectInput(node);
    6994         513 :   Node* control = NodeProperties::GetControlInput(node);
    6995         513 :   Node* regexp = NodeProperties::GetValueInput(node, 1);
    6996             : 
    6997             :   // Check if we know something about the {regexp}.
    6998             :   ZoneHandleSet<Map> regexp_maps;
    6999             :   NodeProperties::InferReceiverMapsResult result =
    7000         513 :       NodeProperties::InferReceiverMaps(broker(), regexp, effect, &regexp_maps);
    7001             : 
    7002             :   bool need_map_check = false;
    7003         513 :   switch (result) {
    7004             :     case NodeProperties::kNoReceiverMaps:
    7005             :       return NoChange();
    7006             :     case NodeProperties::kUnreliableReceiverMaps:
    7007             :       need_map_check = true;
    7008          11 :       break;
    7009             :     case NodeProperties::kReliableReceiverMaps:
    7010             :       break;
    7011             :   }
    7012             : 
    7013        1026 :   for (auto map : regexp_maps) {
    7014             :     MapRef receiver_map(broker(), map);
    7015         513 :     if (receiver_map.instance_type() != JS_REGEXP_TYPE) return NoChange();
    7016             :   }
    7017             : 
    7018             :   // Compute property access info for "exec" on {resolution}.
    7019         513 :   PropertyAccessInfo ai_exec;
    7020             :   AccessInfoFactory access_info_factory(
    7021        1539 :       broker(), dependencies(), native_context().object(), graph()->zone());
    7022         513 :   if (!access_info_factory.ComputePropertyAccessInfo(
    7023             :           MapHandles(regexp_maps.begin(), regexp_maps.end()),
    7024        1026 :           factory()->exec_string(), AccessMode::kLoad, &ai_exec)) {
    7025             :     return NoChange();
    7026             :   }
    7027             :   // If "exec" has been modified on {regexp}, we can't do anything.
    7028         513 :   if (ai_exec.IsDataConstant()) {
    7029         513 :     if (!ai_exec.constant().is_identical_to(
    7030        1026 :             isolate()->regexp_exec_function())) {
    7031             :       return NoChange();
    7032             :     }
    7033           0 :   } else if (ai_exec.IsDataConstantField()) {
    7034             :     Handle<JSObject> holder;
    7035             :     // Do not reduce if the exec method is not on the prototype chain.
    7036           0 :     if (!ai_exec.holder().ToHandle(&holder)) return NoChange();
    7037             : 
    7038             :     // Bail out if the exec method is not the original one.
    7039             :     Handle<Object> constant = JSObject::FastPropertyAt(
    7040           0 :         holder, Representation::Tagged(), ai_exec.field_index());
    7041           0 :     if (!constant.is_identical_to(isolate()->regexp_exec_function())) {
    7042             :       return NoChange();
    7043             :     }
    7044             : 
    7045             :     // Protect the prototype chain from changes.
    7046             :     dependencies()->DependOnStablePrototypeChains(
    7047           0 :         broker(), ai_exec.receiver_maps(), JSObjectRef(broker(), holder));
    7048             : 
    7049             :     // Protect the exec method change in the holder.
    7050             :     Handle<Object> exec_on_proto;
    7051             :     Handle<Map> holder_map(holder->map(), isolate());
    7052             :     Handle<DescriptorArray> descriptors(holder_map->instance_descriptors(),
    7053           0 :                                         isolate());
    7054             :     int descriptor_index =
    7055           0 :         descriptors->Search(*(factory()->exec_string()), *holder_map);
    7056           0 :     CHECK_NE(descriptor_index, DescriptorArray::kNotFound);
    7057             : 
    7058             :     dependencies()->DependOnFieldType(MapRef(broker(), holder_map),
    7059           0 :                                       descriptor_index);
    7060             :   } else {
    7061             :     return NoChange();
    7062             :   }
    7063             : 
    7064             :   PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
    7065             : 
    7066             :   // Add proper dependencies on the {regexp}s [[Prototype]]s.
    7067             :   Handle<JSObject> holder;
    7068         506 :   if (ai_exec.holder().ToHandle(&holder)) {
    7069             :     dependencies()->DependOnStablePrototypeChains(
    7070         506 :         broker(), ai_exec.receiver_maps(), JSObjectRef(broker(), holder));
    7071             :   }
    7072             : 
    7073         506 :   if (need_map_check) {
    7074             :     effect =
    7075             :         graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
    7076           4 :                                                  regexp_maps, p.feedback()),
    7077           8 :                          regexp, effect, control);
    7078             :   }
    7079             : 
    7080         506 :   Node* context = NodeProperties::GetContextInput(node);
    7081         506 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    7082         506 :   Node* search = NodeProperties::GetValueInput(node, 2);
    7083             :   Node* search_string = effect = graph()->NewNode(
    7084        1012 :       simplified()->CheckString(p.feedback()), search, effect, control);
    7085             : 
    7086             :   Node* lastIndex = effect = graph()->NewNode(
    7087             :       simplified()->LoadField(AccessBuilder::ForJSRegExpLastIndex()), regexp,
    7088        1518 :       effect, control);
    7089             : 
    7090             :   Node* lastIndexSmi = effect = graph()->NewNode(
    7091         506 :       simplified()->CheckSmi(p.feedback()), lastIndex, effect, control);
    7092             : 
    7093             :   Node* is_positive = graph()->NewNode(simplified()->NumberLessThanOrEqual(),
    7094        1012 :                                        jsgraph()->ZeroConstant(), lastIndexSmi);
    7095             : 
    7096             :   effect = graph()->NewNode(
    7097             :       simplified()->CheckIf(DeoptimizeReason::kNotASmi, p.feedback()),
    7098         506 :       is_positive, effect, control);
    7099             : 
    7100         506 :   node->ReplaceInput(0, regexp);
    7101         506 :   node->ReplaceInput(1, search_string);
    7102         506 :   node->ReplaceInput(2, context);
    7103         506 :   node->ReplaceInput(3, frame_state);
    7104         506 :   node->ReplaceInput(4, effect);
    7105         506 :   node->ReplaceInput(5, control);
    7106         506 :   node->TrimInputCount(6);
    7107         506 :   NodeProperties::ChangeOp(node, javascript()->RegExpTest());
    7108             :   return Changed(node);
    7109             : }
    7110             : 
    7111             : // ES section #sec-number-constructor
    7112        1011 : Reduction JSCallReducer::ReduceNumberConstructor(Node* node) {
    7113             :   DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    7114        1010 :   CallParameters const& p = CallParametersOf(node->op());
    7115         505 :   Node* target = NodeProperties::GetValueInput(node, 0);
    7116         505 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
    7117             :   Node* value = p.arity() < 3 ? jsgraph()->ZeroConstant()
    7118         506 :                               : NodeProperties::GetValueInput(node, 2);
    7119         505 :   Node* context = NodeProperties::GetContextInput(node);
    7120         505 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    7121             : 
    7122             :   // Create the artificial frame state in the middle of the Number constructor.
    7123             :   SharedFunctionInfoRef shared_info =
    7124         505 :       native_context().number_function().shared();
    7125         505 :   Node* stack_parameters[] = {receiver};
    7126             :   int stack_parameter_count = arraysize(stack_parameters);
    7127             :   Node* continuation_frame_state =
    7128             :       CreateJavaScriptBuiltinContinuationFrameState(
    7129             :           jsgraph(), shared_info,
    7130             :           Builtins::kGenericConstructorLazyDeoptContinuation, target, context,
    7131             :           stack_parameters, stack_parameter_count, frame_state,
    7132         505 :           ContinuationFrameStateMode::LAZY);
    7133             : 
    7134             :   // Convert the {value} to a Number.
    7135         505 :   NodeProperties::ReplaceValueInputs(node, value);
    7136         505 :   NodeProperties::ChangeOp(node, javascript()->ToNumberConvertBigInt());
    7137         505 :   NodeProperties::ReplaceFrameStateInput(node, continuation_frame_state);
    7138         505 :   return Changed(node);
    7139             : }
    7140             : 
    7141      419602 : Graph* JSCallReducer::graph() const { return jsgraph()->graph(); }
    7142             : 
    7143       68148 : Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }
    7144             : 
    7145           0 : Factory* JSCallReducer::factory() const { return isolate()->factory(); }
    7146             : 
    7147       89165 : CommonOperatorBuilder* JSCallReducer::common() const {
    7148       89165 :   return jsgraph()->common();
    7149             : }
    7150             : 
    7151       18437 : JSOperatorBuilder* JSCallReducer::javascript() const {
    7152       18437 :   return jsgraph()->javascript();
    7153             : }
    7154             : 
    7155      270069 : SimplifiedOperatorBuilder* JSCallReducer::simplified() const {
    7156      270090 :   return jsgraph()->simplified();
    7157             : }
    7158             : 
    7159             : }  // namespace compiler
    7160             : }  // namespace internal
    7161      183867 : }  // namespace v8

Generated by: LCOV version 1.10