aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/utils/smallstringlayout.h
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2022-08-07 03:35:53 +0200
committerMarco Bubke <marco.bubke@qt.io>2022-08-16 16:15:45 +0000
commitcf064500aaa0c0de7eafffd179250f9922bb03f8 (patch)
tree447b5e161dc78e09863dbee733f0e3db053ba37b /src/libs/utils/smallstringlayout.h
parent735346adb5caa8ee678ae0a8b91e8b43943a5bf1 (diff)
Utils: Improve memory layout code
Actually, the layout is the same, but we move the control block. To prevent padding of the short string, we use pragma pack(1). To align the pointer again, we add some dummy data with the size of a pointer minus a control block because alignas is not working like expected on GCC. Change-Id: Ide86ace243dab5f487da63492ebac018da45098a Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Diffstat (limited to 'src/libs/utils/smallstringlayout.h')
-rw-r--r--src/libs/utils/smallstringlayout.h113
1 files changed, 45 insertions, 68 deletions
diff --git a/src/libs/utils/smallstringlayout.h b/src/libs/utils/smallstringlayout.h
index 7d6190528ef..c1de97e109f 100644
--- a/src/libs/utils/smallstringlayout.h
+++ b/src/libs/utils/smallstringlayout.h
@@ -96,56 +96,17 @@ private:
ControlType m_isReference : 1;
};
-template<uint MaximumShortStringDataAreaSize>
-struct alignas(16) AllocatedLayout
-{
- struct Data
- {
+struct ReferenceLayout
+{ union {
+ const char *constPointer;
char *pointer;
- size_type size;
- size_type capacity;
- };
-
- ControlBlock<MaximumShortStringDataAreaSize> control;
- Data data;
-};
-
-template<uint MaximumShortStringDataAreaSize>
-struct alignas(16) ReferenceLayout
-{
- constexpr ReferenceLayout() noexcept = default;
- constexpr ReferenceLayout(const char *stringPointer,
- size_type size,
- size_type capacity) noexcept
- : control(0, true, true),
- data{stringPointer, size, capacity}
- {}
-
- struct Data
- {
- const char *pointer;
- size_type size;
- size_type capacity;
};
-
- ControlBlock<MaximumShortStringDataAreaSize> control;
- Data data;
-};
-
-template<uint MaximumShortStringDataAreaSize>
-struct alignas(16) ShortStringLayout
-{
- constexpr ShortStringLayout(
- typename ControlBlock<MaximumShortStringDataAreaSize>::SizeType shortStringSize) noexcept
- : control(shortStringSize, false, false)
- {}
-
- ControlBlock<MaximumShortStringDataAreaSize> control;
- char string[MaximumShortStringDataAreaSize];
+ size_type size;
+ size_type capacity;
};
template<uint MaximumShortStringDataAreaSize, typename = void>
-struct StringDataLayout
+struct alignas(16) StringDataLayout
{
static_assert(MaximumShortStringDataAreaSize >= 15, "Size must be greater equal than 15 bytes!");
static_assert(MaximumShortStringDataAreaSize < 32, "Size must be less than 32 bytes!");
@@ -156,17 +117,19 @@ struct StringDataLayout
StringDataLayout() noexcept { reset(); }
constexpr StringDataLayout(const char *string, size_type size) noexcept
- : reference(string, size, 0)
+ : control{0, true, true}
+ , reference{{string}, size, 0}
{}
template<size_type Size>
constexpr StringDataLayout(const char (&string)[Size]) noexcept
{
if constexpr (Size <= MaximumShortStringDataAreaSize) {
- shortString = {Size - 1};
+ control = {Size - 1, false, false};
for (size_type i = 0; i < Size; ++i)
- shortString.string[i] = string[i];
+ shortString[i] = string[i];
} else {
+ control = {0, true, true};
reference = {string, Size - 1, 0};
}
}
@@ -178,20 +141,27 @@ struct StringDataLayout
constexpr void reset()
{
- shortString.control = ControlBlock<MaximumShortStringDataAreaSize>();
- shortString.string[0] = '\0';
+ control = ControlBlock<MaximumShortStringDataAreaSize>();
+ shortString[0] = '\0';
}
+#pragma pack(push)
+#pragma pack(1)
+ ControlBlock<MaximumShortStringDataAreaSize> control;
union {
- AllocatedLayout<MaximumShortStringDataAreaSize> allocated;
- ReferenceLayout<MaximumShortStringDataAreaSize> reference;
- ShortStringLayout<MaximumShortStringDataAreaSize> shortString;
+ char shortString[MaximumShortStringDataAreaSize];
+ struct
+ {
+ char dummy[sizeof(void *) - sizeof(ControlBlock<MaximumShortStringDataAreaSize>)];
+ ReferenceLayout reference;
+ };
};
+#pragma pack(pop)
};
template<uint MaximumShortStringDataAreaSize>
-struct StringDataLayout<MaximumShortStringDataAreaSize,
- std::enable_if_t<MaximumShortStringDataAreaSize >= 32>>
+struct alignas(16) StringDataLayout<MaximumShortStringDataAreaSize,
+ std::enable_if_t<MaximumShortStringDataAreaSize >= 32>>
{
static_assert(MaximumShortStringDataAreaSize > 31, "Size must be greater than 31 bytes!");
static_assert(MaximumShortStringDataAreaSize < 64
@@ -203,17 +173,19 @@ struct StringDataLayout<MaximumShortStringDataAreaSize,
StringDataLayout() noexcept { reset(); }
constexpr StringDataLayout(const char *string, size_type size) noexcept
- : reference(string, size, 0)
+ : control{0, true, true}
+ , reference{string, size, 0}
{}
template<size_type Size>
constexpr StringDataLayout(const char (&string)[Size]) noexcept
{
if constexpr (Size <= MaximumShortStringDataAreaSize) {
- shortString = {Size - 1};
+ control = {Size - 1, false, false};
for (size_type i = 0; i < Size; ++i)
- shortString.string[i] = string[i];
+ shortString[i] = string[i];
} else {
+ control = {0, true, true};
reference = {string, Size - 1, 0};
}
}
@@ -223,11 +195,9 @@ struct StringDataLayout<MaximumShortStringDataAreaSize,
StringDataLayout &operator=(const StringDataLayout &other) noexcept
{
constexpr auto controlBlockSize = sizeof(ControlBlock<MaximumShortStringDataAreaSize>);
- auto shortStringLayoutSize = other.shortString.control.stringSize() + controlBlockSize;
- constexpr auto referenceLayoutSize = sizeof(ReferenceLayout<MaximumShortStringDataAreaSize>);
- std::memcpy(&shortString,
- &other.shortString,
- std::max(shortStringLayoutSize, referenceLayoutSize));
+ auto shortStringLayoutSize = other.control.stringSize() + controlBlockSize;
+ constexpr auto referenceLayoutSize = sizeof(ReferenceLayout);
+ std::memcpy(this, &other, std::max(shortStringLayoutSize, referenceLayoutSize));
return *this;
}
@@ -239,15 +209,22 @@ struct StringDataLayout<MaximumShortStringDataAreaSize,
constexpr void reset()
{
- shortString.control = ControlBlock<MaximumShortStringDataAreaSize>();
- shortString.string[0] = '\0';
+ control = ControlBlock<MaximumShortStringDataAreaSize>();
+ shortString[0] = '\0';
}
+#pragma pack(push)
+#pragma pack(1)
+ ControlBlock<MaximumShortStringDataAreaSize> control;
union {
- AllocatedLayout<MaximumShortStringDataAreaSize> allocated;
- ReferenceLayout<MaximumShortStringDataAreaSize> reference;
- ShortStringLayout<MaximumShortStringDataAreaSize> shortString;
+ char shortString[MaximumShortStringDataAreaSize];
+ struct
+ {
+ char dummy[sizeof(void *) - sizeof(ControlBlock<MaximumShortStringDataAreaSize>)];
+ ReferenceLayout reference;
+ };
};
+#pragma pack(pop)
};
} // namespace Internal