[libcxx-commits] [libcxx] [libc++] Refactor how we do amortized growth (PR #171117)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 23 04:38:44 PST 2026


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/171117

>From 29c7d38b77b55e42966bf0d80fccbe330415d6a5 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 8 Dec 2025 13:07:30 +0100
Subject: [PATCH] [libc++] Refactor how we do amortized growth

---
 libcxx/include/string | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index 34af7efb56659..8508ccf68b085 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -2272,17 +2272,24 @@ private:
 
   // Allocate a buffer of __capacity size with __alloc and return it
   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 __long
-  __allocate_long_buffer(_Allocator& __alloc, size_type __capacity) {
-    _LIBCPP_ASSERT_INTERNAL(!__fits_in_sso(__capacity),
+  __allocate_long_buffer(_Allocator& __alloc, size_type __size, size_type __min_capacity) {
+    _LIBCPP_ASSERT_INTERNAL(
+        __size <= __min_capacity, "Trying to allocate a long buffer with a smaller capacity than size");
+    _LIBCPP_ASSERT_INTERNAL(!__fits_in_sso(__min_capacity),
                             "Trying to allocate long buffer for a capacity what would fit into the small buffer");
-    auto __buffer = std::__allocate_at_least(__alloc, __align_allocation_size(__capacity));
+    auto __buffer = std::__allocate_at_least(__alloc, __align_allocation_size(__min_capacity));
 
     if (__libcpp_is_constant_evaluated()) {
       for (size_type __i = 0; __i != __buffer.count; ++__i)
         std::__construct_at(std::addressof(__buffer.ptr[__i]));
     }
 
-    return __long(__buffer, __capacity);
+    return __long(__buffer, __size);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 __long
+  __allocate_long_buffer(_Allocator& __alloc, size_type __size) {
+    return __allocate_long_buffer(__alloc, __size, __size);
   }
 
   // Replace the current buffer with __new_rep. Deallocate the old long buffer if it exists.
@@ -2728,7 +2735,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
     size_type __n_del,
     size_type __n_add,
     const value_type* __p_new_stuff) {
-  __long __buffer = __allocate_long_buffer(__alloc_, __get_amortized_growth_capacity(__old_cap + __delta_cap));
+  __long __buffer = __allocate_long_buffer(__alloc_, 0, __get_amortized_growth_capacity(__old_cap + __delta_cap));
   pointer __old_p = __get_pointer();
   __annotate_delete();
   auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
@@ -2761,7 +2768,9 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
     size_type __n_copy,
     size_type __n_del,
     size_type __n_add) {
-  __long __buffer = __allocate_long_buffer(__alloc_, __get_amortized_growth_capacity(__old_cap + __delta_cap));
+  // The size is -1 to make sure the caller sets the size properly, since old versions of this function didn't set the
+  // size at all.
+  __long __buffer = __allocate_long_buffer(__alloc_, -1, __get_amortized_growth_capacity(__old_cap + __delta_cap));
   pointer __old_p = __get_pointer();
   if (__n_copy != 0)
     traits_type::copy(std::__to_address(__buffer.__data_), std::__to_address(__old_p), __n_copy);
@@ -2770,10 +2779,6 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
     traits_type::copy(std::__to_address(__buffer.__data_) + __n_copy + __n_add,
                       std::__to_address(__old_p) + __n_copy + __n_del,
                       __sec_cp_sz);
-
-  // This is -1 to make sure the caller sets the size properly, since old versions of this function didn't set the size
-  // at all.
-  __buffer.__size_ = -1;
   __reset_internal_buffer(__buffer);
 }
 
@@ -3419,8 +3424,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::re
     return;
 
   __annotation_guard __g(*this);
-  __long __buffer  = __allocate_long_buffer(__alloc_, __requested_capacity);
-  __buffer.__size_ = size();
+  __long __buffer = __allocate_long_buffer(__alloc_, size(), __requested_capacity);
   traits_type::copy(std::__to_address(__buffer.__data_), data(), __buffer.__size_ + 1);
   __reset_internal_buffer(__buffer);
 }



More information about the libcxx-commits mailing list