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