diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-10-19 14:50:57 -0700 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2023-12-11 18:41:56 +0000 |
commit | 4d57b30194f31865132312c67abf796cb58a0f8f (patch) | |
tree | f525303d46da62d1e16fb3a5183cfd377b9c7192 | |
parent | 4d7864f0517679ebe70a2a96afdae5dc4f5a2d62 (diff) |
QArrayData: move AlignedQArrayData to the public header
This allows us to use it in QTypedArrayData<T>::AlignmentDummy, which is
used in __builtin_assume_aligned() as a hint to the compiler. This
increases the value we were passing as the compiler hint from 4 to 8 on
32-bit platforms and from 8 to 16 on 64-bit platforms. We actually do
align to a bit higher than even that, but that's not an ABI guarantee
we're making.
However, it looks like GCC on 32-bit platforms is buggy, so we work
around it. Commit r240248 ("Make max_align_t respect _Float128.",
63012d9a57edc950c5f30242d1e19318b5708060 in Git) increased
std::max_align_t to 16 bytes on all platforms, saying "Such an increase
is of course an ABI change" and "I think glibc malloc alignment should
also increase to 16-byte 32-bit x86", but such a change to glibc was
never implemented. Moreover, there are systems that don't use glibc,
such as when using GCC on other OSes.
This is not a change in Qt behavior anywhere. i386 does not (usually) do
alignment checks, so most code wouldn't notice this at all.
Pick-to: 6.7
Change-Id: I79e700614d034281bf55fffd178fa0aee2344307
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
-rw-r--r-- | src/corelib/tools/qarraydata.cpp | 8 | ||||
-rw-r--r-- | src/corelib/tools/qarraydata.h | 18 |
2 files changed, 19 insertions, 7 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index ff3bf2d6b8..3f417fc390 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -145,18 +145,13 @@ static QArrayData *allocateData(qsizetype allocSize) return header; } - namespace { -// QArrayData with strictest alignment requirements supported by malloc() -struct alignas(std::max_align_t) AlignedQArrayData : QArrayData -{ -}; - struct AllocationResult { void *data; QArrayData *header; }; } +using QtPrivate::AlignedQArrayData; static inline AllocationResult allocateHelper(qsizetype objectSize, qsizetype alignment, qsizetype capacity, @@ -172,6 +167,7 @@ allocateHelper(qsizetype objectSize, qsizetype alignment, qsizetype capacity, // Allocate extra (alignment - Q_ALIGNOF(AlignedQArrayData)) padding // bytes so we can properly align the data array. This assumes malloc is // able to provide appropriate alignment for the header -- as it should! + // Effectively, we allocate one QTypedArrayData<T>::AlignmentDummy. headerSize += alignment - headerAlignment; } Q_ASSERT(headerSize > 0); diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index 2369a27e84..4b71619038 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -102,11 +102,27 @@ struct QArrayData Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions) +namespace QtPrivate { +// QArrayData with strictest alignment requirements supported by malloc() +#if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU) +// GCC's definition is incorrect since GCC 8 (commit r240248 in SVN; commit +// 63012d9a57edc950c5f30242d1e19318b5708060 in Git). This is applied to all +// GCC-like compilers in case they decide to follow GCC's lead in being wrong. +constexpr size_t MaxPrimitiveAlignment = 2 * sizeof(void *); +#else +constexpr size_t MaxPrimitiveAlignment = alignof(std::max_align_t); +#endif + +struct alignas(MaxPrimitiveAlignment) AlignedQArrayData : QArrayData +{ +}; +} + template <class T> struct QTypedArrayData : QArrayData { - struct AlignmentDummy { QArrayData header; T data; }; + struct AlignmentDummy { QtPrivate::AlignedQArrayData header; T data; }; [[nodiscard]] static QPair<QTypedArrayData *, T *> allocate(qsizetype capacity, AllocationOption option = QArrayData::KeepSize) { |