LCOV - code coverage report
Current view: top level - src/compiler - js-call-reducer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2676 2777 96.4 %
Date: 2019-03-21 Functions: 110 118 93.2 %

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

Generated by: LCOV version 1.10