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

Generated by: LCOV version 1.10