Reduce code bloat, by cleaning up QMetaTypeFunctionHelper
Create and Delete wrappers are not necessary, because they can be easily simulated with Construct and Destruct. This change removes redundant function wrappers and a bit of over-optimized code. Gain is quite big: Before: text data bss dec hex filename 5366008 47460 14904 5428372 52d494 libQt5Core.so.5.5.0 505578 7060 2124 514762 7daca libQt5DBus.so.5.5.0 5591079 134656 6728 5732463 57786f libQt5Gui.so.5.5.0 1398785 31676 2576 1433037 15ddcd libQt5Network.so.5.5.0 6642431 220952 2536 6865919 68c3ff libQt5Widgets.so.5.5.0 After: text data bss dec hex filename 5342559 47460 14904 5404923 5278fb libQt5Core.so.5.5.0 496025 7068 2124 505217 7b581 libQt5DBus.so.5.5.0 5579291 134272 6728 5720291 5748e3 libQt5Gui.so.5.5.0 1389461 31676 2576 1423713 15b961 libQt5Network.so.5.5.0 6637139 220952 2536 6860627 68af53 libQt5Widgets.so.5.5.0 Cost of the change, is moved to CPU while calling QMetaType create() and destroy(), these two functions became a bit slower. The cost should not be visible, because they call operator new anyway. Change-Id: I34fd410343377d9c29925675d7da8172bfda9ce6 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
parent
78e0e72eb5
commit
3d575d4845
@ -882,24 +882,43 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
|
||||
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\since 5.0
|
||||
\internal
|
||||
\since 5.0
|
||||
\overload
|
||||
Don't use, kept for binary compatibility
|
||||
|
||||
Registers a user type for marshalling, with \a normalizedTypeName, a \a
|
||||
deleter, a \a creator, a \a destructor, a \a constructor, and
|
||||
a \a size. Returns the type's handle, or -1 if the type could
|
||||
not be registered. Note that normalizedTypeName is not checked for
|
||||
conformance with Qt's normalized format, so it must already
|
||||
conform.
|
||||
*/
|
||||
### TODO Qt6: remove me
|
||||
*/
|
||||
int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter,
|
||||
Creator creator,
|
||||
Destructor destructor,
|
||||
Constructor constructor,
|
||||
int size, TypeFlags flags, const QMetaObject *metaObject)
|
||||
{
|
||||
Q_UNUSED(deleter);
|
||||
Q_UNUSED(creator);
|
||||
return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\since 5.5
|
||||
|
||||
Registers a user type for marshalling, with \a normalizedTypeName,
|
||||
a \a destructor, a \a constructor, and a \a size. Returns the type's
|
||||
handle, or -1 if the type could not be registered.
|
||||
|
||||
\note normalizedTypeName is not checked for conformance with
|
||||
Qt's normalized format, so it must already conform.
|
||||
*/
|
||||
int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
|
||||
Destructor destructor,
|
||||
Constructor constructor,
|
||||
int size, TypeFlags flags, const QMetaObject *metaObject)
|
||||
{
|
||||
QVector<QCustomTypeInfo> *ct = customTypes();
|
||||
if (!ct || normalizedTypeName.isEmpty() || !deleter || !creator || !destructor || !constructor)
|
||||
if (!ct || normalizedTypeName.isEmpty() || !destructor || !constructor)
|
||||
return -1;
|
||||
|
||||
int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
|
||||
@ -914,8 +933,6 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
|
||||
if (idx == UnknownType) {
|
||||
QCustomTypeInfo inf;
|
||||
inf.typeName = normalizedTypeName;
|
||||
inf.creator = creator;
|
||||
inf.deleter = deleter;
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
inf.loadOp = 0;
|
||||
inf.saveOp = 0;
|
||||
@ -1016,8 +1033,6 @@ int QMetaType::registerNormalizedTypedef(const NS(QByteArray) &normalizedTypeNam
|
||||
QCustomTypeInfo inf;
|
||||
inf.typeName = normalizedTypeName;
|
||||
inf.alias = aliasId;
|
||||
inf.creator = 0;
|
||||
inf.deleter = 0;
|
||||
ct->append(inf);
|
||||
return aliasId;
|
||||
}
|
||||
@ -1566,60 +1581,6 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
|
||||
return true;
|
||||
}
|
||||
#endif // QT_NO_DATASTREAM
|
||||
namespace {
|
||||
class TypeCreator {
|
||||
template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
|
||||
struct CreatorImpl {
|
||||
static void *Create(const int /* type */, const void *copy)
|
||||
{
|
||||
// Using QMetaTypeFunctionHelper<T>::Create adds function call cost, even if it is a template (gcc).
|
||||
// This "copy" check is moved out from the switcher by compiler (at least by gcc)
|
||||
return copy ? new T(*static_cast<const T*>(copy)) : new T();
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct CreatorImpl<T, /* IsAcceptedType = */ false> {
|
||||
static void *Create(const int type, const void *copy)
|
||||
{
|
||||
if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) {
|
||||
if (Q_LIKELY(qMetaTypeGuiHelper))
|
||||
return qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].creator(copy);
|
||||
}
|
||||
if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) {
|
||||
if (Q_LIKELY(qMetaTypeWidgetsHelper))
|
||||
return qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].creator(copy);
|
||||
}
|
||||
// This point can be reached only for known types that definition is not available, for example
|
||||
// in bootstrap mode. We have no other choice then ignore it.
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
public:
|
||||
TypeCreator(const int type)
|
||||
: m_type(type)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
void *delegate(const T *copy) { return CreatorImpl<T>::Create(m_type, copy); }
|
||||
void *delegate(const void*) { return 0; }
|
||||
void *delegate(const QMetaTypeSwitcher::UnknownType *) { return 0; }
|
||||
void *delegate(const QMetaTypeSwitcher::NotBuiltinType *copy)
|
||||
{
|
||||
QMetaType::Creator creator;
|
||||
const QVector<QCustomTypeInfo> * const ct = customTypes();
|
||||
{
|
||||
QReadLocker locker(customTypesLock());
|
||||
if (Q_UNLIKELY(m_type < QMetaType::User || !ct || ct->count() <= m_type - QMetaType::User))
|
||||
return 0;
|
||||
creator = ct->at(m_type - QMetaType::User).creator;
|
||||
}
|
||||
Q_ASSERT_X(creator, "void *QMetaType::create(int type, const void *copy)", "The type was not properly registered");
|
||||
return creator(copy);
|
||||
}
|
||||
private:
|
||||
const int m_type;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
/*!
|
||||
Returns a copy of \a copy, assuming it is of type \a type. If \a
|
||||
@ -1629,65 +1590,11 @@ private:
|
||||
*/
|
||||
void *QMetaType::create(int type, const void *copy)
|
||||
{
|
||||
TypeCreator typeCreator(type);
|
||||
return QMetaTypeSwitcher::switcher<void*>(typeCreator, type, copy);
|
||||
QMetaType info(type);
|
||||
int size = info.sizeOf();
|
||||
return info.construct(operator new(size), copy);
|
||||
}
|
||||
|
||||
namespace {
|
||||
class TypeDestroyer {
|
||||
template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
|
||||
struct DestroyerImpl {
|
||||
static void Destroy(const int /* type */, void *where) { QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Delete(where); }
|
||||
};
|
||||
template<typename T>
|
||||
struct DestroyerImpl<T, /* IsAcceptedType = */ false> {
|
||||
static void Destroy(const int type, void *where)
|
||||
{
|
||||
if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) {
|
||||
if (Q_LIKELY(qMetaTypeGuiHelper))
|
||||
qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].deleter(where);
|
||||
return;
|
||||
}
|
||||
if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) {
|
||||
if (Q_LIKELY(qMetaTypeWidgetsHelper))
|
||||
qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].deleter(where);
|
||||
return;
|
||||
}
|
||||
// This point can be reached only for known types that definition is not available, for example
|
||||
// in bootstrap mode. We have no other choice then ignore it.
|
||||
}
|
||||
};
|
||||
public:
|
||||
TypeDestroyer(const int type)
|
||||
: m_type(type)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
void delegate(const T *where) { DestroyerImpl<T>::Destroy(m_type, const_cast<T*>(where)); }
|
||||
void delegate(const void *) {}
|
||||
void delegate(const QMetaTypeSwitcher::UnknownType*) {}
|
||||
void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) { customTypeDestroyer(m_type, (void*)where); }
|
||||
|
||||
private:
|
||||
static void customTypeDestroyer(const int type, void *where)
|
||||
{
|
||||
QMetaType::Destructor deleter;
|
||||
const QVector<QCustomTypeInfo> * const ct = customTypes();
|
||||
{
|
||||
QReadLocker locker(customTypesLock());
|
||||
if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
|
||||
return;
|
||||
deleter = ct->at(type - QMetaType::User).deleter;
|
||||
}
|
||||
Q_ASSERT_X(deleter, "void QMetaType::destroy(int type, void *data)", "The type was not properly registered");
|
||||
deleter(where);
|
||||
}
|
||||
|
||||
const int m_type;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
/*!
|
||||
Destroys the \a data, assuming it is of the \a type given.
|
||||
|
||||
@ -1695,8 +1602,9 @@ private:
|
||||
*/
|
||||
void QMetaType::destroy(int type, void *data)
|
||||
{
|
||||
TypeDestroyer deleter(type);
|
||||
QMetaTypeSwitcher::switcher<void>(deleter, type, data);
|
||||
QMetaType info(type);
|
||||
info.destruct(data);
|
||||
operator delete(data);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -2246,10 +2154,10 @@ QMetaType QMetaType::typeInfo(const int type)
|
||||
{
|
||||
TypeInfo typeInfo(type);
|
||||
QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
|
||||
return typeInfo.info.creator ? QMetaType(QMetaType::NoExtensionFlags
|
||||
return typeInfo.info.constructor ? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx)
|
||||
, static_cast<const QMetaTypeInterface *>(0) // typeInfo::info is a temporary variable, we can't return address of it.
|
||||
, typeInfo.info.creator
|
||||
, typeInfo.info.deleter
|
||||
, 0 // unused
|
||||
, 0 // unused
|
||||
, typeInfo.info.saveOp
|
||||
, typeInfo.info.loadOp
|
||||
, typeInfo.info.constructor
|
||||
@ -2291,8 +2199,8 @@ QMetaType::QMetaType(const int typeId)
|
||||
Copy constructs a QMetaType object.
|
||||
*/
|
||||
QMetaType::QMetaType(const QMetaType &other)
|
||||
: m_creator(other.m_creator)
|
||||
, m_deleter(other.m_deleter)
|
||||
: m_creator_unused(other.m_creator_unused)
|
||||
, m_deleter_unused(other.m_deleter_unused)
|
||||
, m_saveOp(other.m_saveOp)
|
||||
, m_loadOp(other.m_loadOp)
|
||||
, m_constructor(other.m_constructor)
|
||||
@ -2307,8 +2215,8 @@ QMetaType::QMetaType(const QMetaType &other)
|
||||
|
||||
QMetaType &QMetaType::operator =(const QMetaType &other)
|
||||
{
|
||||
m_creator = other.m_creator;
|
||||
m_deleter = other.m_deleter;
|
||||
m_creator_unused = other.m_creator_unused;
|
||||
m_deleter_unused = other.m_deleter_unused;
|
||||
m_saveOp = other.m_saveOp;
|
||||
m_loadOp = other.m_loadOp;
|
||||
m_constructor = other.m_constructor;
|
||||
@ -2357,11 +2265,14 @@ void QMetaType::dtor()
|
||||
|
||||
Method used for future binary compatible extensions. The function may be called
|
||||
during QMetaType::create to force library call from inlined code.
|
||||
|
||||
### TODO Qt6 remove the extension
|
||||
*/
|
||||
void *QMetaType::createExtended(const void *copy) const
|
||||
{
|
||||
Q_UNUSED(copy);
|
||||
return 0;
|
||||
if (m_typeId == QMetaType::UnknownType)
|
||||
return 0;
|
||||
return m_constructor(operator new(m_size), copy);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -2370,10 +2281,13 @@ void *QMetaType::createExtended(const void *copy) const
|
||||
|
||||
Method used for future binary compatible extensions. The function may be called
|
||||
during QMetaType::destroy to force library call from inlined code.
|
||||
|
||||
### TODO Qt6 remove the extension
|
||||
*/
|
||||
void QMetaType::destroyExtended(void *data) const
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
m_destructor(data);
|
||||
operator delete(data);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -471,6 +471,11 @@ public:
|
||||
int size,
|
||||
QMetaType::TypeFlags flags,
|
||||
const QMetaObject *metaObject);
|
||||
static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Destructor destructor,
|
||||
Constructor constructor,
|
||||
int size,
|
||||
QMetaType::TypeFlags flags,
|
||||
const QMetaObject *metaObject);
|
||||
static int registerTypedef(const char *typeName, int aliasId);
|
||||
static int registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, int aliasId);
|
||||
static int type(const char *typeName);
|
||||
@ -668,8 +673,8 @@ public:
|
||||
static void unregisterConverterFunction(int from, int to);
|
||||
private:
|
||||
|
||||
Creator m_creator;
|
||||
Deleter m_deleter;
|
||||
Creator m_creator_unused;
|
||||
Deleter m_deleter_unused;
|
||||
SaveOperator m_saveOp;
|
||||
LoadOperator m_loadOp;
|
||||
Constructor m_constructor;
|
||||
@ -1618,8 +1623,6 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz
|
||||
flags |= QMetaType::WasDeclaredAsMetaType;
|
||||
|
||||
const int id = QMetaType::registerNormalizedType(normalizedTypeName,
|
||||
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Delete,
|
||||
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Create,
|
||||
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,
|
||||
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct,
|
||||
int(sizeof(T)),
|
||||
@ -1988,8 +1991,8 @@ inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeI
|
||||
uint theTypeFlags,
|
||||
int typeId,
|
||||
const QMetaObject *_metaObject)
|
||||
: m_creator(creator)
|
||||
, m_deleter(deleter)
|
||||
: m_creator_unused(creator)
|
||||
, m_deleter_unused(deleter)
|
||||
, m_saveOp(saveOp)
|
||||
, m_loadOp(loadOp)
|
||||
, m_constructor(constructor)
|
||||
@ -2023,16 +2026,14 @@ inline bool QMetaType::isRegistered() const
|
||||
|
||||
inline void *QMetaType::create(const void *copy) const
|
||||
{
|
||||
if (Q_UNLIKELY(isExtended(CreateEx)))
|
||||
return createExtended(copy);
|
||||
return m_creator(copy);
|
||||
// ### TODO Qt6 remove the extension
|
||||
return createExtended(copy);
|
||||
}
|
||||
|
||||
inline void QMetaType::destroy(void *data) const
|
||||
{
|
||||
if (Q_UNLIKELY(isExtended(DestroyEx)))
|
||||
return destroyExtended(data);
|
||||
m_deleter(data);
|
||||
// ### TODO Qt6 remove the extension
|
||||
destroyExtended(data);
|
||||
}
|
||||
|
||||
inline void *QMetaType::construct(void *where, const void *copy) const
|
||||
|
@ -114,8 +114,6 @@ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_DECLARE_WIDGETS_MODULE_TYPES_ITER)
|
||||
class QMetaTypeInterface
|
||||
{
|
||||
public:
|
||||
QMetaType::Creator creator;
|
||||
QMetaType::Deleter deleter;
|
||||
QMetaType::SaveOperator saveOp;
|
||||
QMetaType::LoadOperator loadOp;
|
||||
QMetaType::Constructor constructor;
|
||||
@ -148,8 +146,6 @@ public:
|
||||
|
||||
#define QT_METATYPE_INTERFACE_INIT_IMPL(Type, DATASTREAM_DELEGATE) \
|
||||
{ \
|
||||
/*creator*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Create), \
|
||||
/*deleter*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Delete), \
|
||||
DATASTREAM_DELEGATE(Type) \
|
||||
/*constructor*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Construct), \
|
||||
/*destructor*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Destruct), \
|
||||
@ -173,8 +169,6 @@ public:
|
||||
#define QT_METATYPE_INTERFACE_INIT_NO_DATASTREAM(Type) QT_METATYPE_INTERFACE_INIT_IMPL(Type, QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL)
|
||||
#define QT_METATYPE_INTERFACE_INIT_EMPTY() \
|
||||
{ \
|
||||
/*creator*/ 0, \
|
||||
/*deleter*/ 0, \
|
||||
QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(void) \
|
||||
/*constructor*/ 0, \
|
||||
/*destructor*/ 0, \
|
||||
|
Loading…
Reference in New Issue
Block a user