Skip to content

Commit ad4eab0

Browse files
paolosevMSFTV8 LUCI CQ
authored andcommitted
[fastcall] Store multiple CFunction overloads in FunctionTemplateInfo
In order to support Fast API calls with overloads, store a FixedArray of c-function addresses and a FixedArray of the corresponding FunctionInfo*. For now keep using only the first function in the array. Bug: v8:11739 Change-Id: If23381aa9d04c5cd830043951da9c53836a36328 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2876592 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Commit-Queue: Paolo Severini <paolosev@microsoft.com> Cr-Commit-Position: refs/heads/master@{#74643}
1 parent 26ee13b commit ad4eab0

14 files changed

Lines changed: 172 additions & 69 deletions

File tree

include/v8.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6506,7 +6506,7 @@ class V8_EXPORT FunctionTemplate : public Template {
65066506
Local<Signature> signature = Local<Signature>(), int length = 0,
65076507
ConstructorBehavior behavior = ConstructorBehavior::kAllow,
65086508
SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
6509-
const std::vector<const CFunction*>& c_function_overloads = {});
6509+
const MemorySpan<const CFunction>& c_function_overloads = {});
65106510

65116511
/**
65126512
* Creates a function template backed/cached by a private property.
@@ -6539,7 +6539,7 @@ class V8_EXPORT FunctionTemplate : public Template {
65396539
void SetCallHandler(
65406540
FunctionCallback callback, Local<Value> data = Local<Value>(),
65416541
SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
6542-
const std::vector<const CFunction*>& c_function_overloads = {});
6542+
const MemorySpan<const CFunction>& c_function_overloads = {});
65436543

65446544
/** Set the predefined length property for the FunctionTemplate. */
65456545
void SetLength(int length);

src/api/api.cc

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,7 +1218,7 @@ static Local<FunctionTemplate> FunctionTemplateNew(
12181218
bool do_not_cache,
12191219
v8::Local<Private> cached_property_name = v8::Local<Private>(),
12201220
SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
1221-
const std::vector<const CFunction*>& c_function_overloads = {}) {
1221+
const MemorySpan<const CFunction>& c_function_overloads = {}) {
12221222
i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(
12231223
i::FUNCTION_TEMPLATE_INFO_TYPE, i::AllocationType::kOld);
12241224
i::Handle<i::FunctionTemplateInfo> obj =
@@ -1260,20 +1260,15 @@ Local<FunctionTemplate> FunctionTemplate::New(
12601260
return FunctionTemplateNew(
12611261
i_isolate, callback, data, signature, length, behavior, false,
12621262
Local<Private>(), side_effect_type,
1263-
c_function ? std::vector<const CFunction*>{c_function}
1264-
: std::vector<const CFunction*>{});
1263+
c_function ? MemorySpan<const CFunction>{c_function, 1}
1264+
: MemorySpan<const CFunction>{});
12651265
}
12661266

