Commit b891858c authored by Maya Lekova's avatar Maya Lekova Committed by V8 LUCI CQ

[fastcall] Disallow constructors with fast calls

This CL makes sure that the API reports an error if the embedder
attempts to create a fast API function which could be used as a
constructor. It also adds corresponding cctest.

Bug: chromium:1052746
Change-Id: I36e51b298889900131bd5c3894134df3d8d28e5f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3314856
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78243}
parent ca525298
......@@ -1370,6 +1370,14 @@ Local<FunctionTemplate> FunctionTemplate::New(
// Changes to the environment cannot be captured in the snapshot. Expect no
// function templates when the isolate is created for serialization.
LOG_API(i_isolate, FunctionTemplate, New);
if (!Utils::ApiCheck(
!c_function || behavior == ConstructorBehavior::kThrow,
"FunctionTemplate::New",
"Fast API calls are not supported for constructor functions.")) {
return Local<FunctionTemplate>();
}
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
return FunctionTemplateNew(
i_isolate, callback, data, signature, length, behavior, false,
......@@ -1385,17 +1393,17 @@ Local<FunctionTemplate> FunctionTemplate::NewWithCFunctionOverloads(
v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
SideEffectType side_effect_type,
const MemorySpan<const CFunction>& c_function_overloads) {
// TODO(mslekova): Once runtime overload resolution between sequences is
// supported, check that if (c_function_overloads.size() == 2), then
// c_function_overloads.data()[0].
// CanResolveOverload(c_function_overloads.data()[1]). We won't support
// the case where the size is greater than 2 for runtime resolution, until
// we've added support for ArrayBuffers and ArrayBufferViews. OTOH the
// overloads list might contain more than 2 functions with different arity,
// the resolution between which is available at compile time.
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, FunctionTemplate, New);
if (!Utils::ApiCheck(
c_function_overloads.size() == 0 ||
behavior == ConstructorBehavior::kThrow,
"FunctionTemplate::NewWithCFunctionOverloads",
"Fast API calls are not supported for constructor functions.")) {
return Local<FunctionTemplate>();
}
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
return FunctionTemplateNew(i_isolate, callback, data, signature, length,
behavior, false, Local<Private>(),
......
......@@ -28153,7 +28153,7 @@ bool SetupTest(v8::Local<v8::Value> initial_value, LocalContext* env,
Local<v8::FunctionTemplate> checker_templ = v8::FunctionTemplate::New(
isolate, BasicApiChecker<Value, Impl, Ret>::SlowCallback,
v8::Number::New(isolate, 42), v8::Local<v8::Signature>(), 1,
v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect,
v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasSideEffect,
&c_func);
if (!accept_any_receiver) {
checker_templ->SetAcceptAnyReceiver(false);
......@@ -28288,6 +28288,48 @@ void CheckApiObjectArg() {
CHECK(!checker.DidCallSlow());
}
static const char* fast_calls_error_message = nullptr;
static const char* fast_calls_error_location = nullptr;
void FastCallsErrorCallback(const char* location, const char* message) {
fast_calls_error_message = message;
fast_calls_error_location = location;
}
void CheckFastCallsWithConstructor() {
LocalContext env;
v8::Isolate* isolate = CcTest::isolate();
CcTest::isolate()->SetFatalErrorHandler(FastCallsErrorCallback);
CHECK_NULL(fast_calls_error_message);
v8::CFunction c_func_ctor =
v8::CFunction::Make(ApiObjectChecker::FastCallback);
v8::FunctionTemplate::New(isolate, ApiObjectChecker::SlowCallback,
Local<v8::Value>(), v8::Local<v8::Signature>(), 1,
v8::ConstructorBehavior::kAllow,
v8::SideEffectType::kHasSideEffect, &c_func_ctor);
CHECK_NOT_NULL(fast_calls_error_message);
CHECK_EQ(
0, strcmp(fast_calls_error_message,
"Fast API calls are not supported for constructor functions."));
CHECK_NOT_NULL(fast_calls_error_location);
CHECK_EQ(0, strcmp(fast_calls_error_location, "FunctionTemplate::New"));
fast_calls_error_message = nullptr;
const v8::CFunction c_func_ctor_overloads[] = {c_func_ctor};
v8::FunctionTemplate::NewWithCFunctionOverloads(
isolate, ApiObjectChecker::SlowCallback, Local<v8::Value>(),
v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kAllow,
v8::SideEffectType::kHasSideEffect, {c_func_ctor_overloads, 1});
CHECK_NOT_NULL(fast_calls_error_message);
CHECK_EQ(
0, strcmp(fast_calls_error_message,
"Fast API calls are not supported for constructor functions."));
CHECK_NOT_NULL(fast_calls_error_location);
CHECK_EQ(0, strcmp(fast_calls_error_location,
"FunctionTemplate::NewWithCFunctionOverloads"));
}
template <typename T>
struct ReturnValueChecker : BasicApiChecker<T, ReturnValueChecker<T>, T> {
static T FastCallback(v8::Local<v8::Object> receiver, T arg,
......@@ -28547,6 +28589,7 @@ TEST(FastApiCalls) {
v8::internal::FLAG_always_opt = false;
v8::internal::FlagList::EnforceFlagImplications();
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i_isolate->set_embedder_wrapper_type_index(kV8WrapperTypeIndex);
......@@ -28997,6 +29040,7 @@ TEST(FastApiCalls) {
CallWithUnexpectedObjectType(CompileRun("new Proxy({}, {});"));
CheckApiObjectArg();
CheckFastCallsWithConstructor();
// TODO(mslekova): Restructure the tests so that the fast optimized calls
// are compared against the slow optimized calls.
......@@ -29111,7 +29155,7 @@ TEST(FastApiSequenceOverloads) {
Local<v8::FunctionTemplate> sequence_callback_templ =
v8::FunctionTemplate::NewWithCFunctionOverloads(
isolate, SequenceSlowCallback, v8::Number::New(isolate, 42),
v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kAllow,
v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kThrow,
v8::SideEffectType::kHasSideEffect, {sequece_overloads, 2});
v8::Local<v8::ObjectTemplate> object_template =
......@@ -4199,7 +4199,7 @@ TEST(FastApiCPUProfiler) {
Local<v8::FunctionTemplate> receiver_templ = v8::FunctionTemplate::New(
isolate, FastApiReceiver::SlowCallback, v8::Local<v8::Value>(),
v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kAllow,
v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kThrow,
v8::SideEffectType::kHasSideEffect, &c_func);
v8::Local<v8::ObjectTemplate> object_template =
......
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