1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file.
4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/js-call-reducer.h"
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/code-factory.h"
862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/code-stubs.h"
962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/compilation-dependencies.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/js-graph.h"
1162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/compiler/linkage.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/node-matchers.h"
13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/compiler/simplified-operator.h"
1462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/feedback-vector-inl.h"
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects-inl.h"
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 {
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal {
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace compiler {
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSCallReducer::Reduce(Node* node) {
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (node->opcode()) {
2362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSConstruct:
2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return ReduceJSConstruct(node);
2562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSConstructWithSpread:
2662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return ReduceJSConstructWithSpread(node);
2762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCall:
2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return ReduceJSCall(node);
2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCallWithSpread:
3062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return ReduceJSCallWithSpread(node);
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    default:
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      break;
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return NoChange();
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ES6 section 22.1.1 The Array Constructor
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSCallReducer::ReduceArrayConstructor(Node* node) {
4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* target = NodeProperties::GetValueInput(node, 0);
4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallParameters const& p = CallParametersOf(node->op());
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check if we have an allocation site from the CallIC.
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<AllocationSite> site;
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (p.feedback().IsValid()) {
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<Object> feedback(nexus.GetFeedback(), isolate());
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (feedback->IsAllocationSite()) {
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      site = Handle<AllocationSite>::cast(feedback);
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Turn the {node} into a {JSCreateArray} call.
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(2u, p.arity());
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t const arity = p.arity() - 2;
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ReplaceValueInput(node, target, 0);
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ReplaceValueInput(node, target, 1);
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(bmeurer): We might need to propagate the tail call mode to
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the JSCreateArray operator, because an Array call in tail call
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // position must always properly consume the parent stack frame.
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site));
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Changed(node);
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ES6 section 20.1.1 The Number Constructor
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSCallReducer::ReduceNumberConstructor(Node* node) {
6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallParameters const& p = CallParametersOf(node->op());
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Turn the {node} into a {JSToNumber} call.
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(2u, p.arity());
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* value = (p.arity() == 2) ? jsgraph()->ZeroConstant()
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 : NodeProperties::GetValueInput(node, 2);
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ReplaceValueInputs(node, value);
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ChangeOp(node, javascript()->ToNumber());
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Changed(node);
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* target = NodeProperties::GetValueInput(node, 0);
8662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallParameters const& p = CallParametersOf(node->op());
8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Tail calls to Function.prototype.apply are not properly supported
8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // down the pipeline, so we disable this optimization completely for
8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // tail calls (for now).
9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (p.tail_call_mode() == TailCallMode::kAllow) return NoChange();
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<JSFunction> apply =
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<JSFunction>::cast(HeapObjectMatcher(target).Value());
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t arity = p.arity();
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(2u, arity);
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny;
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (arity == 2) {
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Neither thisArg nor argArray was provided.
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNullOrUndefined;
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->ReplaceInput(0, node->InputAt(1));
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->ReplaceInput(1, jsgraph()->UndefinedConstant());
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (arity == 3) {
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // The argArray was not provided, just remove the {target}.
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->RemoveInput(0);
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    --arity;
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (arity == 4) {
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check if argArray is an arguments object, and {node} is the only value
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // user of argArray (except for value uses in frame states).
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* arg_array = NodeProperties::GetValueInput(node, 3);
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (arg_array->opcode() != IrOpcode::kJSCreateArguments) return NoChange();
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (Edge edge : arg_array->use_edges()) {
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (edge.from()->opcode() == IrOpcode::kStateValues) continue;
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!NodeProperties::IsValueEdge(edge)) continue;
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (edge.from() == node) continue;
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return NoChange();
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Check if the arguments can be handled in the fast case (i.e. we don't
11762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // have aliased sloppy arguments), and compute the {start_index} for
11862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // rest parameters.
11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CreateArgumentsType const type = CreateArgumentsTypeOf(arg_array->op());
12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* frame_state = NodeProperties::GetFrameStateInput(arg_array);
12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    int formal_parameter_count;
12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    int start_index = 0;
12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    {
12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Handle<SharedFunctionInfo> shared;
12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      formal_parameter_count = shared->internal_formal_parameter_count();
12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (type == CreateArgumentsType::kMappedArguments) {
13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Mapped arguments (sloppy mode) cannot be handled if they are aliased.
13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (formal_parameter_count != 0) return NoChange();
13262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    } else if (type == CreateArgumentsType::kRestParameter) {
13362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      start_index = formal_parameter_count;
13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
13562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Check if are applying to inlined arguments or to the arguments of
13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // the outermost function.
13762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
13862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (outer_state->opcode() != IrOpcode::kFrameState) {
13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // TODO(jarin,bmeurer): Support the NewUnmappedArgumentsElement and
14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // NewRestParameterElements in the EscapeAnalysis and Deoptimizer
14162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // instead, then we don't need this hack.
14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Only works with zero formal parameters because of lacking deoptimizer
14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // support.
14462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (type != CreateArgumentsType::kRestParameter &&
14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          formal_parameter_count == 0) {
14662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // There are no other uses of the {arg_array} except in StateValues,
14762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // so we just replace {arg_array} with a marker for the Deoptimizer
14862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // that this refers to the arguments object.
14962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* arguments = graph()->NewNode(common()->ArgumentsObjectState());
15062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        ReplaceWithValue(arg_array, arguments);
15162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
15262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
15362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Reduce {node} to a JSCallForwardVarargs operation, which just
15462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // re-pushes the incoming arguments and calls the {target}.
15562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      node->RemoveInput(0);  // Function.prototype.apply
15662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      node->RemoveInput(2);  // arguments
15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      NodeProperties::ChangeOp(node, javascript()->CallForwardVarargs(
15862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                         start_index, p.tail_call_mode()));
15962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return Changed(node);
16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Get to the actual frame state from which to extract the arguments;
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // we can only optimize this in case the {node} was already inlined into
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // some other function (and same for the {arg_array}).
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameStateInfo outer_info = OpParameter<FrameStateInfo>(outer_state);
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Need to take the parameters from the arguments adaptor.
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      frame_state = outer_state;
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Remove the argArray input from the {node}.
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->RemoveInput(static_cast<int>(--arity));
17162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Add the actual parameters to the {node}, skipping the receiver,
17262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // starting from {start_index}.
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
17462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    for (int i = start_index + 1; i < parameters->InputCount(); ++i) {
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node->InsertInput(graph()->zone(), static_cast<int>(arity),
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        parameters->InputAt(i));
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ++arity;
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Drop the {target} from the {node}.
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->RemoveInput(0);
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    --arity;
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return NoChange();
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
18562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Change {node} to the new {JSCall} operator.
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ChangeOp(
18762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      node,
18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      javascript()->Call(arity, p.frequency(), VectorSlotPair(), convert_mode,
18962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                         p.tail_call_mode()));
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Change context of {node} to the Function.prototype.apply context,
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to ensure any exception is thrown in the correct context.
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ReplaceContextInput(
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node, jsgraph()->HeapConstant(handle(apply->context(), isolate())));
19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Try to further reduce the JSCall {node}.
19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Reduction const reduction = ReduceJSCall(node);
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return reduction.Changed() ? reduction : Changed(node);
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args)
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
20262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallParameters const& p = CallParametersOf(node->op());
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<JSFunction> call = Handle<JSFunction>::cast(
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      HeapObjectMatcher(NodeProperties::GetValueInput(node, 0)).Value());
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Change context of {node} to the Function.prototype.call context,
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to ensure any exception is thrown in the correct context.
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ReplaceContextInput(
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      node, jsgraph()->HeapConstant(handle(call->context(), isolate())));
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Remove the target from {node} and use the receiver as target instead, and
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the thisArg becomes the new target.  If thisArg was not provided, insert
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // undefined instead.
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t arity = p.arity();
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(2u, arity);
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConvertReceiverMode convert_mode;
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (arity == 2) {
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // The thisArg was not provided, use undefined as receiver.
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kNullOrUndefined;
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->ReplaceInput(0, node->InputAt(1));
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->ReplaceInput(1, jsgraph()->UndefinedConstant());
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Just remove the target, which is the first value input.
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    convert_mode = ConvertReceiverMode::kAny;
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    node->RemoveInput(0);
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    --arity;
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeProperties::ChangeOp(
22862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      node,
22962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      javascript()->Call(arity, p.frequency(), VectorSlotPair(), convert_mode,
23062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                         p.tail_call_mode()));
23162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Try to further reduce the JSCall {node}.
23262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Reduction const reduction = ReduceJSCall(node);
233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return reduction.Changed() ? reduction : Changed(node);
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
23662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] (V)
23762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochReduction JSCallReducer::ReduceFunctionPrototypeHasInstance(Node* node) {
23862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
23962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* receiver = NodeProperties::GetValueInput(node, 1);
24062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* object = (node->op()->ValueInputCount() >= 3)
24162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     ? NodeProperties::GetValueInput(node, 2)
24262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     : jsgraph()->UndefinedConstant();
24362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = NodeProperties::GetContextInput(node);
24462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* frame_state = NodeProperties::GetFrameStateInput(node);
24562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
24662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* control = NodeProperties::GetControlInput(node);
24762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
24862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(turbofan): If JSOrdinaryToInstance raises an exception, the
24962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // stack trace doesn't contain the @@hasInstance call; we have the
25062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // corresponding bug in the baseline case. Some massaging of the frame
25162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // state would be necessary here.
25262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
25362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Morph this {node} into a JSOrdinaryHasInstance node.
25462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->ReplaceInput(0, receiver);
25562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->ReplaceInput(1, object);
25662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->ReplaceInput(2, context);
25762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->ReplaceInput(3, frame_state);
25862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->ReplaceInput(4, effect);
25962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->ReplaceInput(5, control);
26062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->TrimInputCount(6);
26162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
26262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Changed(node);
26362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
26462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
265c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochnamespace {
266c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
26762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool CanInlineApiCall(Isolate* isolate, Node* node,
26862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      Handle<FunctionTemplateInfo> function_template_info) {
26962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(node->opcode() == IrOpcode::kJSCall);
27062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
27162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (function_template_info->call_code()->IsUndefined(isolate)) {
27262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return false;
27362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
27462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallParameters const& params = CallParametersOf(node->op());
27562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // CallApiCallbackStub expects the target in a register, so we count it out,
27662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // and counts the receiver as an implicit argument, so we count the receiver
27762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // out too.
27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int const argc = static_cast<int>(params.arity()) - 2;
27962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (argc > CallApiCallbackStub::kArgMax || !params.feedback().IsValid()) {
28062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return false;
281c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
28262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HeapObjectMatcher receiver(NodeProperties::GetValueInput(node, 1));
28362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!receiver.HasValue()) {
28462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return false;
28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
28662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return receiver.Value()->IsUndefined(isolate) ||
28762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         (receiver.Value()->map()->IsJSObjectMap() &&
28862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          !receiver.Value()->map()->is_access_check_needed());
289c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
290c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
29162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}  // namespace
29262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
29362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochJSCallReducer::HolderLookup JSCallReducer::LookupHolder(
29462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<JSObject> object,
29562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<FunctionTemplateInfo> function_template_info,
29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<JSObject>* holder) {
29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(object->map()->IsJSObjectMap());
29862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Map> object_map(object->map());
29962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<FunctionTemplateInfo> expected_receiver_type;
30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!function_template_info->signature()->IsUndefined(isolate())) {
30162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    expected_receiver_type =
30262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        handle(FunctionTemplateInfo::cast(function_template_info->signature()));
30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
30462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (expected_receiver_type.is_null() ||
30562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      expected_receiver_type->IsTemplateFor(*object_map)) {
30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    *holder = Handle<JSObject>::null();
30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return kHolderIsReceiver;
30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
30962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  while (object_map->has_hidden_prototype()) {
31062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    object_map = handle(prototype->map());
31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (expected_receiver_type->IsTemplateFor(*object_map)) {
31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      *holder = prototype;
31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return kHolderFound;
315c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
316c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return kHolderNotFound;
318c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
319c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
320c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// ES6 section B.2.2.1.1 get Object.prototype.__proto__
321c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochReduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) {
32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
32362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* receiver = NodeProperties::GetValueInput(node, 1);
32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
325c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
326c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Try to determine the {receiver} map.
32762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ZoneHandleSet<Map> receiver_maps;
32862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  NodeProperties::InferReceiverMapsResult result =
32962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps);
33062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (result == NodeProperties::kReliableReceiverMaps) {
33162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Map> candidate_map(
33262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        receiver_maps[0]->GetPrototypeChainRootMap(isolate()));
33362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Object> candidate_prototype(candidate_map->prototype(), isolate());
33462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
33562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Check if we can constant-fold the {candidate_prototype}.
33662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    for (size_t i = 0; i < receiver_maps.size(); ++i) {
33762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Handle<Map> const receiver_map(
33862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          receiver_maps[i]->GetPrototypeChainRootMap(isolate()));
33962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (receiver_map->IsJSProxyMap() ||
34062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          receiver_map->has_hidden_prototype() ||
34162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          receiver_map->is_access_check_needed() ||
34262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          receiver_map->prototype() != *candidate_prototype) {
34362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return NoChange();
34462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
345c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
34662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value = jsgraph()->Constant(candidate_prototype);
34762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ReplaceWithValue(node, value);
34862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Replace(value);
349c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
350c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
351c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return NoChange();
352c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
35462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochReduction JSCallReducer::ReduceCallApiFunction(
35562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* node, Node* target,
35662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<FunctionTemplateInfo> function_template_info) {
35762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Isolate* isolate = this->isolate();
35862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CHECK(!isolate->serializer_enabled());
35962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HeapObjectMatcher m(target);
36062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(m.HasValue() && m.Value()->IsJSFunction());
36162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!CanInlineApiCall(isolate, node, function_template_info)) {
36262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return NoChange();
36362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
36462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<CallHandlerInfo> call_handler_info(
36562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      handle(CallHandlerInfo::cast(function_template_info->call_code())));
36662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> data(call_handler_info->data(), isolate);
36762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
36862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* receiver_node = NodeProperties::GetValueInput(node, 1);
36962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallParameters const& params = CallParametersOf(node->op());
37062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
37162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<HeapObject> receiver = HeapObjectMatcher(receiver_node).Value();
37262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool const receiver_is_undefined = receiver->IsUndefined(isolate);
37362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (receiver_is_undefined) {
37462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    receiver = handle(Handle<JSFunction>::cast(m.Value())->global_proxy());
37562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
37662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(receiver->map()->IsJSObjectMap() &&
37762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch           !receiver->map()->is_access_check_needed());
37862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
37962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
38062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<JSObject> holder;
38162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HolderLookup lookup = LookupHolder(Handle<JSObject>::cast(receiver),
38262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                     function_template_info, &holder);
38362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (lookup == kHolderNotFound) return NoChange();
38462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (receiver_is_undefined) {
38562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    receiver_node = jsgraph()->HeapConstant(receiver);
38662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    NodeProperties::ReplaceValueInput(node, receiver_node, 1);
38762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
38862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* holder_node =
38962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      lookup == kHolderFound ? jsgraph()->HeapConstant(holder) : receiver_node;
39062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
39162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Zone* zone = graph()->zone();
39262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Same as CanInlineApiCall: exclude the target (which goes in a register) and
39362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // the receiver (which is implicitly counted by CallApiCallbackStub) from the
39462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // arguments count.
39562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int const argc = static_cast<int>(params.arity() - 2);
39662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallApiCallbackStub stub(isolate, argc, data->IsUndefined(isolate), false);
39762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallInterfaceDescriptor cid = stub.GetCallInterfaceDescriptor();
39862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
39962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate, zone, cid,
40062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      cid.GetStackParameterCount() + argc + 1 /* implicit receiver */,
40162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CallDescriptor::kNeedsFrameState, Operator::kNoProperties,
40262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      MachineType::AnyTagged(), 1);
40362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ApiFunction api_function(v8::ToCData<Address>(call_handler_info->callback()));
40462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ExternalReference function_reference(
40562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      &api_function, ExternalReference::DIRECT_API_CALL, isolate);
40662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
40762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // CallApiCallbackStub's register arguments: code, target, call data, holder,
40862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // function address.
40962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->InsertInput(zone, 0, jsgraph()->HeapConstant(stub.GetCode()));
41062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->InsertInput(zone, 2, jsgraph()->Constant(data));
41162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->InsertInput(zone, 3, holder_node);
41262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->InsertInput(zone, 4, jsgraph()->ExternalConstant(function_reference));
41362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
41462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Changed(node);
41562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
41662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
41762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochReduction JSCallReducer::ReduceSpreadCall(Node* node, int arity) {
41862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(node->opcode() == IrOpcode::kJSCallWithSpread ||
41962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         node->opcode() == IrOpcode::kJSConstructWithSpread);
42062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Do check to make sure we can actually avoid iteration.
42262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!isolate()->initial_array_iterator_prototype_map()->is_stable()) {
42362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return NoChange();
42462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
42562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* spread = NodeProperties::GetValueInput(node, arity);
42762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check if spread is an arguments object, and {node} is the only value user
42962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // of spread (except for value uses in frame states).
43062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (spread->opcode() != IrOpcode::kJSCreateArguments) return NoChange();
43162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (Edge edge : spread->use_edges()) {
43262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (edge.from()->opcode() == IrOpcode::kStateValues) continue;
43362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!NodeProperties::IsValueEdge(edge)) continue;
43462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (edge.from() == node) continue;
43562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return NoChange();
43662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
43762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
43862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Get to the actual frame state from which to extract the arguments;
43962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // we can only optimize this in case the {node} was already inlined into
44062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // some other function (and same for the {spread}).
44162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CreateArgumentsType type = CreateArgumentsTypeOf(spread->op());
44262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* frame_state = NodeProperties::GetFrameStateInput(spread);
44362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
44462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (outer_state->opcode() != IrOpcode::kFrameState) return NoChange();
44562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  FrameStateInfo outer_info = OpParameter<FrameStateInfo>(outer_state);
44662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
44762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Need to take the parameters from the arguments adaptor.
44862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    frame_state = outer_state;
44962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
45062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
45162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int start_index = 0;
45262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (type == CreateArgumentsType::kMappedArguments) {
45362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Mapped arguments (sloppy mode) cannot be handled if they are aliased.
45462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<SharedFunctionInfo> shared;
45562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
45662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (shared->internal_formal_parameter_count() != 0) return NoChange();
45762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else if (type == CreateArgumentsType::kRestParameter) {
45862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<SharedFunctionInfo> shared;
45962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
46062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    start_index = shared->internal_formal_parameter_count();
46162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
46262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Only check the array iterator protector when we have a rest object.
46362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!isolate()->IsArrayIteratorLookupChainIntact()) return NoChange();
46462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Add a code dependency on the array iterator protector.
46562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    dependencies()->AssumePropertyCell(factory()->array_iterator_protector());
46662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
46762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
46862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dependencies()->AssumeMapStable(
46962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate()->initial_array_iterator_prototype_map());
47062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
47162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  node->RemoveInput(arity--);
47262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
47362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Add the actual parameters to the {node}, skipping the receiver.
47462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
47562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (int i = start_index + 1; i < state_info.parameter_count(); ++i) {
47662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    node->InsertInput(graph()->zone(), static_cast<int>(++arity),
47762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      parameters->InputAt(i));
47862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
47962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
48062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (node->opcode() == IrOpcode::kJSCallWithSpread) {
48162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    NodeProperties::ChangeOp(
48262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        node, javascript()->Call(arity + 1, 7, VectorSlotPair()));
48362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
48462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    NodeProperties::ChangeOp(
48562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        node, javascript()->Construct(arity + 2, 7, VectorSlotPair()));
48662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
48762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Changed(node);
48862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
48962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
49062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochReduction JSCallReducer::ReduceJSCall(Node* node) {
49162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
49262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallParameters const& p = CallParametersOf(node->op());
493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* target = NodeProperties::GetValueInput(node, 0);
494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
49762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Try to specialize JSCall {node}s with constant {target}s.
498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HeapObjectMatcher m(target);
499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (m.HasValue()) {
500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (m.Value()->IsJSFunction()) {
501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<SharedFunctionInfo> shared(function->shared(), isolate());
503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Raise a TypeError if the {target} is a "classConstructor".
505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (IsClassConstructor(shared->kind())) {
506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::ReplaceValueInputs(node, target);
507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::ChangeOp(
508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            node, javascript()->CallRuntime(
509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      Runtime::kThrowConstructorNonCallableError, 1));
510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return Changed(node);
511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
51362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Don't inline cross native context.
51462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (function->native_context() != *native_context()) return NoChange();
51562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Check for known builtin functions.
517c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      switch (shared->code()->builtin_index()) {
518c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        case Builtins::kFunctionPrototypeApply:
519c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          return ReduceFunctionPrototypeApply(node);
520c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        case Builtins::kFunctionPrototypeCall:
521c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          return ReduceFunctionPrototypeCall(node);
52262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case Builtins::kFunctionPrototypeHasInstance:
52362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          return ReduceFunctionPrototypeHasInstance(node);
524c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        case Builtins::kNumberConstructor:
525c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          return ReduceNumberConstructor(node);
526c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        case Builtins::kObjectPrototypeGetProto:
527c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          return ReduceObjectPrototypeGetProto(node);
528c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        default:
529c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          break;
530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Check for the Array constructor.
533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (*function == function->native_context()->array_function()) {
534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceArrayConstructor(node);
535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
53662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
53762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (shared->IsApiFunction()) {
53862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return ReduceCallApiFunction(
53962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            node, target,
54062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            handle(FunctionTemplateInfo::cast(shared->function_data())));
54162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (m.Value()->IsJSBoundFunction()) {
543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<JSBoundFunction> function =
544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Handle<JSBoundFunction>::cast(m.Value());
545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<JSReceiver> bound_target_function(
546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          function->bound_target_function(), isolate());
547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<Object> bound_this(function->bound_this(), isolate());
548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<FixedArray> bound_arguments(function->bound_arguments(),
549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         isolate());
55062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CallParameters const& p = CallParametersOf(node->op());
551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ConvertReceiverMode const convert_mode =
55262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          (bound_this->IsNullOrUndefined(isolate()))
553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              ? ConvertReceiverMode::kNullOrUndefined
554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              : ConvertReceiverMode::kNotNullOrUndefined;
555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      size_t arity = p.arity();
556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_LE(2u, arity);
557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::ReplaceValueInput(
559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          node, jsgraph()->Constant(bound_target_function), 0);
560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        1);
562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Insert the [[BoundArguments]] for {node}.
563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (int i = 0; i < bound_arguments->length(); ++i) {
564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node->InsertInput(
565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            graph()->zone(), i + 2,
566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            jsgraph()->Constant(handle(bound_arguments->get(i), isolate())));
567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        arity++;
568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
56962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      NodeProperties::ChangeOp(
57062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          node,
57162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          javascript()->Call(arity, p.frequency(), VectorSlotPair(),
57262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             convert_mode, p.tail_call_mode()));
57362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Try to further reduce the JSCall {node}.
57462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Reduction const reduction = ReduceJSCall(node);
575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return reduction.Changed() ? reduction : Changed(node);
576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Don't mess with other {node}s that have a constant {target}.
579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // TODO(bmeurer): Also support proxies here.
580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return NoChange();
581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Extract feedback from the {node} using the CallICNexus.
584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!p.feedback().IsValid()) return NoChange();
585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
58662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (nexus.IsUninitialized()) {
58762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // TODO(turbofan): Tail-calling to a CallIC stub is not supported.
58862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (p.tail_call_mode() == TailCallMode::kAllow) return NoChange();
58962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
59062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Insert a CallIC here to collect feedback for uninitialized calls.
59162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    int const arg_count = static_cast<int>(p.arity() - 2);
59262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Callable callable = CodeFactory::CallIC(isolate(), p.convert_mode());
59362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
59462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
59562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate(), graph()->zone(), callable.descriptor(), arg_count + 1,
59662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        flags);
59762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* stub_code = jsgraph()->HeapConstant(callable.code());
59862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* stub_arity = jsgraph()->Constant(arg_count);
59962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* slot_index =
60062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        jsgraph()->Constant(FeedbackVector::GetIndex(p.feedback().slot()));
60162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector());
60262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    node->InsertInput(graph()->zone(), 0, stub_code);
60362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    node->InsertInput(graph()->zone(), 2, stub_arity);
60462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    node->InsertInput(graph()->zone(), 3, slot_index);
60562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    node->InsertInput(graph()->zone(), 4, feedback_vector);
60662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    NodeProperties::ChangeOp(node, common()->Call(desc));
607f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return Changed(node);
608f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
60962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
61062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Not much we can do if deoptimization support is disabled.
61162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!(flags() & kDeoptimizationEnabled)) return NoChange();
61262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Object> feedback(nexus.GetFeedback(), isolate());
614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (feedback->IsAllocationSite()) {
615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Retrieve the Array function from the {node}.
616c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* array_function = jsgraph()->HeapConstant(
617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        handle(native_context()->array_function(), isolate()));
618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check that the {target} is still the {array_function}.
620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                   array_function);
622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control);
623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Turn the {node} into a {JSCreateArray} call.
625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ReplaceValueInput(node, array_function, 0);
626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ReplaceEffectInput(node, effect);
627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return ReduceArrayConstructor(node);
628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (feedback->IsWeakCell()) {
629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback);
630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (cell->value()->IsJSFunction()) {
631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Node* target_function =
632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          jsgraph()->Constant(handle(cell->value(), isolate()));
633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Check that the {target} is still the {target_function}.
635f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                     target_function);
637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      effect =
638f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          graph()->NewNode(simplified()->CheckIf(), check, effect, control);
639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
64062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Specialize the JSCall node to the {target_function}.
641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::ReplaceValueInput(node, target_function, 0);
64213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      NodeProperties::ReplaceEffectInput(node, effect);
643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
64462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Try to further reduce the JSCall {node}.
64562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Reduction const reduction = ReduceJSCall(node);
646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return reduction.Changed() ? reduction : Changed(node);
647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return NoChange();
650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
65262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochReduction JSCallReducer::ReduceJSCallWithSpread(Node* node) {
65362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSCallWithSpread, node->opcode());
65462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallWithSpreadParameters const& p = CallWithSpreadParametersOf(node->op());
65562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_LE(3u, p.arity());
65662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int arity = static_cast<int>(p.arity() - 1);
65762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
65862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ReduceSpreadCall(node, arity);
65962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
66162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochReduction JSCallReducer::ReduceJSConstruct(Node* node) {
66262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
66362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ConstructParameters const& p = ConstructParametersOf(node->op());
664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(2u, p.arity());
665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const arity = static_cast<int>(p.arity() - 2);
666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* target = NodeProperties::GetValueInput(node, 0);
667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(node);
669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* control = NodeProperties::GetControlInput(node);
670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
67162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Try to specialize JSConstruct {node}s with constant {target}s.
672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HeapObjectMatcher m(target);
673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (m.HasValue()) {
674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (m.Value()->IsJSFunction()) {
675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Raise a TypeError if the {target} is not a constructor.
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!function->IsConstructor()) {
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::ReplaceValueInputs(node, target);
680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::ChangeOp(
68162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            node, javascript()->CallRuntime(
68262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      Runtime::kThrowConstructedNonConstructable));
683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return Changed(node);
684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
68662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Don't inline cross native context.
68762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (function->native_context() != *native_context()) return NoChange();
68862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Check for the ArrayConstructor.
690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (*function == function->native_context()->array_function()) {
691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Check if we have an allocation site.
692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Handle<AllocationSite> site;
693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p.feedback().IsValid()) {
694f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
695f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          Handle<Object> feedback(nexus.GetFeedback(), isolate());
696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (feedback->IsAllocationSite()) {
697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            site = Handle<AllocationSite>::cast(feedback);
698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Turn the {node} into a {JSCreateArray} call.
702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (int i = arity; i > 0; --i) {
703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          NodeProperties::ReplaceValueInput(
704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              node, NodeProperties::GetValueInput(node, i), i + 1);
705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::ReplaceValueInput(node, new_target, 1);
707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site));
708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return Changed(node);
709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Don't mess with other {node}s that have a constant {target}.
713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // TODO(bmeurer): Also support optimizing bound functions and proxies here.
714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return NoChange();
715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Not much we can do if deoptimization support is disabled.
718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!(flags() & kDeoptimizationEnabled)) return NoChange();
719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!p.feedback().IsValid()) return NoChange();
721f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
722f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Handle<Object> feedback(nexus.GetFeedback(), isolate());
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (feedback->IsAllocationSite()) {
724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // The feedback is an AllocationSite, which means we have called the
725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Array function and collected transition (and pretenuring) feedback
726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // for the resulting arrays.  This has to be kept in sync with the
727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // implementation of the CallConstructStub.
728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<AllocationSite> site = Handle<AllocationSite>::cast(feedback);
729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Retrieve the Array function from the {node}.
731c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* array_function = jsgraph()->HeapConstant(
732c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        handle(native_context()->array_function(), isolate()));
733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check that the {target} is still the {array_function}.
735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                   array_function);
737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control);
738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Turn the {node} into a {JSCreateArray} call.
740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ReplaceEffectInput(node, effect);
741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = arity; i > 0; --i) {
742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::ReplaceValueInput(
743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          node, NodeProperties::GetValueInput(node, i), i + 1);
744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ReplaceValueInput(node, new_target, 1);
746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site));
747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(node);
748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (feedback->IsWeakCell()) {
749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback);
750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (cell->value()->IsJSFunction()) {
751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Node* target_function =
752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          jsgraph()->Constant(handle(cell->value(), isolate()));
753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Check that the {target} is still the {target_function}.
755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
756f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                     target_function);
757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      effect =
758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          graph()->NewNode(simplified()->CheckIf(), check, effect, control);
759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
76062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Specialize the JSConstruct node to the {target_function}.
761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::ReplaceValueInput(node, target_function, 0);
762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      NodeProperties::ReplaceEffectInput(node, effect);
763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (target == new_target) {
764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        NodeProperties::ReplaceValueInput(node, target_function, arity + 1);
765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
76762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Try to further reduce the JSConstruct {node}.
76862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Reduction const reduction = ReduceJSConstruct(node);
769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return reduction.Changed() ? reduction : Changed(node);
770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return NoChange();
774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
77662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochReduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) {
77762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kJSConstructWithSpread, node->opcode());
77862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ConstructWithSpreadParameters const& p =
77962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ConstructWithSpreadParametersOf(node->op());
78062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_LE(3u, p.arity());
78162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int arity = static_cast<int>(p.arity() - 2);
78262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
78362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ReduceSpreadCall(node, arity);
78462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
78562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochGraph* JSCallReducer::graph() const { return jsgraph()->graph(); }
787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochIsolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }
789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
79062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochFactory* JSCallReducer::factory() const { return isolate()->factory(); }
79162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCommonOperatorBuilder* JSCallReducer::common() const {
793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return jsgraph()->common();
794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochJSOperatorBuilder* JSCallReducer::javascript() const {
797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return jsgraph()->javascript();
798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
800f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochSimplifiedOperatorBuilder* JSCallReducer::simplified() const {
801f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return jsgraph()->simplified();
802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
803f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace compiler
805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
807