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; return;
} }
// write parameter array // 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; rOutStm.WriteChar('{') << endl;
std::vector<sal_uInt32> aSuperList; std::vector<sal_uInt32> aSuperList;
@ -304,7 +304,8 @@ void SvMetaClass::WriteSfx( SvIdlDataBase & rBase, SvStream & rOutStm )
rOutStm << endl; rOutStm << endl;
// write slotmap // 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; rOutStm.WriteChar( '{' ) << endl;
// write all attributes // write all attributes

View file

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

View file

@ -98,30 +98,33 @@ template<class T> SfxPoolItem* createSfxPoolItem()
{ {
return T::CreateDefault(); return T::CreateDefault();
} }
struct SfxType struct SfxType
{ {
std::function<SfxPoolItem* ()> createSfxPoolItemFunc; SfxPoolItem* (*createSfxPoolItemFunc)();
const std::type_info* pType; const std::type_info* pType;
sal_uInt16 nAttribs; sal_uInt16 nAttribs;
SfxTypeAttrib aAttrib[1]; // variable length
const std::type_info* Type() const{return pType;} const std::type_info* Type() const{return pType;}
std::unique_ptr<SfxPoolItem> CreateItem() const std::unique_ptr<SfxPoolItem> CreateItem() const
{ return std::unique_ptr<SfxPoolItem>(createSfxPoolItemFunc()); } { return std::unique_ptr<SfxPoolItem>(createSfxPoolItemFunc()); }
inline const SfxTypeAttrib& getAttrib(sal_uInt16 idx) const;
}; };
struct SfxType0 struct SfxTypeImpl : public SfxType
{ {
std::function<SfxPoolItem* ()> createSfxPoolItemFunc; SfxTypeAttrib aAttrib[1]; // variable length
const std::type_info* pType;
sal_uInt16 nAttribs;
const std::type_info* Type() const { return pType;}
}; };
#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]; \ SfxTypeAttrib aAttrib[n]; \
} }

View file

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

View file

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