LCOV - code coverage report
Current view: top level - src/compiler - js-call-reducer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2682 2760 97.2 %
Date: 2019-04-18 Functions: 113 119 95.0 %

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

Generated by: LCOV version 1.10