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