make the slot data constinit

because it takes a surprising amount of time to initialise it
at runtime during startup

(*) have to convert the std::function in SfxType to a
function pointer, because the std::function constructor
is not constinit compatible.

(*) the SfxType0..SfxTypeN types need some reinterpret_cast
to work around the lack of zero-sized trailing arrays in c++

(*) Sadly MSVC does not support taking the address of symbols
in constinit structures, so we cannot make the SfxSlot
array constinit.

Change-Id: I300ee770cc115d30bc25c819f2ad34b29633876c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166963
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
Noel Grandin 2024-05-01 13:33:41 +02:00 committed by Noel Grandin
parent b26ff81a6f
commit d4c0e39d93
5 changed files with 66 additions and 93 deletions

View file

@ -269,7 +269,7 @@ void SvMetaClass::WriteSfx( SvIdlDataBase & rBase, SvStream & rOutStm )
return;
}
// write parameter array
rOutStm.WriteOString("static SfxFormalArgument a").WriteOString(GetName()).WriteOString("Args_Impl[] =") << endl;
rOutStm.WriteOString("static const SfxFormalArgument a").WriteOString(GetName()).WriteOString("Args_Impl[] =") << endl;
rOutStm.WriteChar('{') << endl;
std::vector<sal_uInt32> aSuperList;
@ -304,7 +304,8 @@ void SvMetaClass::WriteSfx( SvIdlDataBase & rBase, SvStream & rOutStm )
rOutStm << endl;
// write slotmap
rOutStm.WriteOString("static SfxSlot a").WriteOString(GetName()).WriteOString("Slots_Impl[] =") << endl;
rOutStm.WriteOString("static SfxSlot a").WriteOString(GetName())
.WriteOString("Slots_Impl[").WriteOString(OString::number(nSlotCount == 0 ? 1 : nSlotCount)).WriteOString("] =") << endl;
rOutStm.WriteChar( '{' ) << endl;
// write all attributes

View file