12671267
Local<FunctionTemplate> FunctionTemplate::NewWithCFunctionOverloads(
12681268
Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
12691269
v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
12701270
SideEffectType side_effect_type,
1271-
const std::vector<const CFunction*>& c_function_overloads) {
1272-
// Multiple overloads not supported yet.
1273-
Utils::ApiCheck(c_function_overloads.size() == 1,
1274-
"v8::FunctionTemplate::NewWithCFunctionOverloads",
1275-
"Function overloads not supported yet.");
1276-
1271+
const MemorySpan<const CFunction>& c_function_overloads) {
12771272
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
12781273
LOG_API(i_isolate, FunctionTemplate, New);
12791274
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
@@ -1313,7 +1308,7 @@ Local<AccessorSignature> AccessorSignature::New(
13131308
void FunctionTemplate::SetCallHandler(
13141309
FunctionCallback callback, v8::Local<Value> data,
13151310
SideEffectType side_effect_type,
1316-
const std::vector<const CFunction*>& c_function_overloads) {
1311+
const MemorySpan<const CFunction>& c_function_overloads) {
13171312
auto info = Utils::OpenHandle(this);
13181313
EnsureNotPublished(info, "v8::FunctionTemplate::SetCallHandler");
13191314
i::Isolate* isolate = info->GetIsolate();
@@ -1327,22 +1322,28 @@ void FunctionTemplate::SetCallHandler(
13271322
data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
13281323
}
13291324
obj->set_data(*Utils::OpenHandle(*data));
1330-
// Blink passes CFunction's constructed with the default constructor
1331-
// for non-fast calls, so we should check the address too.
1332-
if (!c_function_overloads.empty()) {
1333-
// Multiple overloads not supported yet.
1334-
Utils::ApiCheck(c_function_overloads.size() == 1,
1335-
"v8::FunctionTemplate::SetCallHandler",
1336-
"Function overloads not supported yet.");
1337-
const CFunction* c_function = c_function_overloads[0];
1338-
if (c_function != nullptr && c_function->GetAddress()) {
1339-
i::FunctionTemplateInfo::SetCFunction(
1340-
isolate, info,
1341-
i::handle(*FromCData(isolate, c_function->GetAddress()), isolate));
1342-
i::FunctionTemplateInfo::SetCSignature(
1343-
isolate, info,
1344-
i::handle(*FromCData(isolate, c_function->GetTypeInfo()), isolate));
1325+
if (c_function_overloads.size() > 0) {
1326+
// Stores the data for a sequence of CFunction overloads into a single
1327+
// FixedArray, as [address_0, signature_0, ... address_n-1, signature_n-1].
1328+
i::Handle<i::FixedArray> function_overloads =
1329+
isolate->factory()->NewFixedArray(static_cast<int>(
1330+
c_function_overloads.size() *
1331+
i::FunctionTemplateInfo::kFunctionOverloadEntrySize));
1332+
int function_count = static_cast<int>(c_function_overloads.size());
1333+
for (int i = 0; i < function_count; i++) {
1334+
const CFunction& c_function = c_function_overloads.data()[i];
1335+
i::Handle<i::Object> address =
1336+
FromCData(isolate, c_function.GetAddress());
1337+
function_overloads->set(
1338+
i::FunctionTemplateInfo::kFunctionOverloadEntrySize * i, *address);
1339+
i::Handle<i::Object> signature =
1340+
FromCData(isolate, c_function.GetTypeInfo());
1341+
function_overloads->set(
1342+
i::FunctionTemplateInfo::kFunctionOverloadEntrySize * i + 1,
1343+
*signature);
13451344
}
1345+
i::FunctionTemplateInfo::SetCFunctionOverloads(isolate, info,
1346+
function_overloads);
13461347
}
13471348
info->set_call_code(*obj, kReleaseStore);
13481349
}

src/compiler/heap-refs.cc

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,10 @@ class FunctionTemplateInfoData : public HeapObjectData {
234234

235235
void SerializeCallCode(JSHeapBroker* broker);
236236
ObjectData* call_code() const { return call_code_; }
237-
Address c_function() const { return c_function_; }
238-
const CFunctionInfo* c_signature() const { return c_signature_; }
237+
ZoneVector<Address> c_functions() const { return c_functions_; }
238+
ZoneVector<const CFunctionInfo*> c_signatures() const {
239+
return c_signatures_;
240+
}
239241
KnownReceiversMap& known_receivers() { return known_receivers_; }
240242

241243
private:
@@ -244,8 +246,8 @@ class FunctionTemplateInfoData : public HeapObjectData {
244246
bool has_call_code_ = false;
245247

246248
ObjectData* call_code_ = nullptr;
247-
const Address c_function_;
248-
const CFunctionInfo* const c_signature_;
249+
ZoneVector<Address> c_functions_;
250+
ZoneVector<const CFunctionInfo*> c_signatures_;
249251
KnownReceiversMap known_receivers_;
250252
};
251253

@@ -265,15 +267,50 @@ class CallHandlerInfoData : public HeapObjectData {
265267
ObjectData* data_ = nullptr;
266268
};
267269

270+
namespace {
271+
272+
ZoneVector<Address> GetCFunctions(FixedArray function_overloads, Zone* zone) {
273+
const int len = function_overloads.length() /
274+
FunctionTemplateInfo::kFunctionOverloadEntrySize;
275+
ZoneVector<Address> c_functions = ZoneVector<Address>(len, zone);
276+
for (int i = 0; i < len; i++) {
277+
c_functions[i] = v8::ToCData<Address>(function_overloads.get(
278+
FunctionTemplateInfo::kFunctionOverloadEntrySize * i));
279+
}
280+
return c_functions;
281+
}
282+
283+
ZoneVector<const CFunctionInfo*> GetCSignatures(FixedArray function_overloads,
284+
Zone* zone) {
285+
const int len = function_overloads.length() /
286+
FunctionTemplateInfo::kFunctionOverloadEntrySize;
287+
ZoneVector<const CFunctionInfo*> c_signatures =
288+
ZoneVector<const CFunctionInfo*>(len, zone);
289+
for (int i = 0; i < len; i++) {
290+
c_signatures[i] = v8::ToCData<const CFunctionInfo*>(function_overloads.get(
291+
FunctionTemplateInfo::kFunctionOverloadEntrySize * i + 1));
292+
}
293+
return c_signatures;
294+
}
295+
296+
} // namespace
297+
268298
FunctionTemplateInfoData::FunctionTemplateInfoData(
269299
JSHeapBroker* broker, ObjectData** storage,
270300
Handle<FunctionTemplateInfo> object)
271301
: HeapObjectData(broker, storage, object),
272-
c_function_(v8::ToCData<Address>(object->GetCFunction())),
273-
c_signature_(v8::ToCData<CFunctionInfo*>(object->GetCSignature())),
302+
c_functions_(broker->zone()),
303+
c_signatures_(broker->zone()),
274304
known_receivers_(broker->zone()) {
275305
DCHECK(!broker->is_concurrent_inlining());
306+
276307
auto function_template_info = Handle<FunctionTemplateInfo>::cast(object);
308+
309+
FixedArray function_overloads_array =
310+
FixedArray::cast(function_template_info->GetCFunctionOverloads());
311+
c_functions_ = GetCFunctions(function_overloads_array, broker->zone());
312+
c_signatures_ = GetCSignatures(function_overloads_array, broker->zone());
313+
277314
is_signature_undefined_ =
278315
function_template_info->signature().IsUndefined(broker->isolate());
279316
accept_any_receiver_ = function_template_info->accept_any_receiver();
@@ -3693,18 +3730,20 @@ Address CallHandlerInfoRef::callback() const {
36933730
return HeapObjectRef::data()->AsCallHandlerInfo()->callback();
36943731
}
36953732

3696-
Address FunctionTemplateInfoRef::c_function() const {
3733+
ZoneVector<Address> FunctionTemplateInfoRef::c_functions() const {
36973734
if (data_->should_access_heap()) {
3698-
return v8::ToCData<Address>(object()->GetCFunction());
3735+
return GetCFunctions(FixedArray::cast(object()->GetCFunctionOverloads()),
3736+
broker()->zone());
36993737
}
3700-
return HeapObjectRef::data()->AsFunctionTemplateInfo()->c_function();
3738+
return HeapObjectRef::data()->AsFunctionTemplateInfo()->c_functions();
37013739
}
37023740

3703-
const CFunctionInfo* FunctionTemplateInfoRef::c_signature() const {
3741+
ZoneVector<const CFunctionInfo*> FunctionTemplateInfoRef::c_signatures() const {
37043742
if (data_->should_access_heap()) {
3705-
return v8::ToCData<CFunctionInfo*>(object()->GetCSignature());
3743+
return GetCSignatures(FixedArray::cast(object()->GetCFunctionOverloads()),
3744+
broker()->zone());
37063745
}
3707-
return HeapObjectRef::data()->AsFunctionTemplateInfo()->c_signature();
3746+
return HeapObjectRef::data()->AsFunctionTemplateInfo()->c_signatures();
37083747
}
37093748

37103749
bool StringRef::IsSeqString() const {

src/compiler/heap-refs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -738,8 +738,8 @@ class FunctionTemplateInfoRef : public HeapObjectRef {
738738

739739
void SerializeCallCode();
740740
base::Optional<CallHandlerInfoRef> call_code() const;
741-
Address c_function() const;
742-
const CFunctionInfo* c_signature() const;
741+
ZoneVector<Address> c_functions() const;
742+
ZoneVector<const CFunctionInfo*> c_signatures() const;
743743

744744
HolderLookupResult LookupHolderOfExpectedType(
745745
MapRef receiver_map,

src/compiler/js-call-reducer.cc

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -890,17 +890,17 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
890890
Node* holder, const SharedFunctionInfoRef shared, Node* target,
891891
const int arity, Node* effect)
892892
: JSCallReducerAssembler(reducer, node),
893-
c_function_(function_template_info.c_function()),
894-
c_signature_(function_template_info.c_signature()),
893+
c_functions_(function_template_info.c_functions()),
894+
c_signatures_(function_template_info.c_signatures()),
895895
function_template_info_(function_template_info),
896896
receiver_(receiver),
897897
holder_(holder),
898898
shared_(shared),
899899
target_(target),
900900
arity_(arity) {
901901
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
902-
DCHECK_NE(c_function_, kNullAddress);
903-
CHECK_NOT_NULL(c_signature_);
902+
CHECK_GT(c_functions_.size(), 0);
903+
CHECK_GT(c_signatures_.size(), 0);
904904
InitializeEffectControl(effect, NodeProperties::GetControlInput(node));
905905
}
906906

@@ -909,13 +909,16 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
909909
// C arguments include the receiver at index 0. Thus C index 1 corresponds
910910
// to the JS argument 0, etc.
911911
const int c_argument_count =
912-
static_cast<int>(c_signature_->ArgumentCount());
912+
static_cast<int>(c_signatures_[0]->ArgumentCount());
913913
CHECK_GE(c_argument_count, kReceiver);
914914

915915
int cursor = 0;
916916
base::SmallVector<Node*, kInlineSize> inputs(c_argument_count + arity_ +
917917
kExtraInputsCount);
918-
inputs[cursor++] = ExternalConstant(ExternalReference::Create(c_function_));
918+
// Multiple function overloads not supported yet, always call the first
919+
// overload.
920+
inputs[cursor++] =
921+
ExternalConstant(ExternalReference::Create(c_functions_[0]));
919922

920923
inputs[cursor++] = n.receiver();
921924

@@ -987,12 +990,12 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
987990
TNode<Object> FastApiCall(CallDescriptor* descriptor, Node** inputs,
988991
size_t inputs_size) {
989992
return AddNode<Object>(graph()->NewNode(
990-
simplified()->FastApiCall(c_signature_, feedback(), descriptor),
993+
simplified()->FastApiCall(c_signatures_[0], feedback(), descriptor),
991994
static_cast<int>(inputs_size), inputs));
992995
}
993996

994-
const Address c_function_;
995-
const CFunctionInfo* const c_signature_;
997+
const ZoneVector<Address> c_functions_;
998+
const ZoneVector<const CFunctionInfo*> c_signatures_;
996999
const FunctionTemplateInfoRef function_template_info_;
9971000
Node* const receiver_;
9981001
Node* const holder_;
@@ -3539,11 +3542,13 @@ bool Has64BitIntegerParamsInSignature(const CFunctionInfo* c_signature) {
35393542

35403543
bool CanOptimizeFastCall(
35413544
const FunctionTemplateInfoRef& function_template_info) {
3542-
const CFunctionInfo* c_signature = function_template_info.c_signature();
3545+
if (function_template_info.c_functions().empty()) return false;
35433546

3544-
bool optimize_to_fast_call =
3545-
FLAG_turbo_fast_api_calls &&
3546-
function_template_info.c_function() != kNullAddress;
3547+
// Multiple function overloads not supported yet, always call the first
3548+
// overload.
3549+
const CFunctionInfo* c_signature = function_template_info.c_signatures()[0];
3550+
3551+
bool optimize_to_fast_call = FLAG_turbo_fast_api_calls;
35473552
#ifndef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
35483553
optimize_to_fast_call =
35493554
optimize_to_fast_call && !HasFPParamsInSignature(c_signature);

src/d8/d8-test.cc

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ class FastCApiObject {
5555
static_cast<double>(arg_i64) + static_cast<double>(arg_u64) +
5656
static_cast<double>(arg_f32) + arg_f64;
5757
}
58+
static double AddAllFastCallback_5Args(Local<Object> receiver,
59+
bool should_fallback, int32_t arg_i32,
60+
uint32_t arg_u32, int64_t arg_i64,
61+
uint64_t arg_u64, float arg_f32,
62+
FastApiCallbackOptions& options) {
63+
return AddAllFastCallback(receiver, should_fallback, arg_i32, arg_u32,
64+
arg_i64, arg_u64, arg_f32, 0, options);
65+
}
5866
static void AddAllSlowCallback(const FunctionCallbackInfo<Value>& args) {
5967
Isolate* isolate = args.GetIsolate();
6068

@@ -283,12 +291,16 @@ Local<FunctionTemplate> Shell::CreateTestFastCApiTemplate(Isolate* isolate) {
283291
SideEffectType::kHasSideEffect, &add_all_c_func));
284292

285293
// To test function overloads.
294+
CFunction add_all_5args_c_func =
295+
CFunction::Make(FastCApiObject::AddAllFastCallback_5Args);
296+
const CFunction c_function_overloads[] = {add_all_c_func,
297+
add_all_5args_c_func};
286298
api_obj_ctor->PrototypeTemplate()->Set(
287299
isolate, "overloaded_add_all",
288300
FunctionTemplate::NewWithCFunctionOverloads(
289301
isolate, FastCApiObject::AddAllSlowCallback, Local<Value>(),
290302
signature, 1, ConstructorBehavior::kThrow,
291-
SideEffectType::kHasSideEffect, {&add_all_c_func}));
303+
SideEffectType::kHasSideEffect, {c_function_overloads, 2}));
292304

293305
CFunction add_32bit_int_c_func =
294306
CFunction::Make(FastCApiObject::Add32BitIntFastCallback);

src/diagnostics/objects-debug.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,12 @@ void StackFrameInfo::StackFrameInfoVerify(Isolate* isolate) {
17461746
#endif // V8_ENABLE_WEBASSEMBLY
17471747
}
17481748

1749+
void FunctionTemplateRareData::FunctionTemplateRareDataVerify(
1750+
Isolate* isolate) {
1751+
CHECK(c_function_overloads().IsFixedArray() ||
1752+
c_function_overloads().IsUndefined(isolate));
1753+
}
1754+
17491755
#endif // VERIFY_HEAP
17501756

17511757
#ifdef DEBUG

src/heap/factory-base.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,18 @@ Handle<SwissNameDictionary> FactoryBase<Impl>::NewSwissNameDictionary(
897897
SwissNameDictionary::CapacityFor(at_least_space_for), allocation);
898898
}
899899

900+
template <typename Impl>
901+
Handle<FunctionTemplateRareData>
902+
FactoryBase<Impl>::NewFunctionTemplateRareData() {
903+
auto function_template_rare_data =
904+
NewStructInternal<FunctionTemplateRareData>(
905+
FUNCTION_TEMPLATE_RARE_DATA_TYPE, AllocationType::kOld);
906+
DisallowGarbageCollection no_gc;
907+
function_template_rare_data.set_c_function_overloads(
908+
*impl()->empty_fixed_array(), SKIP_WRITE_BARRIER);
909+
return handle(function_template_rare_data, isolate());
910+
}
911+
900912
// Instantiate FactoryBase for the two variants we want.
901913
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) FactoryBase<Factory>;
902914
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)

src/heap/factory-base.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase
228228
Handle<SwissNameDictionary> NewSwissNameDictionaryWithCapacity(
229229
int capacity, AllocationType allocation);
230230

231+
Handle<FunctionTemplateRareData> NewFunctionTemplateRareData();
232+
231233
protected:
232234
// Allocate memory for an uninitialized array (e.g., a FixedArray or similar).
233235
HeapObject AllocateRawArray(int size, AllocationType allocation);

src/logging/log.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,9 +2274,10 @@ void ExistingCodeLogger::LogExistingFunction(
22742274
CALL_CODE_EVENT_HANDLER(CallbackEvent(fun_name, entry_point))
22752275

22762276
// Fast API function.
2277-
Address c_function = v8::ToCData<Address>(fun_data->GetCFunction());
2278-
if (c_function != kNullAddress) {
2279-
CALL_CODE_EVENT_HANDLER(CallbackEvent(fun_name, c_function))
2277+
int c_functions_count = fun_data->GetCFunctionsCount();
2278+
for (int i = 0; i < c_functions_count; i++) {
2279+
CALL_CODE_EVENT_HANDLER(
2280+
CallbackEvent(fun_name, fun_data->GetCFunction(i)))
22802281
}
22812282
}
22822283
}

0 commit comments

Comments
 (0)