Commit 813f2318 authored by verwaest's avatar verwaest Committed by Commit bot

Further streamline HandleApiCall

The CL avoids superfluous conversions / reboxing and handlescopes.

BUG=

Review-Url: https://codereview.chromium.org/2089703004
Cr-Commit-Position: refs/heads/master@{#37180}
parent c7715c2f
......@@ -5123,21 +5123,12 @@ JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
return nullptr;
}
MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(Isolate* isolate,
BuiltinArguments args) {
HandleScope scope(isolate);
Handle<HeapObject> function = args.target<HeapObject>();
Handle<HeapObject> new_target = args.new_target();
bool is_construct = !new_target->IsUndefined(isolate);
template <bool is_construct>
MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
Isolate* isolate, Handle<HeapObject> function,
Handle<HeapObject> new_target, Handle<FunctionTemplateInfo> fun_data,
BuiltinArguments args) {
Handle<JSObject> receiver;
DCHECK(function->IsFunctionTemplateInfo() ||
Handle<JSFunction>::cast(function)->shared()->IsApiFunction());
Handle<FunctionTemplateInfo> fun_data =
function->IsFunctionTemplateInfo()
? Handle<FunctionTemplateInfo>::cast(function)
: handle(JSFunction::cast(*function)->shared()->get_api_func_data());
JSObject* raw_holder;
if (is_construct) {
DCHECK(args.receiver()->IsTheHole(isolate));
......@@ -5201,15 +5192,18 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(Isolate* isolate,
args.length() - 1);
Handle<Object> result = custom.Call(callback);
if (result.is_null()) result = isolate->factory()->undefined_value();
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
if (!is_construct || result->IsJSObject()) {
return scope.CloseAndEscape(result);
if (result.is_null()) {
if (is_construct) return receiver;
return isolate->factory()->undefined_value();
}
// Rebox the result.
result->VerifyApiCallResultType();
if (!is_construct || result->IsJSObject()) return handle(*result, isolate);
}
return scope.CloseAndEscape(receiver);
return receiver;
}
} // namespace
......@@ -5217,7 +5211,19 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(Isolate* isolate,
BUILTIN(HandleApiCall) {
HandleScope scope(isolate);
RETURN_RESULT_OR_FAILURE(isolate, HandleApiCallHelper(isolate, args));
Handle<JSFunction> function = args.target<JSFunction>();
Handle<HeapObject> new_target = args.new_target();
Handle<FunctionTemplateInfo> fun_data(function->shared()->get_api_func_data(),
isolate);
if (new_target->IsJSReceiver()) {
RETURN_RESULT_OR_FAILURE(
isolate, HandleApiCallHelper<true>(isolate, function, new_target,
fun_data, args));
} else {
RETURN_RESULT_OR_FAILURE(
isolate, HandleApiCallHelper<false>(isolate, function, new_target,
fun_data, args));
}
}
......@@ -5317,14 +5323,17 @@ class RelocatableArguments : public BuiltinArguments, public Relocatable {
} // namespace
MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate,
Handle<HeapObject> function,
Handle<Object> receiver,
int argc,
Handle<Object> args[]) {
Isolate* isolate = function->GetIsolate();
DCHECK(function->IsFunctionTemplateInfo() ||
(function->IsJSFunction() &&
JSFunction::cast(*function)->shared()->IsApiFunction()));
// Do proper receiver conversion for non-strict mode api functions.
if (!receiver->IsJSReceiver()) {
DCHECK(function->IsFunctionTemplateInfo() || function->IsJSFunction());
if (function->IsFunctionTemplateInfo() ||
is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
......@@ -5332,6 +5341,13 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
Object);
}
}
Handle<FunctionTemplateInfo> fun_data =
function->IsFunctionTemplateInfo()
? 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;
......@@ -5347,15 +5363,14 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
argv[argc - i + 1] = *args[i];
}
argv[1] = *function;
argv[0] = isolate->heap()->undefined_value(); // new target
argv[0] = *new_target;
MaybeHandle<Object> result;
{
RelocatableArguments arguments(isolate, argc + 3, &argv[argc] + 2);
result = HandleApiCallHelper(isolate, arguments);
}
if (argv != small_argv) {
delete[] argv;
result = HandleApiCallHelper<false>(isolate, function, new_target, fun_data,
arguments);
}
if (argv != small_argv) delete[] argv;
return result;
}
......
......@@ -447,8 +447,8 @@ class Builtins {
bool is_initialized() const { return initialized_; }
MUST_USE_RESULT static MaybeHandle<Object> InvokeApiFunction(
Handle<HeapObject> function, Handle<Object> receiver, int argc,
Handle<Object> args[]);
Isolate* isolate, Handle<HeapObject> function, Handle<Object> receiver,
int argc, Handle<Object> args[]);
private:
Builtins();
......
......@@ -140,7 +140,8 @@ MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
SaveContext save(isolate);
isolate->set_context(function->context());
DCHECK(function->context()->global_object()->IsJSGlobalObject());
auto value = Builtins::InvokeApiFunction(function, receiver, argc, argv);
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) {
......
......@@ -7308,6 +7308,9 @@ void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
set_flag(AttributesField::update(flag(), attributes));
}
bool FunctionTemplateInfo::IsTemplateFor(JSObject* object) {
return IsTemplateFor(object->map());
}
bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
if (!HasExpectedReceiverType()) return true;
......
......@@ -988,11 +988,6 @@ bool Object::ToInt32(int32_t* value) {
return false;
}
bool FunctionTemplateInfo::IsTemplateFor(JSObject* object) {
return IsTemplateFor(object->map());
}
bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
// There is a constraint on the object; check.
if (!map->IsJSObjectMap()) return false;
......@@ -1156,16 +1151,9 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
// Regular accessor.
Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
if (getter->IsFunctionTemplateInfo()) {
auto result = Builtins::InvokeApiFunction(
Handle<FunctionTemplateInfo>::cast(getter), receiver, 0, nullptr);
if (isolate->has_pending_exception()) {
return MaybeHandle<Object>();
}
Handle<Object> return_value;
if (result.ToHandle(&return_value)) {
return_value->VerifyApiCallResultType();
return handle(*return_value, isolate);
}
return Builtins::InvokeApiFunction(
isolate, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
nullptr);
} else if (getter->IsCallable()) {
// TODO(rossberg): nicer would be to cast to some JSCallable here...
return Object::GetPropertyWithDefinedGetter(
......@@ -1245,12 +1233,11 @@ Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
if (setter->IsFunctionTemplateInfo()) {
Handle<Object> argv[] = {value};
auto result =
Builtins::InvokeApiFunction(Handle<FunctionTemplateInfo>::cast(setter),
receiver, arraysize(argv), argv);
if (isolate->has_pending_exception()) {
return Nothing<bool>();
}
RETURN_ON_EXCEPTION_VALUE(
isolate, Builtins::InvokeApiFunction(
isolate, Handle<FunctionTemplateInfo>::cast(setter),
receiver, arraysize(argv), argv),
Nothing<bool>());
return Just(true);
} else if (setter->IsCallable()) {
// TODO(rossberg): nicer would be to cast to some JSCallable here...
......
......@@ -10557,7 +10557,7 @@ class FunctionTemplateInfo: public TemplateInfo {
static const int kSize = kLengthOffset + kPointerSize;
// Returns true if |object| is an instance of this function template.
bool IsTemplateFor(JSObject* object);
inline bool IsTemplateFor(JSObject* object);
bool IsTemplateFor(Map* map);
private:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment