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