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.

Change-Id: I79e700614d034281bf55fffd178fa0aee2344307
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit 4d57b30194f31865132312c67abf796cb58a0f8f)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2023-10-19 14:50:57 -07:00 committed by Qt Cherry-pick Bot
parent 5d534ee9a9
commit 9039b0cd25
2 changed files with 19 additions and 7 deletions

View File

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

View File

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