[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:
parent
bcd8bf90ff
commit
2650b3f7d6
@ -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
|
||||
|
@ -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_;
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user