Skip to content

Commit 88311e4

Browse files
committed
Unconditionally change std::string's alignment to 8.
Save memory by providing the allocator more freedom to allocate the most efficient size class by dropping the alignment requirements for std::string's pointer from 16 to 8. This changes the output of std::string::max_size, which makes it ABI breaking. That said, the discussion concluded that we don't care about this ABI break and would like this change enabled universally. The ABI break isn't one of layout or "class size", but rather the value of "max_size()" changes, which in turn changes whether std::bad_alloc or std::length_error is thrown for large allocations. This change is the child of PR #68807, which enabled the change behind an ABI flag.
1 parent 9261ab7 commit 88311e4

File tree

6 files changed

+17
-32
lines changed

6 files changed

+17
-32
lines changed

libcxx/docs/ReleaseNotes/18.rst

+4-5
Original file line numberDiff line numberDiff line change
@@ -275,11 +275,10 @@ ABI Affecting Changes
275275
results in an ABI break, however in practice we expect uses of ``std::projected`` in ABI-sensitive places to be
276276
extremely rare. Any error resulting from this change should result in a link-time error.
277277

278-
- Under the unstable ABI, the internal alignment requirements for heap allocations
279-
inside ``std::string`` has decreased from 16 to 8. This saves memory since string requests fewer additional
280-
bytes than it did previously. However, this also changes the return value of ``std::string::max_size``
281-
and can cause code compiled against older libc++ versions but linked at runtime to a new version
282-
to throw a different exception when attempting allocations that are too large
278+
- The internal alignment requirements for heap allocations inside ``std::string`` has decreased from 16 to 8. This
279+
saves memory since string requests fewer additional bytes than it did previously. However, this also changes the
280+
return value of ``std::string::max_size`` and can cause code compiled against older libc++ versions but linked at
281+
runtime to a new version to throw a different exception when attempting allocations that are too large
283282
(``std::bad_alloc`` vs ``std::length_error``).
284283

285284
- The layout of some range adaptors that use the ``movable-box`` exposition-only type as an implementation

libcxx/include/__config

-5
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,6 @@
174174
// The implementation moved to the header, but we still export the symbols from
175175
// the dylib for backwards compatibility.
176176
# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
177-
// Save memory by providing the allocator more freedom to allocate the most
178-
// efficient size class by dropping the alignment requirements for std::string's
179-
// pointer from 16 to 8. This changes the output of std::string::max_size,
180-
// which makes it ABI breaking
181-
# define _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT
182177
# elif _LIBCPP_ABI_VERSION == 1
183178
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
184179
// Enable compiling copies of now inline methods into the dylib to support

libcxx/include/string

+1-6
Original file line numberDiff line numberDiff line change
@@ -1931,12 +1931,7 @@ private:
19311931
return (__s + (__a - 1)) & ~(__a - 1);
19321932
}
19331933
enum {
1934-
__alignment =
1935-
#ifdef _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT
1936-
8
1937-
#else
1938-
16
1939-
#endif
1934+
__alignment = 8
19401935
};
19411936
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __recommend(size_type __s) _NOEXCEPT {
19421937
if (__s < __min_cap) {

libcxx/test/libcxx/strings/basic.string/string.capacity/allocation_size.pass.cpp

+4-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
// XFAIL: stdlib=apple-libc++ && target={{.+}}-apple-macosx{{10.13|10.15|11.0}}
10+
911
// <string>
1012

1113
// This test demonstrates the smaller allocation sizes when the alignment
@@ -17,14 +19,8 @@
1719

1820
#include "test_macros.h"
1921

20-
// alignment of the string heap buffer is hardcoded to either 16 or 8
21-
22-
const std::size_t alignment =
23-
#ifdef _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT
24-
8;
25-
#else
26-
16;
27-
#endif
22+
// alignment of the string heap buffer is hardcoded to 8
23+
const std::size_t alignment = 8;
2824

2925
int main(int, char**) {
3026
std::string input_string;

libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp

+2-8
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,8 @@
1717

1818
#include "test_macros.h"
1919

20-
// alignment of the string heap buffer is hardcoded to 16
21-
22-
static const std::size_t alignment =
23-
#ifdef _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT
24-
8;
25-
#else
26-
16;
27-
#endif
20+
// alignment of the string heap buffer is hardcoded to 8
21+
static const std::size_t alignment = 8;
2822

2923
template <class = int>
3024
TEST_CONSTEXPR_CXX20 void full_size() {

libcxx/test/std/strings/basic.string/string.capacity/max_size.pass.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
//===----------------------------------------------------------------------===//
88

99
// UNSUPPORTED: no-exceptions
10+
11+
// After changing the alignment of the allocated pointer from 16 to 8, the exception thrown is no longer `bad_alloc`
12+
// but instead length_error on systems using new headers but older dylibs.
13+
//
14+
// XFAIL: stdlib=apple-libc++ && target={{.+}}-apple-macosx{{10.13|10.15|11.0}}
15+
1016
// <string>
1117

1218
// size_type max_size() const; // constexpr since C++20

0 commit comments

Comments
 (0)