Index: src/compiler/js-typed-lowering.cc |
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc |
index 62861b3c1c70cd3d82fa1a14a464e5d186ad684c..5fa1d82fe96ae6cc2cff29acf9556f51b9cfe6d0 100644 |
--- a/src/compiler/js-typed-lowering.cc |
+++ b/src/compiler/js-typed-lowering.cc |
@@ -1505,6 +1505,35 @@ Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) { |
namespace { |
+static const int kStubAndReceiver = 2; |
+ |
+// Adapts arguments if required and returns the number of JS arguments. This |
+// is always the number of formal arguments if we're adapting, and the current |
+// arity otherwise. |
+int MaybeAdaptArguments(Isolate* isolate, JSGraph* jsgraph, Node* node, |
+ int arity, SharedFunctionInfo* shared) { |
+ const int formal_parameter_count = shared->internal_formal_parameter_count(); |
+ const bool should_adapt_arguments = |
+ formal_parameter_count != SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
+ |
+ if (!should_adapt_arguments) return arity; |
+ |
+ if (arity < formal_parameter_count) { |
+ // Fewer actual than formal parameters, push the rest as undefined. |
+ Node* undefined = jsgraph->UndefinedConstant(); |
+ for (int i = arity; i < formal_parameter_count; i++) { |
+ node->InsertInput(jsgraph->zone(), arity + kStubAndReceiver, undefined); |
+ } |
+ } else if (arity > formal_parameter_count) { |
+ // More actual than formal parameters, remove trailing parameters. |
+ for (int i = formal_parameter_count; i < arity; i++) { |
+ node->RemoveInput(formal_parameter_count + kStubAndReceiver); |
+ } |
+ } |
+ |
+ return formal_parameter_count; |
+} |
+ |
void ReduceBuiltin(Isolate* isolate, JSGraph* jsgraph, Node* node, |
int builtin_index, int arity, CallDescriptor::Flags flags) { |
// Patch {node} to a direct CEntryStub call. |
@@ -1529,20 +1558,22 @@ void ReduceBuiltin(Isolate* isolate, JSGraph* jsgraph, Node* node, |
DCHECK(Builtins::HasCppImplementation(builtin_index)); |
+ Zone* zone = jsgraph->zone(); |
Node* target = NodeProperties::GetValueInput(node, 0); |
Node* new_target = is_construct |
? NodeProperties::GetValueInput(node, arity + 1) |
: jsgraph->UndefinedConstant(); |
+ Type* target_type = NodeProperties::GetType(target); |
+ DCHECK(target_type->IsConstant()); |
+ |
// API and CPP builtins are implemented in C++, and we can inline both. |
// CPP builtins create a builtin exit frame, API builtins don't. |
const bool has_builtin_exit_frame = Builtins::IsCpp(builtin_index); |
- |
Node* stub = jsgraph->CEntryStubConstant(1, kDontSaveFPRegs, kArgvOnStack, |
has_builtin_exit_frame); |
node->ReplaceInput(0, stub); |
- Zone* zone = jsgraph->zone(); |
if (is_construct) { |
// Unify representations between construct and call nodes. |
// Remove new target and add receiver as a stack parameter. |
@@ -1551,19 +1582,25 @@ void ReduceBuiltin(Isolate* isolate, JSGraph* jsgraph, Node* node, |
node->InsertInput(zone, 1, receiver); |
} |
- const int argc = arity + BuiltinArguments::kNumExtraArgsWithReceiver; |
+ Handle<JSFunction> function = |
+ Handle<JSFunction>::cast(target_type->AsConstant()->Value()); |
+ const int adapted_arity = |
+ MaybeAdaptArguments(isolate, jsgraph, node, arity, function->shared()); |
+ |
+ const int argc = adapted_arity + BuiltinArguments::kNumExtraArgsWithReceiver; |
Node* argc_node = jsgraph->Int32Constant(argc); |
- node->InsertInput(zone, arity + 2, argc_node); |
- node->InsertInput(zone, arity + 3, target); |
- node->InsertInput(zone, arity + 4, new_target); |
+ int cursor = adapted_arity + kStubAndReceiver; |
+ node->InsertInput(zone, cursor++, argc_node); |
+ node->InsertInput(zone, cursor++, target); |
+ node->InsertInput(zone, cursor++, new_target); |
Address entry = Builtins::CppEntryOf(builtin_index); |
ExternalReference entry_ref(ExternalReference(entry, isolate)); |
Node* entry_node = jsgraph->ExternalConstant(entry_ref); |
- node->InsertInput(zone, arity + 5, entry_node); |
- node->InsertInput(zone, arity + 6, argc_node); |
+ node->InsertInput(zone, cursor++, entry_node); |
+ node->InsertInput(zone, cursor++, argc_node); |
static const int kReturnCount = 1; |
const char* debug_name = Builtins::name(builtin_index); |
@@ -1598,10 +1635,7 @@ Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) { |
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; |
- if (is_builtin && Builtins::HasCppImplementation(builtin_index) && |
- (shared->internal_formal_parameter_count() == arity || |
- shared->internal_formal_parameter_count() == |
- SharedFunctionInfo::kDontAdaptArgumentsSentinel)) { |
+ if (is_builtin && Builtins::HasCppImplementation(builtin_index)) { |
// Patch {node} to a direct CEntryStub call. |
// Load the context from the {target}. |
@@ -1713,10 +1747,7 @@ Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) { |
Node* new_target = jsgraph()->UndefinedConstant(); |
Node* argument_count = jsgraph()->Int32Constant(arity); |
- if (is_builtin && Builtins::HasCppImplementation(builtin_index) && |
- (shared->internal_formal_parameter_count() == arity || |
- shared->internal_formal_parameter_count() == |
- SharedFunctionInfo::kDontAdaptArgumentsSentinel)) { |
+ if (is_builtin && Builtins::HasCppImplementation(builtin_index)) { |
// Patch {node} to a direct CEntryStub call. |
ReduceBuiltin(isolate(), jsgraph(), node, builtin_index, arity, flags); |
} else if (shared->internal_formal_parameter_count() == arity || |