summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qvariant.h
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-07-10 14:06:36 +0200
committerLars Knoll <lars.knoll@qt.io>2020-08-24 00:17:04 +0200
commit6754198c338abd560f3af31ff09630e0f1085843 (patch)
tree4354bf6840007f90c6187adc5e0a33e39f2fdcf3 /src/corelib/kernel/qvariant.h
parent76e8e8e9c8093f093cb9f37d61d273f43398fefb (diff)
Cleanup QVariant::PrivateShared
Remove the additional indirection through ptr and replace it with an offset calculation. Get rid of PrivateSharedEx that was handling certain types differently. This also fixes the support for overaligned types, by using the alignment field from QMetaType to determine the alignment requirements. Change-Id: Icc6a78eb57f664c7747450578fe58dfee8f2863b Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel/qvariant.h')
-rw-r--r--src/corelib/kernel/qvariant.h38
1 files changed, 34 insertions, 4 deletions
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index b738b80d38..96756fdda7 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -52,7 +52,6 @@
#ifndef QT_BOOTSTRAPPED
#include <QtCore/qbytearraylist.h>
#endif
-
#include <memory>
#if __has_include(<variant>) && __cplusplus >= 201703L
@@ -405,9 +404,40 @@ class Q_CORE_EXPORT QVariant
public:
struct PrivateShared
{
- inline PrivateShared(void *v) : ptr(v), ref(1) { }
- void *ptr;
- QAtomicInt ref;
+ private:
+ inline PrivateShared() : ref(1) { }
+ public:
+ static PrivateShared *create(QMetaType type)
+ {
+ size_t size = type.sizeOf();
+ size_t align = type.alignOf();
+
+ size += sizeof(PrivateShared);
+ if (align > sizeof(PrivateShared)) {
+ // The alignment is larger than the alignment we can guarantee for the pointer
+ // directly following PrivateShared, so we need to allocate some additional
+ // memory to be able to fit the object into the available memory with suitable
+ // alignment.
+ size += align - sizeof(PrivateShared);
+ }
+ void *data = operator new(size);
+ auto *ps = new (data) QVariant::PrivateShared();
+ ps->offset = int(((quintptr(ps) + sizeof(PrivateShared) + align - 1) & ~(align - 1)) - quintptr(ps));
+ return ps;
+ }
+ static void free(PrivateShared *p)
+ {
+ p->~PrivateShared();
+ operator delete(p);
+ }
+
+ alignas(8) QAtomicInt ref;
+ int offset;
+
+ const void *data() const
+ { return reinterpret_cast<const unsigned char *>(this) + offset; }
+ void *data()
+ { return reinterpret_cast<unsigned char *>(this) + offset; }
};
struct Private
{