summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/tools/qarraydata.cpp64
-rw-r--r--src/corelib/tools/qarraydata.h32
2 files changed, 73 insertions, 23 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 56f1461644..ff3bf2d6b8 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -151,21 +151,19 @@ namespace {
struct alignas(std::max_align_t) AlignedQArrayData : QArrayData
{
};
-}
+struct AllocationResult {
+ void *data;
+ QArrayData *header;
+};
+}
-void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype alignment,
- qsizetype capacity, QArrayData::AllocationOption option) noexcept
+static inline AllocationResult
+allocateHelper(qsizetype objectSize, qsizetype alignment, qsizetype capacity,
+ QArrayData::AllocationOption option) noexcept
{
- Q_ASSERT(dptr);
- // Alignment is a power of two
- Q_ASSERT(alignment >= qsizetype(alignof(QArrayData))
- && !(alignment & (alignment - 1)));
-
- if (capacity == 0) {
- *dptr = nullptr;
- return nullptr;
- }
+ if (capacity == 0)
+ return {};
qsizetype headerSize = sizeof(AlignedQArrayData);
const qsizetype headerAlignment = alignof(AlignedQArrayData);
@@ -181,10 +179,8 @@ void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype al
auto blockSize = calculateBlockSize(capacity, objectSize, headerSize, option);
capacity = blockSize.elementCount;
qsizetype allocSize = blockSize.size;
- if (Q_UNLIKELY(allocSize < 0)) { // handle overflow. cannot allocate reliably
- *dptr = nullptr;
- return nullptr;
- }
+ if (Q_UNLIKELY(allocSize < 0)) // handle overflow. cannot allocate reliably
+ return {};
QArrayData *header = allocateData(allocSize);
void *data = nullptr;
@@ -194,8 +190,40 @@ void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype al
header->alloc = qsizetype(capacity);
}
- *dptr = header;
- return data;
+ return { data, header };
+}
+
+// Generic size and alignment allocation function
+void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype alignment,
+ qsizetype capacity, AllocationOption option) noexcept
+{
+ Q_ASSERT(dptr);
+ // Alignment is a power of two
+ Q_ASSERT(alignment >= qsizetype(alignof(QArrayData))
+ && !(alignment & (alignment - 1)));
+
+ auto r = allocateHelper(objectSize, alignment, capacity, option);
+ *dptr = r.header;
+ return r.data;
+}
+
+// Fixed size and alignment allocation functions
+void *QArrayData::allocate1(QArrayData **dptr, qsizetype capacity, AllocationOption option) noexcept
+{
+ Q_ASSERT(dptr);
+
+ auto r = allocateHelper(1, alignof(AlignedQArrayData), capacity, option);
+ *dptr = r.header;
+ return r.data;
+}
+
+void *QArrayData::allocate2(QArrayData **dptr, qsizetype capacity, AllocationOption option) noexcept
+{
+ Q_ASSERT(dptr);
+
+ auto r = allocateHelper(2, alignof(AlignedQArrayData), capacity, option);
+ *dptr = r.header;
+ return r.data;
}
QPair<QArrayData *, void *>
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index adc53fe39d..2369a27e84 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -11,6 +11,12 @@
QT_BEGIN_NAMESPACE
+#if __has_cpp_attribute(gnu::malloc)
+# define Q_DECL_MALLOCLIKE [[nodiscard, gnu::malloc]]
+#else
+# define Q_DECL_MALLOCLIKE [[nodiscard]]
+#endif
+
template <class T> struct QTypedArrayData;
struct QArrayData
@@ -78,12 +84,16 @@ struct QArrayData
return newSize;
}
- [[nodiscard]]
-#if defined(Q_CC_GNU)
- __attribute__((__malloc__))
-#endif
+ Q_DECL_MALLOCLIKE
static Q_CORE_EXPORT void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment,
qsizetype capacity, AllocationOption option = QArrayData::KeepSize) noexcept;
+ Q_DECL_MALLOCLIKE
+ static Q_CORE_EXPORT void *allocate1(QArrayData **pdata, qsizetype capacity,
+ AllocationOption option = QArrayData::KeepSize) noexcept;
+ Q_DECL_MALLOCLIKE
+ static Q_CORE_EXPORT void *allocate2(QArrayData **pdata, qsizetype capacity,
+ AllocationOption option = QArrayData::KeepSize) noexcept;
+
[[nodiscard]] static Q_CORE_EXPORT QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer,
qsizetype objectSize, qsizetype newCapacity, AllocationOption option) noexcept;
static Q_CORE_EXPORT void deallocate(QArrayData *data, qsizetype objectSize,
@@ -102,8 +112,18 @@ struct QTypedArrayData
{
static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
QArrayData *d;
- void *result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, option);
+ void *result;
+ if constexpr (sizeof(T) == 1) {
+ // necessarily, alignof(T) == 1
+ result = allocate1(&d, capacity, option);
+ } else if constexpr (sizeof(T) == 2) {
+ // alignof(T) may be 1, but that makes no difference
+ result = allocate2(&d, capacity, option);
+ } else {
+ result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, option);
+ }
#if __has_builtin(__builtin_assume_aligned)
+ // and yet we do offer results that have stricter alignment
result = __builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy));
#endif
return qMakePair(static_cast<QTypedArrayData *>(d), static_cast<T *>(result));
@@ -172,6 +192,8 @@ struct Q_CORE_EXPORT QContainerImplHelper
};
}
+#undef Q_DECL_MALLOCLIKE
+
QT_END_NAMESPACE
#endif // include guard