[api] Don't unnecessary set up a fake api frame

Change-Id: I4fe880b8d0f3c6886b7bf2f0aa497068f4cfd9a5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3735134
Auto-Submit: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81495}
This commit is contained in:
Toon Verwaest 2022-07-01 15:05:15 +02:00 committed by V8 LUCI CQ
parent bcd8bf90ff
commit 2650b3f7d6
3 changed files with 39 additions and 70 deletions

View File

@ -4,6 +4,7 @@
#include "src/api/api-arguments-inl.h"
#include "src/api/api-natives.h"
#include "src/base/small-vector.h"
#include "src/builtins/builtins-utils-inl.h"
#include "src/builtins/builtins.h"
#include "src/logging/log.h"
@ -47,16 +48,18 @@ JSReceiver GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo info,
return JSReceiver();
}
// argv and argc are the same as those passed to FunctionCallbackInfo:
// - argc is the number of arguments excluding the receiver
// - argv is the array arguments. The receiver is stored at argv[-1].
template <bool is_construct>
V8_WARN_UNUSED_RESULT MaybeHandle<Object> HandleApiCallHelper(
Isolate* isolate, Handle<HeapObject> new_target,
Handle<FunctionTemplateInfo> fun_data, Handle<Object> receiver,
BuiltinArguments args) {
Address* argv, int argc) {
Handle<JSReceiver> js_receiver;
JSReceiver raw_holder;
base::Optional<BuiltinArguments::ChangeValueScope> set_receiver_value_scope;
if (is_construct) {
DCHECK(args.receiver()->IsTheHole(isolate));
DCHECK(receiver->IsTheHole(isolate));
if (fun_data->GetInstanceTemplate().IsUndefined(isolate)) {
v8::Local<ObjectTemplate> templ =
ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate),
@ -71,10 +74,7 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> HandleApiCallHelper(
ApiNatives::InstantiateObject(isolate, instance_template,
Handle<JSReceiver>::cast(new_target)),
Object);
set_receiver_value_scope.emplace(
isolate, &args, BuiltinArguments::kReceiverOffset, *js_receiver);
DCHECK_EQ(*js_receiver, *args.receiver());
argv[-1] = js_receiver->ptr();
raw_holder = *js_receiver;
} else {
DCHECK(receiver->IsJSReceiver());
@ -84,10 +84,9 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> HandleApiCallHelper(
js_receiver->IsAccessCheckNeeded()) {
// Proxies never need access checks.
DCHECK(js_receiver->IsJSObject());
Handle<JSObject> js_obj_receiver = Handle<JSObject>::cast(js_receiver);
if (!isolate->MayAccess(handle(isolate->context(), isolate),
js_obj_receiver)) {
isolate->ReportFailedAccessCheck(js_obj_receiver);
Handle<JSObject> js_object = Handle<JSObject>::cast(js_receiver);
if (!isolate->MayAccess(handle(isolate->context(), isolate), js_object)) {
isolate->ReportFailedAccessCheck(js_object);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->undefined_value();
}
@ -109,8 +108,7 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> HandleApiCallHelper(
Object data_obj = call_data.data();
FunctionCallbackArguments custom(isolate, data_obj, raw_holder, *new_target,
args.address_of_first_argument(),
args.length() - 1);
argv, argc);
Handle<Object> result = custom.Call(call_data);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
@ -135,32 +133,40 @@ BUILTIN(HandleApiCall) {
Handle<HeapObject> new_target = args.new_target();
Handle<FunctionTemplateInfo> fun_data(
args.target()->shared().get_api_func_data(), isolate);
int argc = args.length() - 1;
Address* argv = args.address_of_first_argument();
if (new_target->IsJSReceiver()) {
RETURN_RESULT_OR_FAILURE(
isolate, HandleApiCallHelper<true>(isolate, new_target, fun_data,
receiver, args));
receiver, argv, argc));
} else {
RETURN_RESULT_OR_FAILURE(
isolate, HandleApiCallHelper<false>(isolate, new_target, fun_data,
receiver, args));
receiver, argv, argc));
}
}
namespace {
class RelocatableArguments : public BuiltinArguments, public Relocatable {
class RelocatableArguments : public Relocatable {
public:
RelocatableArguments(Isolate* isolate, int length, Address* arguments)
: BuiltinArguments(length, arguments), Relocatable(isolate) {}
RelocatableArguments(Isolate* isolate, size_t length, Address* arguments)
: Relocatable(isolate), length_(length), arguments_(arguments) {
DCHECK_LT(0, length_);
}
RelocatableArguments(const RelocatableArguments&) = delete;
RelocatableArguments& operator=(const RelocatableArguments&) = delete;
inline void IterateInstance(RootVisitor* v) override {
if (length() == 0) return;
v->VisitRootPointers(Root::kRelocatable, nullptr, first_slot(),
last_slot() + 1);
v->VisitRootPointers(Root::kRelocatable, nullptr,
FullObjectSlot(&arguments_[0]),
FullObjectSlot(&arguments_[length_]));
}
private:
size_t length_;
Address* arguments_;
};
} // namespace
@ -181,40 +187,19 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(
// a break point on any API function.
DCHECK(!Handle<FunctionTemplateInfo>::cast(function)->BreakAtEntry());
// Construct BuiltinArguments object:
// new target, function, arguments reversed, receiver.
const int kBufferSize = 32;
Address small_argv[kBufferSize];
Address* argv;
const int frame_argc = argc + BuiltinArguments::kNumExtraArgsWithReceiver;
if (frame_argc <= kBufferSize) {
argv = small_argv;
} else {
argv = new Address[frame_argc];
}
argv[BuiltinArguments::kNewTargetOffset] = new_target->ptr();
argv[BuiltinArguments::kTargetOffset] = Smi::FromInt(0).ptr();
argv[BuiltinArguments::kArgcOffset] = Smi::FromInt(frame_argc).ptr();
argv[BuiltinArguments::kPaddingOffset] =
ReadOnlyRoots(isolate).the_hole_value().ptr();
argv[BuiltinArguments::kReceiverOffset] = receiver->ptr();
int cursor = BuiltinArguments::kNumExtraArgsWithReceiver;
base::SmallVector<Address, 32> argv(argc + 1);
argv[0] = receiver->ptr();
for (int i = 0; i < argc; ++i) {
argv[cursor++] = args[i]->ptr();
argv[i + 1] = args[i]->ptr();
}
MaybeHandle<Object> result;
{
RelocatableArguments arguments(isolate, frame_argc, &argv[frame_argc - 1]);
if (is_construct) {
result = HandleApiCallHelper<true>(isolate, new_target, function,
receiver, arguments);
} else {
result = HandleApiCallHelper<false>(isolate, new_target, function,
receiver, arguments);
}
RelocatableArguments arguments(isolate, argv.size(), argv.data());
if (is_construct) {
return HandleApiCallHelper<true>(isolate, new_target, function, receiver,
argv.data() + 1, argc);
}
if (argv != small_argv) delete[] argv;
return result;
return HandleApiCallHelper<false>(isolate, new_target, function, receiver,
argv.data() + 1, argc);
}
// Helper function to handle calls to non-function objects created through the

View File

@ -65,10 +65,6 @@ class Arguments {
V8_INLINE double number_value_at(int index) const;
V8_INLINE FullObjectSlot slot_at(int index) const {
return FullObjectSlot(address_of_arg_at(index));
}
V8_INLINE Address* address_of_arg_at(int index) const {
DCHECK_LE(static_cast<uint32_t>(index), static_cast<uint32_t>(length_));
uintptr_t offset = index * kSystemPointerSize;
@ -82,19 +78,6 @@ class Arguments {
// Get the total number of arguments including the receiver.
V8_INLINE int length() const { return static_cast<int>(length_); }
// Arguments on the stack are in reverse order (compared to an array).
FullObjectSlot first_slot() const {
int index = length() - 1;
if (arguments_type == ArgumentsType::kJS) index = 0;
return slot_at(index);
}
FullObjectSlot last_slot() const {
int index = 0;
if (arguments_type == ArgumentsType::kJS) index = length() - 1;
return slot_at(index);
}
private:
intptr_t length_;
Address* arguments_;

View File

@ -5098,7 +5098,8 @@ void JSObject::EnsureCanContainElements(Handle<JSObject> object,
JavaScriptArguments* args,
uint32_t arg_count,
EnsureElementsMode mode) {
return EnsureCanContainElements(object, args->first_slot(), arg_count, mode);
return EnsureCanContainElements(
object, FullObjectSlot(args->address_of_arg_at(0)), arg_count, mode);
}
void JSObject::ValidateElements(JSObject object) {