diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2022-07-20 13:36:46 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2022-07-27 12:35:50 -0700 |
commit | 8738d9a6a861f79df83e563db41e8b95adeed14a (patch) | |
tree | 72be6ae6d4a42f1b37b4ef7a0cc7e35d9ce55162 | |
parent | 27b10261398304978c3dc0166aad28d80c9b359e (diff) |
QVariant: move the check for std::nullptr_t a bit up in customConstruct
Avoids having to do work after QMetaType::construct() returns. That
can't get the tail-call optimization right now because it is a non-
inline non-static member function, so the QMetaType must be spilled to
the stack.
Change-Id: I3859764fed084846bcb0fffd1703a3ffc723f43f
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/corelib/kernel/qmetatype.cpp | 10 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype_p.h | 11 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 12 |
3 files changed, 17 insertions, 16 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 16d51ae7a1..f7fa838911 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE QT_IMPL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl, QPairVariantInterfaceImpl) -using QtMetaTypePrivate::isVoid; +using QtMetaTypePrivate::isInterfaceFor; namespace { @@ -828,22 +828,22 @@ bool QMetaType::equals(const void *lhs, const void *rhs) const bool QMetaType::isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept { - return !isVoid(iface) && QtMetaTypePrivate::isDefaultConstructible(iface); + return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDefaultConstructible(iface); } bool QMetaType::isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept { - return !isVoid(iface) && QtMetaTypePrivate::isCopyConstructible(iface); + return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isCopyConstructible(iface); } bool QMetaType::isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept { - return !isVoid(iface) && QtMetaTypePrivate::isMoveConstructible(iface); + return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isMoveConstructible(iface); } bool QMetaType::isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept { - return !isVoid(iface) && QtMetaTypePrivate::isDestructible(iface); + return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDestructible(iface); } /*! diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h index 08c1aeaa1d..3defbc70ef 100644 --- a/src/corelib/kernel/qmetatype_p.h +++ b/src/corelib/kernel/qmetatype_p.h @@ -116,11 +116,12 @@ template<> struct TypeDefinition<QQuaternion> { static const bool IsAvailable = template<> struct TypeDefinition<QIcon> { static const bool IsAvailable = false; }; #endif -inline bool isVoid(const QtPrivate::QMetaTypeInterface *iface) +template <typename T> inline bool isInterfaceFor(const QtPrivate::QMetaTypeInterface *iface) { - // void is special because it can't be constructed, copied or destroyed, - // but iface->flags doesn't set Needs{Construction,Destruction}. - return iface->typeId.loadRelaxed() == QMetaType::Void; + // typeId for built-in types are fixed and require no registration + static_assert(QMetaTypeId2<T>::IsBuiltIn, "This function only works for built-in types"); + static constexpr int typeId = QtPrivate::BuiltinMetaType<T>::value; + return iface->typeId.loadRelaxed() == typeId; } template <typename FPointer> @@ -129,7 +130,7 @@ inline bool checkMetaTypeFlagOrPointer(const QtPrivate::QMetaTypeInterface *ifac // helper to the isXxxConstructible & isDestructible functions below: a // meta type has the trait if the trait is trivial or we have the pointer // to perform the operation - Q_ASSERT(!isVoid(iface)); + Q_ASSERT(!isInterfaceFor<void>(iface)); Q_ASSERT(iface->size); return ptr != nullptr || (iface->flags & Flag) == 0; } diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f3c6305432..841c99bf49 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -218,7 +218,7 @@ static bool isValidMetaTypeForVariant(const QtPrivate::QMetaTypeInterface *iface if (!iface || iface->size == 0) return false; - Q_ASSERT(!isVoid(iface)); // only void should have size 0 + Q_ASSERT(!isInterfaceFor<void>(iface)); // only void should have size 0 if (!isCopyConstructible(iface) || !isDestructible(iface)) { // all meta types must be copyable (because QVariant is) and // destructible (because QVariant owns it) @@ -243,11 +243,15 @@ static void customConstruct(const QtPrivate::QMetaTypeInterface *iface, QVariant using namespace QtMetaTypePrivate; Q_ASSERT(iface); Q_ASSERT(iface->size); - Q_ASSERT(!isVoid(iface)); + Q_ASSERT(!isInterfaceFor<void>(iface)); Q_ASSERT(isCopyConstructible(iface)); Q_ASSERT(isDestructible(iface)); Q_ASSERT(copy || isDefaultConstructible(iface)); + // need to check for nullptr_t here, as this can get called by fromValue(nullptr). fromValue() uses + // std::addressof(value) which in this case returns the address of the nullptr object. + d->is_null = !copy || isInterfaceFor<std::nullptr_t>(iface); + void *dst; if (QVariant::Private::canUseInternalSpace(iface)) { d->is_shared = false; @@ -260,10 +264,6 @@ static void customConstruct(const QtPrivate::QMetaTypeInterface *iface, QVariant // now ask QMetaType to construct for us QMetaType(iface).construct(dst, copy); - - // need to check for nullptr_t here, as this can get called by fromValue(nullptr). fromValue() uses - // std::addressof(value) which in this case returns the address of the nullptr object. - d->is_null = !copy || QMetaType(iface) == QMetaType::fromType<std::nullptr_t>(); } static void customClear(QVariant::Private *d) |