[api] Stay in C++ when constructing an API-function
This CL applies the same optimization already present for calling API-function. Execution::New and Execution::Call now both check whether the target is an API-function and avoid calling out into the construct/call stub. BUG=chromium:630217 Review-Url: https://codereview.chromium.org/2203353002 Cr-Commit-Position: refs/heads/master@{#38433}
This commit is contained in:
parent
b12a51c1f6
commit
b920d5f3ff
@ -157,16 +157,17 @@ class RelocatableArguments : public BuiltinArguments, public Relocatable {
|
||||
} // namespace
|
||||
|
||||
MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate,
|
||||
bool is_construct,
|
||||
Handle<HeapObject> function,
|
||||
Handle<Object> receiver,
|
||||
int argc,
|
||||
Handle<Object> args[]) {
|
||||
int argc, Handle<Object> args[],
|
||||
Handle<HeapObject> new_target) {
|
||||
DCHECK(function->IsFunctionTemplateInfo() ||
|
||||
(function->IsJSFunction() &&
|
||||
JSFunction::cast(*function)->shared()->IsApiFunction()));
|
||||
|
||||
// Do proper receiver conversion for non-strict mode api functions.
|
||||
if (!receiver->IsJSReceiver()) {
|
||||
if (!is_construct && !receiver->IsJSReceiver()) {
|
||||
if (function->IsFunctionTemplateInfo() ||
|
||||
is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
|
||||
@ -180,7 +181,6 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate,
|
||||
? Handle<FunctionTemplateInfo>::cast(function)
|
||||
: handle(JSFunction::cast(*function)->shared()->get_api_func_data(),
|
||||
isolate);
|
||||
Handle<HeapObject> new_target = isolate->factory()->undefined_value();
|
||||
// Construct BuiltinArguments object:
|
||||
// new target, function, arguments reversed, receiver.
|
||||
const int kBufferSize = 32;
|
||||
@ -204,8 +204,13 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate,
|
||||
MaybeHandle<Object> result;
|
||||
{
|
||||
RelocatableArguments arguments(isolate, frame_argc, &argv[frame_argc - 1]);
|
||||
result = HandleApiCallHelper<false>(isolate, function, new_target, fun_data,
|
||||
receiver, arguments);
|
||||
if (is_construct) {
|
||||
result = HandleApiCallHelper<true>(isolate, function, new_target,
|
||||
fun_data, receiver, arguments);
|
||||
} else {
|
||||
result = HandleApiCallHelper<false>(isolate, function, new_target,
|
||||
fun_data, receiver, arguments);
|
||||
}
|
||||
}
|
||||
if (argv != small_argv) delete[] argv;
|
||||
return result;
|
||||
|
@ -604,8 +604,9 @@ class Builtins {
|
||||
bool is_initialized() const { return initialized_; }
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> InvokeApiFunction(
|
||||
Isolate* isolate, Handle<HeapObject> function, Handle<Object> receiver,
|
||||
int argc, Handle<Object> args[]);
|
||||
Isolate* isolate, bool is_construct, Handle<HeapObject> function,
|
||||
Handle<Object> receiver, int argc, Handle<Object> args[],
|
||||
Handle<HeapObject> new_target);
|
||||
|
||||
enum ExitFrameType { EXIT, BUILTIN_EXIT };
|
||||
|
||||
|
@ -72,6 +72,30 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct,
|
||||
}
|
||||
#endif
|
||||
|
||||
// api callbacks can be called directly.
|
||||
if (target->IsJSFunction()) {
|
||||
Handle<JSFunction> function = Handle<JSFunction>::cast(target);
|
||||
if ((!is_construct || function->IsConstructor()) &&
|
||||
function->shared()->IsApiFunction()) {
|
||||
SaveContext save(isolate);
|
||||
isolate->set_context(function->context());
|
||||
DCHECK(function->context()->global_object()->IsJSGlobalObject());
|
||||
if (is_construct) receiver = isolate->factory()->the_hole_value();
|
||||
auto value = Builtins::InvokeApiFunction(
|
||||
isolate, is_construct, function, receiver, argc, args,
|
||||
Handle<HeapObject>::cast(new_target));
|
||||
bool has_exception = value.is_null();
|
||||
DCHECK(has_exception == isolate->has_pending_exception());
|
||||
if (has_exception) {
|
||||
isolate->ReportPendingMessages();
|
||||
return MaybeHandle<Object>();
|
||||
} else {
|
||||
isolate->clear_pending_message();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// Entering JavaScript.
|
||||
VMState<JS> state(isolate);
|
||||
CHECK(AllowJavascriptExecution::IsAllowed(isolate));
|
||||
@ -147,26 +171,6 @@ MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
|
||||
receiver =
|
||||
handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(), isolate);
|
||||
}
|
||||
|
||||
// api callbacks can be called directly.
|
||||
if (callable->IsJSFunction() &&
|
||||
Handle<JSFunction>::cast(callable)->shared()->IsApiFunction()) {
|
||||
Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
|
||||
SaveContext save(isolate);
|
||||
isolate->set_context(function->context());
|
||||
DCHECK(function->context()->global_object()->IsJSGlobalObject());
|
||||
auto value =
|
||||
Builtins::InvokeApiFunction(isolate, function, receiver, argc, argv);
|
||||
bool has_exception = value.is_null();
|
||||
DCHECK(has_exception == isolate->has_pending_exception());
|
||||
if (has_exception) {
|
||||
isolate->ReportPendingMessages();
|
||||
return MaybeHandle<Object>();
|
||||
} else {
|
||||
isolate->clear_pending_message();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return Invoke(isolate, false, callable, receiver, argc, argv,
|
||||
isolate->factory()->undefined_value());
|
||||
}
|
||||
|
@ -1344,8 +1344,8 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
|
||||
Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
|
||||
if (getter->IsFunctionTemplateInfo()) {
|
||||
return Builtins::InvokeApiFunction(
|
||||
isolate, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
|
||||
nullptr);
|
||||
isolate, false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
|
||||
nullptr, isolate->factory()->undefined_value());
|
||||
} else if (getter->IsCallable()) {
|
||||
// TODO(rossberg): nicer would be to cast to some JSCallable here...
|
||||
return Object::GetPropertyWithDefinedGetter(
|
||||
@ -1427,8 +1427,9 @@ Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
|
||||
Handle<Object> argv[] = {value};
|
||||
RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, Builtins::InvokeApiFunction(
|
||||
isolate, Handle<FunctionTemplateInfo>::cast(setter),
|
||||
receiver, arraysize(argv), argv),
|
||||
isolate, false, Handle<FunctionTemplateInfo>::cast(setter),
|
||||
receiver, arraysize(argv), argv,
|
||||
isolate->factory()->undefined_value()),
|
||||
Nothing<bool>());
|
||||
return Just(true);
|
||||
} else if (setter->IsCallable()) {
|
||||
|
Loading…
Reference in New Issue
Block a user