QMetaType: move the built-in QMetaTypeInterfaces to read-only segments
The presence of the mutable causes the const object to lose its constness, so declaring as const wasn't helpful. But we can't drop the const wholesale for MSVC right now because it mangles the variable's type in the external name. For all other compilers, we drop it for user-defined types, which is a no-op but is semantically correct because QMetaType needs to modify those objects. Aside from a few const_cast (marked with comments), nothing else changes. For types with built-in type IDs, however, the QMetaTypeInterface is now fully const... or would be if it weren't full of relocations. It does move the lot from the .data section to the .data.rel.ro section. After this change, QtCore and QtGui have: QtCore QtGui .data.rel.ro 57 23 .data, exported 17 39 .data, private 94 193 sizeof(QtPrivate::QMetaTypeInterface) = 112 on 64-bit platforms (but GCC issues ".align 32", so they effectively occupy 128 bytes) Change-Id: Id0fb9ab0089845ee8843fffd16f9a35bfafebf77 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
dbf58407cb
commit
c474825945
@ -75,8 +75,11 @@ struct QMetaTypeCustomRegistry
|
||||
// index of first empty (unregistered) type in registry, if any.
|
||||
int firstEmpty = 0;
|
||||
|
||||
int registerCustomType(const QtPrivate::QMetaTypeInterface *ti)
|
||||
int registerCustomType(const QtPrivate::QMetaTypeInterface *cti)
|
||||
{
|
||||
// we got here because cti->typeId is 0, so this is a custom meta type
|
||||
// (not read-only)
|
||||
auto ti = const_cast<QtPrivate::QMetaTypeInterface *>(cti);
|
||||
{
|
||||
QWriteLocker l(&lock);
|
||||
if (int id = ti->typeId.loadRelaxed())
|
||||
@ -789,9 +792,11 @@ bool QMetaType::isOrdered() const
|
||||
void QMetaType::unregisterMetaType(QMetaType type)
|
||||
{
|
||||
if (type.d_ptr && type.d_ptr->typeId.loadRelaxed() >= QMetaType::User) {
|
||||
// this is a custom meta type (not read-only)
|
||||
auto d = const_cast<QtPrivate::QMetaTypeInterface *>(type.d_ptr);
|
||||
if (auto reg = customTypeRegistry())
|
||||
reg->unregisterDynamicType(type.d_ptr->typeId.loadRelaxed());
|
||||
type.d_ptr->typeId.storeRelease(0);
|
||||
reg->unregisterDynamicType(d->typeId.loadRelaxed());
|
||||
d->typeId.storeRelease(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,6 +225,20 @@ struct QMetaObject;
|
||||
namespace QtPrivate
|
||||
{
|
||||
|
||||
class QMetaTypeInterface;
|
||||
|
||||
// MSVC is the only supported compiler that includes the type of a variable in
|
||||
// its mangled form, so it's not binary-compatible to drop the const in
|
||||
// QMetaTypeInterfaceWrapper::metaType for it, which means we must keep the
|
||||
// mutable field until Qt 7.
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || !defined(Q_CC_MSVC)
|
||||
# define QMTI_MUTABLE
|
||||
using NonConstMetaTypeInterface = QMetaTypeInterface;
|
||||
#else
|
||||
# define QMTI_MUTABLE mutable
|
||||
using NonConstMetaTypeInterface = const QMetaTypeInterface;
|
||||
#endif
|
||||
|
||||
class QMetaTypeInterface
|
||||
{
|
||||
public:
|
||||
@ -232,7 +246,7 @@ public:
|
||||
ushort alignment;
|
||||
uint size;
|
||||
uint flags;
|
||||
mutable QBasicAtomicInt typeId;
|
||||
QMTI_MUTABLE QBasicAtomicInt typeId;
|
||||
|
||||
using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
|
||||
MetaObjectFn metaObjectFn;
|
||||
@ -261,6 +275,7 @@ public:
|
||||
using LegacyRegisterOp = void (*)();
|
||||
LegacyRegisterOp legacyRegisterOp;
|
||||
};
|
||||
#undef QMTI_MUTABLE
|
||||
|
||||
/*!
|
||||
This template is used for implicit conversion from type From to type To.
|
||||
@ -2326,7 +2341,13 @@ public:
|
||||
template<typename T>
|
||||
struct QMetaTypeInterfaceWrapper
|
||||
{
|
||||
static inline constexpr const QMetaTypeInterface metaType = {
|
||||
// if the type ID for T is known at compile-time, then we can declare
|
||||
// the QMetaTypeInterface object const; otherwise, we declare it as
|
||||
// non-const and the .typeId is updated by QMetaType::idHelper().
|
||||
static constexpr bool IsConstMetaTypeInterface = !!BuiltinMetaType<T>::value;
|
||||
using InterfaceType = std::conditional_t<IsConstMetaTypeInterface, const QMetaTypeInterface, NonConstMetaTypeInterface>;
|
||||
|
||||
static inline InterfaceType metaType = {
|
||||
/*.revision=*/ 0,
|
||||
/*.alignment=*/ alignof(T),
|
||||
/*.size=*/ sizeof(T),
|
||||
|
Loading…
Reference in New Issue
Block a user