[libcxx-commits] [libcxx] Unconditionally lower std::string's alignment requirement from 16 to 8. (PR #68925)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 12 13:40:38 PDT 2023


https://github.com/EricWF created https://github.com/llvm/llvm-project/pull/68925

As requested in #68807

>From efe2fa35a7e7820e3099ff30e29ca62716b4d658 Mon Sep 17 00:00:00 2001
From: Eric Fiselier <eric at efcs.ca>
Date: Thu, 12 Oct 2023 16:37:03 -0400
Subject: [PATCH] Unconditionally lower std::string's alignment requirement
 from 16 to 8.

As requested in #68807
---
 libcxx/docs/ReleaseNotes/18.rst               |  6 ++++
 libcxx/include/string                         |  2 +-
 .../string.capacity/allocation_size.pass.cpp  | 31 +++++++++++++++++++
 .../string.capacity/max_size.pass.cpp         |  3 +-
 4 files changed, 40 insertions(+), 2 deletions(-)
 create mode 100644 libcxx/test/libcxx/strings/basic.string/string.capacity/allocation_size.pass.cpp

diff --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst
index 5f43d2f2afe22d3..57f0fa1d7df53d9 100644
--- a/libcxx/docs/ReleaseNotes/18.rst
+++ b/libcxx/docs/ReleaseNotes/18.rst
@@ -133,6 +133,12 @@ ABI Affecting Changes
   results in an ABI break, however in practice we expect uses of ``std::projected`` in ABI-sensitive places to be
   extremely rare. Any error resulting from this change should result in a link-time error.
 
+- The internal alignment requirements for heap allocations inside std::string has decreased from 16 to 8.
+  This save memory since string requests fewer additional bytes than it did previously. However, this
+  also changes the return value of std::string::max_length and can cause code compiled against older
+  libc++ versions but linked at runtime to a new version to thrown a different exception
+  when attempting allocations that are too large (std::bad_alloc vs std::length_error).
+
 Build System Changes
 --------------------
 
diff --git a/libcxx/include/string b/libcxx/include/string
index 33e87406a1156a6..4badb55a78944a1 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1851,7 +1851,7 @@ private:
         _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
         size_type __align_it(size_type __s) _NOEXCEPT
             {return (__s + (__a-1)) & ~(__a-1);}
-    enum {__alignment = 16};
+    enum { __alignment = 8 };
     static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
     size_type __recommend(size_type __s) _NOEXCEPT
     {
diff --git a/libcxx/test/libcxx/strings/basic.string/string.capacity/allocation_size.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.capacity/allocation_size.pass.cpp
new file mode 100644
index 000000000000000..6917a2c48128e81
--- /dev/null
+++ b/libcxx/test/libcxx/strings/basic.string/string.capacity/allocation_size.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <string>
+
+// This test demonstrates the smaller allocation sizes when the alignment
+// requirements of std::string are dropped from 16 to 8.
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <string>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  std::string input_string;
+  input_string.resize(64, 'a');
+
+  // Call a constructor which selects its size using __recommend.
+  std::string test_string(input_string.data());
+  constexpr std::size_t expected_align8_size = 71;
+  // Previously, when the alignment used to be 16 bytes, the expected
+  // capacity was 79.
+  assert(test_string.capacity() == expected_align8_size);
+}
diff --git a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp
index 5af9cab0be4e80a..a13b3826d5d564c 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp
@@ -18,7 +18,8 @@
 #include "test_macros.h"
 
 // alignment of the string heap buffer is hardcoded to 16
-static const std::size_t alignment = 16;
+
+static const std::size_t alignment = 8;
 
 template <class = int>
 TEST_CONSTEXPR_CXX20 void full_size() {



More information about the libcxx-commits mailing list