| Index: src/compiler/js-typed-lowering.cc
|
| diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
|
| index a49a3ae28fefd0031ab0422fae107ae5264b3435..92c25747a34080e0a8f83c6341ebf9ce59cc4716 100644
|
| --- a/src/compiler/js-typed-lowering.cc
|
| +++ b/src/compiler/js-typed-lowering.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "src/compiler/js-typed-lowering.h"
|
|
|
| +#include "src/builtins/builtins-utils.h"
|
| #include "src/code-factory.h"
|
| #include "src/compilation-dependencies.h"
|
| #include "src/compiler/access-builder.h"
|
| @@ -1582,6 +1583,8 @@ Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
|
| Handle<JSFunction> function =
|
| Handle<JSFunction>::cast(target_type->AsConstant()->Value());
|
| Handle<SharedFunctionInfo> shared(function->shared(), isolate());
|
| + Handle<Code> code(shared->code());
|
| + auto builtin_name = static_cast<Builtins::Name>(code->builtin_index());
|
|
|
| // Class constructors are callable, but [[Call]] will raise an exception.
|
| // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
|
| @@ -1613,9 +1616,60 @@ Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
|
|
|
| Node* new_target = jsgraph()->UndefinedConstant();
|
| Node* argument_count = jsgraph()->Int32Constant(arity);
|
| - if (shared->internal_formal_parameter_count() == arity ||
|
| - shared->internal_formal_parameter_count() ==
|
| - SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
|
| + if (code->kind() == Code::BUILTIN &&
|
| + isolate()->builtins()->IsCppBuiltin(builtin_name)) {
|
| + // Patch {node} to a direct CEntryStub call.
|
| + //
|
| + // ----------- A r g u m e n t s -----------
|
| + // -- 0: CEntryStub
|
| + // --- Stack args ---
|
| + // -- 1: receiver
|
| + // -- [2, 2 + n[: the n actual arguments passed to the builtin
|
| + // -- 2 + n: argc, including the receiver and implicit args (Smi)
|
| + // -- 2 + n + 1: target
|
| + // -- 2 + n + 2: new_target
|
| + // --- Register args ---
|
| + // -- 2 + n + 3: the C entry point
|
| + // -- 2 + n + 4: argc (Int32)
|
| + // -----------------------------------
|
| +
|
| + // The logic contained here is mirrored in Builtins::Generate_Adaptor.
|
| + // Keep these in sync.
|
| +
|
| + // 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 auto builtin = isolate()->builtins()->DescriptorFor(builtin_name);
|
| + const bool create_builtin_exit_frame = (builtin->kind == Builtins::CPP);
|
| +
|
| + Node* stub = jsgraph()->CEntryStubConstant(
|
| + 1, kDontSaveFPRegs, kArgvOnStack, create_builtin_exit_frame);
|
| + node->ReplaceInput(0, stub);
|
| +
|
| + const int argc = arity + BuiltinArguments::kNumExtraArgsWithReceiver;
|
| + Node* argc_node = jsgraph()->Int32Constant(argc);
|
| +
|
| + Zone* zone = graph()->zone();
|
| + node->InsertInput(zone, arity + 2, argc_node);
|
| + node->InsertInput(zone, arity + 3, target);
|
| + node->InsertInput(zone, arity + 4, new_target);
|
| +
|
| + ExternalReference entry(ExternalReference(builtin->entry, isolate()));
|
| + Node* entry_node = jsgraph()->ExternalConstant(entry);
|
| +
|
| + node->InsertInput(zone, arity + 5, entry_node);
|
| + node->InsertInput(zone, arity + 6, argc_node);
|
| +
|
| + const int return_count = 1;
|
| + CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
|
| + Operator::Properties properties = node->op()->properties();
|
| + CallDescriptor* desc = Linkage::GetCEntryStubCallDescriptor(
|
| + graph()->zone(), return_count, argc, builtin->debug_name, properties,
|
| + flags);
|
| +
|
| + NodeProperties::ChangeOp(node, common()->Call(desc));
|
| + } else if (shared->internal_formal_parameter_count() == arity ||
|
| + shared->internal_formal_parameter_count() ==
|
| + SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
|
| // Patch {node} to a direct call.
|
| node->InsertInput(graph()->zone(), arity + 2, new_target);
|
| node->InsertInput(graph()->zone(), arity + 3, argument_count);
|
|
|