summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-01-27 09:56:58 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2021-01-28 18:51:22 +0100
commit40bfbe7dd9fb783b07550db8944931d1637da721 (patch)
tree1a898a9b4782395aa9ab753110f5a107f41c4966 /src/corelib/kernel
parentaf53fb0e00d694b7cb115b0162ee75d883adff67 (diff)
QVariant: Use QMetaTypeInferface directly
There is no reason for QVariant to go through QMetaType when it can use the QMetaTypeInterface directly. Without LTO, the QMetaType method calls are opaque, and we therefore risk to lose optimizations. Additionally, avoid constructing a QMetaType from a type id if we already have the QMetaType. Fixes: QTBUG-90673 Change-Id: I7069ff6aff70d5baecdf5cf5760014c3dda81784 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qvariant.cpp64
-rw-r--r--src/corelib/kernel/qvariant.h21
-rw-r--r--src/corelib/kernel/qvariant_p.h2
3 files changed, 63 insertions, 24 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 036ee42e05..97623727a8 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -248,24 +248,32 @@ static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok)
// the type of d has already been set, but other field are not set
static void customConstruct(QVariant::Private *d, const void *copy)
{
- const QMetaType type = d->type();
- const uint size = type.sizeOf();
- if (!size) {
+ QtPrivate::QMetaTypeInterface *iface = d->typeInterface();
+ if (!(iface && iface->size)) {
*d = QVariant::Private();
return;
}
- if (QVariant::Private::canUseInternalSpace(type)) {
- type.construct(&d->data, copy);
+ if (QVariant::Private::canUseInternalSpace(iface)) {
+ // QVariant requires type to be copy and default constructible
+ Q_ASSERT(iface->copyCtr);
+ Q_ASSERT(iface->defaultCtr);
+ if (copy)
+ iface->copyCtr(iface, &d->data, copy);
+ else
+ iface->defaultCtr(iface, &d->data);
d->is_shared = false;
} else {
- d->data.shared = QVariant::PrivateShared::create(type);
- type.construct(d->data.shared->data(), copy);
+ d->data.shared = QVariant::PrivateShared::create(iface);
+ if (copy)
+ iface->copyCtr(iface, d->data.shared->data(), copy);
+ else
+ iface->defaultCtr(iface, d->data.shared->data());
d->is_shared = true;
}
// 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 || type == QMetaType::fromType<std::nullptr_t>();
+ d->is_null = !copy || QMetaType(iface) == QMetaType::fromType<std::nullptr_t>();
}
static void customClear(QVariant::Private *d)
@@ -471,11 +479,23 @@ static void customClear(QVariant::Private *d)
Constructs a variant private of type \a type, and initializes with \a copy if
\a copy is not \nullptr.
-*/
+*/
+//### Qt 7: Remove in favor of QMetaType overload
void QVariant::create(int type, const void *copy)
{
- d = Private(QMetaType(type));
+ create(QMetaType(type), copy);
+}
+
+/*!
+ \fn QVariant::create(int type, const void *copy)
+
+ \internal
+ \overload
+*/
+void QVariant::create(QMetaType type, const void *copy)
+{
+ d = Private(type);
customConstruct(&d, copy);
}
@@ -510,9 +530,14 @@ QVariant::QVariant(const QVariant &p)
d.data.shared->ref.ref();
return;
}
- QMetaType t = d.type();
- if (t.isValid())
- t.construct(&d, p.constData());
+ QtPrivate::QMetaTypeInterface *iface = d.typeInterface();
+ auto other = p.constData();
+ if (iface) {
+ if (other)
+ iface->copyCtr(iface, &d, other);
+ else
+ iface->defaultCtr(iface, &d);
+ }
}
/*!
@@ -995,9 +1020,14 @@ QVariant &QVariant::operator=(const QVariant &variant)
d = variant.d;
} else {
d = variant.d;
- QMetaType t = d.type();
- if (t.isValid())
- t.construct(&d, variant.constData());
+ QtPrivate::QMetaTypeInterface *iface = d.typeInterface();
+ const void *other = variant.constData();
+ if (iface) {
+ if (other)
+ iface->copyCtr(iface, &d, other);
+ else
+ iface->defaultCtr(iface, &d);
+ }
}
return *this;
@@ -2021,7 +2051,7 @@ bool QVariant::convert(QMetaType targetType)
QVariant oldValue = *this;
clear();
- create(targetType.id(), nullptr);
+ create(targetType, nullptr);
if (!oldValue.canConvert(targetType))
return false;
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index b7d347a61e..d95d3cd0fb 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -426,10 +426,11 @@ public:
private:
inline PrivateShared() : ref(1) { }
public:
- static PrivateShared *create(QMetaType type)
+ static PrivateShared *create(const QtPrivate::QMetaTypeInterface *type)
{
- size_t size = type.sizeOf();
- size_t align = type.alignOf();
+ Q_ASSERT(type);
+ size_t size = type->size;
+ size_t align = type->alignment;
size += sizeof(PrivateShared);
if (align > sizeof(PrivateShared)) {
@@ -463,10 +464,11 @@ public:
static constexpr size_t MaxInternalSize = 3*sizeof(void *);
template<typename T>
static constexpr bool CanUseInternalSpace = (QTypeInfo<T>::isRelocatable && sizeof(T) <= MaxInternalSize && alignof(T) <= alignof(double));
- static constexpr bool canUseInternalSpace(QMetaType type)
+ static constexpr bool canUseInternalSpace(QtPrivate::QMetaTypeInterface *type)
{
- return type.flags() & QMetaType::RelocatableType &&
- size_t(type.sizeOf()) <= MaxInternalSize && size_t(type.alignOf()) <= alignof(double);
+ Q_ASSERT(type);
+ return QMetaType::TypeFlags(type->flags) & QMetaType::RelocatableType &&
+ size_t(type->size) <= MaxInternalSize && size_t(type->alignment) <= alignof(double);
}
union
@@ -506,6 +508,12 @@ public:
{
return QMetaType(reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2));
}
+
+ inline QtPrivate::QMetaTypeInterface * typeInterface() const
+ {
+ return reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2);
+ }
+
inline int typeId() const
{
return type().id();
@@ -531,6 +539,7 @@ private:
protected:
Private d;
void create(int type, const void *copy);
+ void create(QMetaType type, const void *copy);
bool equals(const QVariant &other) const;
bool convert(int type, void *ptr) const;
bool view(int type, void *ptr);
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index f0b15012ec..ef6042d745 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -65,7 +65,7 @@ inline void v_construct(QVariant::Private *x, const T &t)
new (&x->data) T(t);
x->is_shared = false;
} else {
- x->data.shared = QVariant::PrivateShared::create(QMetaType::fromType<T>());
+ x->data.shared = QVariant::PrivateShared::create(QtPrivate::qMetaTypeInterfaceForType<T>());
new (x->data.shared->data()) T(t);
x->is_shared = true;
}