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>
bb10
Thiago Macieira 2022-07-20 13:36:46 -07:00
parent 27b1026139
commit 8738d9a6a8
3 changed files with 17 additions and 16 deletions

View File

@ -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);
}
/*!

View File

@ -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;
}

View File

@ -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)