Commit a7980d43 authored by Paolo Severini's avatar Paolo Severini Committed by V8 LUCI CQ

[fastcall] Add vector of CFunction overloads to FunctionTemplate

As a first step to support Fast API calls with overloads, adds a
new FunctionTemplate constructor that accepts a vector of CFunction*.

Bug: v8:11739
Change-Id: I112b1746768f52df52c893a4f1fb799b6bd90856
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2860838Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Paolo Severini <paolosev@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#74481}
parent f4a6c628
......@@ -6499,6 +6499,15 @@ class V8_EXPORT FunctionTemplate : public Template {
SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
const CFunction* c_function = nullptr);
/** Creates a function template for multiple overloaded fast API calls.*/
static Local<FunctionTemplate> NewWithCFunctionOverloads(
Isolate* isolate, FunctionCallback callback = nullptr,
Local<Value> data = Local<Value>(),
Local<Signature> signature = Local<Signature>(), int length = 0,
ConstructorBehavior behavior = ConstructorBehavior::kAllow,
SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
const std::vector<const CFunction*>& c_function_overloads = {});
/**
* Creates a function template backed/cached by a private property.
*/
......@@ -6530,7 +6539,7 @@ class V8_EXPORT FunctionTemplate : public Template {
void SetCallHandler(
FunctionCallback callback, Local<Value> data = Local<Value>(),
SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
const CFunction* c_function = nullptr);
const std::vector<const CFunction*>& c_function_overloads = {});
/** Set the predefined length property for the FunctionTemplate. */
void SetLength(int length);
......
......@@ -1185,7 +1185,7 @@ void FunctionTemplate::SetPrototypeProviderTemplate(
Utils::OpenHandle(*prototype_provider);
Utils::ApiCheck(self->GetPrototypeTemplate().IsUndefined(i_isolate),
"v8::FunctionTemplate::SetPrototypeProviderTemplate",
"Protoype must be undefiend");
"Protoype must be undefined");
Utils::ApiCheck(self->GetParentTemplate().IsUndefined(i_isolate),
"v8::FunctionTemplate::SetPrototypeProviderTemplate",
"Prototype provider must be empty");
......@@ -1218,7 +1218,7 @@ static Local<FunctionTemplate> FunctionTemplateNew(
bool do_not_cache,
v8::Local<Private> cached_property_name = v8::Local<Private>(),
SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
const CFunction* c_function = nullptr) {
const std::vector<const CFunction*>& c_function_overloads = {}) {
i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(
i::FUNCTION_TEMPLATE_INFO_TYPE, i::AllocationType::kOld);
i::Handle<i::FunctionTemplateInfo> obj =
......@@ -1243,7 +1243,7 @@ static Local<FunctionTemplate> FunctionTemplateNew(
}
if (callback != nullptr) {
Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type,
c_function);
c_function_overloads);
}
return Utils::ToLocal(obj);
}
......@@ -1257,10 +1257,29 @@ Local<FunctionTemplate> FunctionTemplate::New(
// function templates when the isolate is created for serialization.
LOG_API(i_isolate, FunctionTemplate, New);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
auto templ = FunctionTemplateNew(i_isolate, callback, data, signature, length,
behavior, false, Local<Private>(),
side_effect_type, c_function);
return templ;
return FunctionTemplateNew(
i_isolate, callback, data, signature, length, behavior, false,
Local<Private>(), side_effect_type,
c_function ? std::vector<const CFunction*>{c_function}
: std::vector<const CFunction*>{});
}
Local<FunctionTemplate> FunctionTemplate::NewWithCFunctionOverloads(
Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
SideEffectType side_effect_type,
const std::vector<const CFunction*>& c_function_overloads) {
// Multiple overloads not supported yet.
Utils::ApiCheck(c_function_overloads.size() == 1,
"v8::FunctionTemplate::NewWithCFunctionOverloads",
"Function overloads not supported yet.");
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, FunctionTemplate, New);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
return FunctionTemplateNew(i_isolate, callback, data, signature, length,
behavior, false, Local<Private>(),
side_effect_type, c_function_overloads);
}
Local<FunctionTemplate> FunctionTemplate::NewWithCache(
......@@ -1291,10 +1310,10 @@ Local<AccessorSignature> AccessorSignature::New(
(obj)->setter(*foreign); \
} while (false)
void FunctionTemplate::SetCallHandler(FunctionCallback callback,
v8::Local<Value> data,
SideEffectType side_effect_type,
const CFunction* c_function) {
void FunctionTemplate::SetCallHandler(
FunctionCallback callback, v8::Local<Value> data,
SideEffectType side_effect_type,
const std::vector<const CFunction*>& c_function_overloads) {
auto info = Utils::OpenHandle(this);
EnsureNotPublished(info, "v8::FunctionTemplate::SetCallHandler");
i::Isolate* isolate = info->GetIsolate();
......@@ -1310,13 +1329,20 @@ void FunctionTemplate::SetCallHandler(FunctionCallback callback,
obj->set_data(*Utils::OpenHandle(*data));
// Blink passes CFunction's constructed with the default constructor
// for non-fast calls, so we should check the address too.
if (c_function != nullptr && c_function->GetAddress()) {
i::FunctionTemplateInfo::SetCFunction(
isolate, info,
i::handle(*FromCData(isolate, c_function->GetAddress()), isolate));
i::FunctionTemplateInfo::SetCSignature(
isolate, info,
i::handle(*FromCData(isolate, c_function->GetTypeInfo()), isolate));
if (!c_function_overloads.empty()) {
// Multiple overloads not supported yet.
Utils::ApiCheck(c_function_overloads.size() == 1,
"v8::FunctionTemplate::SetCallHandler",
"Function overloads not supported yet.");
const CFunction* c_function = c_function_overloads[0];
if (c_function != nullptr && c_function->GetAddress()) {
i::FunctionTemplateInfo::SetCFunction(
isolate, info,
i::handle(*FromCData(isolate, c_function->GetAddress()), isolate));
i::FunctionTemplateInfo::SetCSignature(
isolate, info,
i::handle(*FromCData(isolate, c_function->GetTypeInfo()), isolate));
}
}
info->set_call_code(*obj, kReleaseStore);
}
......
......@@ -284,6 +284,15 @@ Local<FunctionTemplate> Shell::CreateTestFastCApiTemplate(Isolate* isolate) {
Local<Value>(), signature, 1,
ConstructorBehavior::kThrow,
SideEffectType::kHasSideEffect, &add_all_c_func));
// To test function overloads.
api_obj_ctor->PrototypeTemplate()->Set(
isolate, "overloaded_add_all",
FunctionTemplate::NewWithCFunctionOverloads(
isolate, FastCApiObject::AddAllSlowCallback, Local<Value>(),
signature, 1, ConstructorBehavior::kThrow,
SideEffectType::kHasSideEffect, {&add_all_c_func}));
CFunction add_32bit_int_c_func =
CFunction::Make(FastCApiObject::Add32BitIntFastCallback);
api_obj_ctor->PrototypeTemplate()->Set(
......
......@@ -178,3 +178,15 @@ assertEquals(add_32bit_int_result, add_32bit_int_mismatch(false, -42, 45));
assertOptimized(add_32bit_int_mismatch);
assertEquals(1, fast_c_api.fast_call_count());
assertEquals(0, fast_c_api.slow_call_count());
// Test function overloads
function overloaded_add_all(should_fallback = false) {
return fast_c_api.overloaded_add_all(should_fallback,
-42, 45, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER,
max_safe_float * 0.5, Math.PI);
}
%PrepareFunctionForOptimization(overloaded_add_all);
assertEquals(add_all_result, overloaded_add_all());
%OptimizeFunctionOnNextCall(overloaded_add_all);
assertEquals(add_all_result, overloaded_add_all());
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