@ -242,7 +242,7 @@ void SvMetaType::WriteSfxItem(
rOutStm.WriteOString( "extern " );
if (bExport)
rOutStm.WriteOString( "SFX2_DLLPUBLIC " );
rOutStm.WriteOString( aTypeName )
rOutStm.WriteOString( "constinit const " ).WriteOString( aTypeName )
.WriteOString( aVarName ).WriteChar( ';' ) << endl;
if (bReturn)
return;
@ -252,7 +252,7 @@ void SvMetaType::WriteSfxItem(
rOutStm.WriteOString( "#if !defined(_WIN32) && (defined(DISABLE_DYNLOADING) && (defined(ANDROID) || defined(IOS) || defined(EMSCRIPTEN) || defined(LINUX)))" ) << endl;
rOutStm.WriteOString( "__attribute__((__weak__))" ) << endl;
rOutStm.WriteOString( "#endif" ) << endl;
rOutStm.WriteOString( aTypeName ).WriteOString( aVarName )
rOutStm.WriteOString( "constinit const " ).WriteOString( aTypeName ).WriteOString( aVarName )
.WriteOString( " = " ) << endl;
rOutStm.WriteChar( '{' ) << endl;

View file

@ -98,30 +98,33 @@ template<class T> SfxPoolItem* createSfxPoolItem()
{
return T::CreateDefault();
}
struct SfxType
{
std::function<SfxPoolItem* ()> createSfxPoolItemFunc;
SfxPoolItem* (*createSfxPoolItemFunc)();
const std::type_info* pType;
sal_uInt16 nAttribs;
SfxTypeAttrib aAttrib[1]; // variable length
const std::type_info* Type() const{return pType;}
std::unique_ptr<SfxPoolItem> CreateItem() const
{ return std::unique_ptr<SfxPoolItem>(createSfxPoolItemFunc()); }
inline const SfxTypeAttrib& getAttrib(sal_uInt16 idx) const;
};
struct SfxType0
struct SfxTypeImpl : public SfxType
{
std::function<SfxPoolItem* ()> createSfxPoolItemFunc;
const std::type_info* pType;
sal_uInt16 nAttribs;
const std::type_info* Type() const { return pType;}
SfxTypeAttrib aAttrib[1]; // variable length
};
#define SFX_DECL_TYPE(n) struct SfxType##n \
// Some casting to work around the lack of zero-sized trailing arrays in c++
inline const SfxTypeAttrib& SfxType::getAttrib(sal_uInt16 idx) const
{ return reinterpret_cast<const SfxTypeImpl*>(this)->aAttrib[idx]; }
struct SfxType0 : public SfxType
{
};
#define SFX_DECL_TYPE(n) struct SfxType##n : public SfxType \
{ \
std::function<SfxPoolItem* ()> createSfxPoolItemFunc; \
const std::type_info* pType; \
sal_uInt16 nAttribs; \
SfxTypeAttrib aAttrib[n]; \
}

View file

@ -60,37 +60,37 @@ using namespace ::com::sun::star::io;
// needs to be converted to a better data structure
SfxFormalArgument const aFormalArgs[] = {
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "SuggestedSaveAsName", SID_DEFAULTFILENAME },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "SuggestedSaveAsDir", SID_DEFAULTFILEPATH },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "VersionAuthor", SID_DOCINFO_AUTHOR },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "VersionComment", SID_DOCINFO_COMMENTS },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "DontTerminateEdit", FN_PARAM_1 },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "VersionMajor", SID_DOCINFO_MAJOR },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "FilterOptions", SID_FILE_FILTEROPTIONS },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "FilterName", SID_FILTER_NAME },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "Margin1", SID_RULER_MARGIN1 },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "Margin2", SID_RULER_MARGIN2 },
// { reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "FileName", SID_FILE_NAME },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "URL", SID_FILE_NAME },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "OpenFlags", SID_OPTIONS },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "Overwrite", SID_OVERWRITE },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "Password", SID_PASSWORD },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "PasswordInteraction", SID_PASSWORDINTERACTION },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "Referer", SID_REFERER },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "SaveTo", SID_SAVETO },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "TemplateName", SID_TEMPLATE_NAME },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "TemplateRegion", SID_TEMPLATE_REGIONNAME },
// { reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "Region", SID_TEMPLATE_REGIONNAME },
// { reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "Name", SID_TEMPLATE_NAME },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "Unpacked", SID_UNPACK },
{ reinterpret_cast<SfxType*>(&aSfxInt16Item_Impl), "Version", SID_VERSION },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "SaveACopy", SID_SAVEACOPYITEM },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "NoFileSync", SID_NO_FILE_SYNC },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "NoThumbnail", SID_NO_THUMBNAIL },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "NoEmbDataSet", SID_NO_EMBEDDED_DS },
{ reinterpret_cast<SfxType*>(&aSfxBoolItem_Impl), "IsRedactMode", SID_IS_REDACT_MODE },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "RedactionStyle", SID_REDACTION_STYLE },
{ reinterpret_cast<SfxType*>(&aSfxStringItem_Impl), "AdditionsTag", FN_PARAM_ADDITIONS_TAG },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "SuggestedSaveAsName", SID_DEFAULTFILENAME },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "SuggestedSaveAsDir", SID_DEFAULTFILEPATH },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "VersionAuthor", SID_DOCINFO_AUTHOR },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "VersionComment", SID_DOCINFO_COMMENTS },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "DontTerminateEdit", FN_PARAM_1 },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "VersionMajor", SID_DOCINFO_MAJOR },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "FilterOptions", SID_FILE_FILTEROPTIONS },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "FilterName", SID_FILTER_NAME },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "Margin1", SID_RULER_MARGIN1 },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "Margin2", SID_RULER_MARGIN2 },
// { static_cast<const SfxType*>(&aSfxStringItem_Impl), "FileName", SID_FILE_NAME },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "URL", SID_FILE_NAME },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "OpenFlags", SID_OPTIONS },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "Overwrite", SID_OVERWRITE },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "Password", SID_PASSWORD },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "PasswordInteraction", SID_PASSWORDINTERACTION },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "Referer", SID_REFERER },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "SaveTo", SID_SAVETO },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "TemplateName", SID_TEMPLATE_NAME },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "TemplateRegion", SID_TEMPLATE_REGIONNAME },
// { static_cast<const SfxType*>(&aSfxStringItem_Impl), "Region", SID_TEMPLATE_REGIONNAME },
// { static_cast<const SfxType*>(&aSfxStringItem_Impl), "Name", SID_TEMPLATE_NAME },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "Unpacked", SID_UNPACK },
{ static_cast<const SfxType*>(&aSfxInt16Item_Impl), "Version", SID_VERSION },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "SaveACopy", SID_SAVEACOPYITEM },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "NoFileSync", SID_NO_FILE_SYNC },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "NoThumbnail", SID_NO_THUMBNAIL },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "NoEmbDataSet", SID_NO_EMBEDDED_DS },
{ static_cast<const SfxType*>(&aSfxBoolItem_Impl), "IsRedactMode", SID_IS_REDACT_MODE },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "RedactionStyle", SID_REDACTION_STYLE },
{ static_cast<const SfxType*>(&aSfxStringItem_Impl), "AdditionsTag", FN_PARAM_ADDITIONS_TAG },
};
sal_uInt16 const nMediaArgsCount = SAL_N_ELEMENTS(aFormalArgs);
@ -242,9 +242,9 @@ void TransformParameters( sal_uInt16 nSlotId, const uno::Sequence<beans::Propert
for ( nSub=0; nSub<nSubCount; nSub++ )
{
// search sub item by name
if ( rPropValue.Name == (pSlot->aUnoName + "." + pType->aAttrib[nSub].aName) )
if ( rPropValue.Name == (pSlot->aUnoName + "." + pType->getAttrib(nSub).aName) )
{
sal_uInt8 nSubId = static_cast<sal_uInt8>(static_cast<sal_Int8>(pType->aAttrib[nSub].nAID));
sal_uInt8 nSubId = static_cast<sal_uInt8>(static_cast<sal_Int8>(pType->getAttrib(nSub).nAID));
if ( bConvertTwips )
nSubId |= CONVERT_TWIPS;
if ( pItem->PutValue( rPropValue.Value, nSubId ) )
@ -344,14 +344,14 @@ void TransformParameters( sal_uInt16 nSlotId, const uno::Sequence<beans::Propert
for ( sal_uInt16 nSub=0; nSub<nSubCount; nSub++ )
{
// search sub item by name
if ( rProp.Name == (rArg.aName + "." + pType->aAttrib[nSub].aName) )
if ( rProp.Name == (rArg.aName + "." + pType->getAttrib(nSub).aName) )
{
// at least one member found ...
bRet = true;
#ifdef DBG_UTIL
++nFoundArgs;
#endif
sal_uInt8 nSubId = static_cast<sal_uInt8>(static_cast<sal_Int8>(pType->aAttrib[nSub].nAID));
sal_uInt8 nSubId = static_cast<sal_uInt8>(static_cast<sal_Int8>(pType->getAttrib(nSub).nAID));
if ( bConvertTwips )
nSubId |= CONVERT_TWIPS;
if (!pItem->PutValue( rProp.Value, nSubId ) )
@ -1311,17 +1311,17 @@ void TransformItems( sal_uInt16 nSlotId, const SfxItemSet& rSet, uno::Sequence<b
// complex type, add a property value for every member of the struct
for ( sal_uInt16 n=1; n<=nSubCount; ++n )
{
sal_uInt8 nSubId = static_cast<sal_uInt8>(static_cast<sal_Int8>(pType->aAttrib[n-1].nAID));
sal_uInt8 nSubId = static_cast<sal_uInt8>(static_cast<sal_Int8>(pType->getAttrib(n-1).nAID));
if ( bConvertTwips )
nSubId |= CONVERT_TWIPS;
DBG_ASSERT(( pType->aAttrib[n-1].nAID ) <= 127, "Member ID out of range" );
DBG_ASSERT(( pType->getAttrib(n-1).nAID ) <= 127, "Member ID out of range" );
pValue[nActProp].Name = pSlot->aUnoName +
"." +
pType->aAttrib[n-1].aName;
pType->getAttrib(n-1).aName;
if ( !pItem->QueryValue( pValue[nActProp++].Value, nSubId ) )
{
SAL_WARN( "sfx", "Sub item " << pType->aAttrib[n-1].nAID
SAL_WARN( "sfx", "Sub item " << pType->getAttrib(n-1).nAID
<< " not convertible in slot: " << nSlotId );
}
}
@ -1356,18 +1356,18 @@ void TransformItems( sal_uInt16 nSlotId, const SfxItemSet& rSet, uno::Sequence<b
// complex type, add a property value for every member of the struct
for ( sal_uInt16 n = 1; n <= nSubCount; ++n )
{
sal_uInt8 nSubId = static_cast<sal_uInt8>(static_cast<sal_Int8>(rArg.pType->aAttrib[n-1].nAID));
sal_uInt8 nSubId = static_cast<sal_uInt8>(static_cast<sal_Int8>(rArg.pType->getAttrib(n-1).nAID));
if ( bConvertTwips )
nSubId |= CONVERT_TWIPS;
DBG_ASSERT((rArg.pType->aAttrib[n-1].nAID) <= 127, "Member ID out of range" );
DBG_ASSERT((rArg.pType->getAttrib(n-1).nAID) <= 127, "Member ID out of range" );
pValue[nActProp].Name = rArg.aName +
"." +
rArg.pType->aAttrib[n-1].aName ;
rArg.pType->getAttrib(n-1).aName ;
if ( !pItem->QueryValue( pValue[nActProp++].Value, nSubId ) )
{
SAL_WARN( "sfx", "Sub item "
<< rArg.pType->aAttrib[n-1].nAID
<< rArg.pType->getAttrib(n-1).nAID
<< " not convertible in slot: "
<< rArg.nSlotId );
}

View file

@ -30,12 +30,6 @@
extern "C" {
static int
SfxCompareSlots_qsort( const void* pSmaller, const void* pBigger )
{
return static_cast<int>(static_cast<SfxSlot const *>(pSmaller)->GetSlotId()) -
static_cast<int>(static_cast<SfxSlot const *>(pBigger)->GetSlotId());
}
static int
SfxCompareSlots_bsearch( const void* pSmaller, const void* pBigger )
@ -113,39 +107,14 @@ void SfxInterface::SetSlotMap( SfxSlot& rSlotMap, sal_uInt16 nSlotCount )
pSlots = &rSlotMap;
nCount = nSlotCount;
SfxSlot* pIter = pSlots;
if ( 1 == nCount && !pIter->pNextSlot )
pIter->pNextSlot = pIter;
if ( !pIter->pNextSlot )
{
// sort the SfxSlots by id
qsort( pSlots, nCount, sizeof(SfxSlot), SfxCompareSlots_qsort );
// link masters and slaves
sal_uInt16 nIter = 1;
for ( pIter = pSlots; nIter <= nCount; ++pIter, ++nIter )
assert(std::is_sorted(pSlots, pSlots + nCount,
[](const SfxSlot& rLHS, const SfxSlot& rRHS)
{
assert( nIter == nCount ||
pIter->GetSlotId() != (pIter+1)->GetSlotId() );
if ( nullptr == pIter->GetNextSlot() )
{
// Slots referring in circle to the next with the same
// Status method.
SfxSlot *pLastSlot = pIter;
for ( sal_uInt16 n = nIter; n < Count(); ++n )
{
SfxSlot *pCurSlot = pSlots+n;
if ( pCurSlot->GetStateFnc() == pIter->GetStateFnc() )
{
pLastSlot->pNextSlot = pCurSlot;
pLastSlot = pCurSlot;
}
}
pLastSlot->pNextSlot = pIter;
}
}
return rLHS.GetSlotId() < rRHS.GetSlotId();
}));
}
#ifdef DBG_UTIL
else