Skip to content

Commit a39cb38

Browse files
committed
[libc++] Make __allocate_long_buffer a constructor of __long
1 parent bb4ed55 commit a39cb38

File tree

1 file changed

+43
-63
lines changed

1 file changed

+43
-63
lines changed

libcxx/include/string

Lines changed: 43 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -825,31 +825,44 @@ public:
825825
private:
826826
static_assert(CHAR_BIT == 8, "This implementation assumes that one byte contains 8 bits");
827827

828-
# ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
829-
828+
// Attribute 'packed' is used to keep the layout compatible with the
829+
// previous definition that did not use bit fields. This is because on
830+
// some platforms bit fields have a default size rather than the actual
831+
// size used, e.g., it is 4 bytes on AIX. See D128285 for details.
830832
struct __long {
831833
__long() = default;
832834

833-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __long(__alloc_result __alloc, size_type __size)
834-
: __data_(__alloc.ptr), __size_(__size), __cap_(__alloc.count / __endian_factor), __is_long_(true) {
835-
_LIBCPP_ASSERT_INTERNAL(!__fits_in_sso(__alloc.count), "Long capacity should always be larger than the SSO");
835+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __long(_Allocator& __alloc, size_type __size)
836+
: __is_long_(true), __size_(__size) {
837+
_LIBCPP_ASSERT_INTERNAL(!__fits_in_sso(__size), "Long capacity should always be larger than the SSO");
838+
auto __allocation = std::__allocate_at_least(__alloc, __recommend(__size) + 1);
839+
840+
__cap_ = __allocation.count / __endian_factor;
841+
__data_ = __allocation.ptr;
842+
843+
if (__libcpp_is_constant_evaluated()) {
844+
for (size_type __i = 0; __i != __allocation.count; ++__i)
845+
std::__construct_at(std::addressof(__allocation.ptr[__i]));
846+
}
836847
}
837848

849+
# ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
838850
pointer __data_;
839851
size_type __size_;
840-
size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
852+
size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
841853
size_type __is_long_ : 1;
854+
# else
855+
struct _LIBCPP_PACKED {
856+
size_type __is_long_ : 1;
857+
size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
858+
};
859+
size_type __size_;
860+
pointer __data_;
861+
# endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
842862
};
843863

844864
enum { __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 ? (sizeof(__long) - 1) / sizeof(value_type) : 2 };
845865

846-
struct __short {
847-
value_type __data_[__min_cap];
848-
_LIBCPP_NO_UNIQUE_ADDRESS __padding<sizeof(value_type) - 1> __padding_;
849-
unsigned char __size_ : 7;
850-
unsigned char __is_long_ : 1;
851-
};
852-
853866
// The __endian_factor is required because the field we use to store the size
854867
// has one fewer bit than it would if it were not a bitfield.
855868
//
@@ -862,42 +875,22 @@ private:
862875
// If the MSB is used for the short-flag, the max_size() is numeric_limits<size_type>::max() / 2.
863876
// This does not impact the short string representation, since we never need the MSB
864877
// for representing the size of a short string anyway.
865-
866-
# ifdef _LIBCPP_BIG_ENDIAN
878+
#if defined(_LIBCPP_BIG_ENDIAN) == defined(_LIBCPP_ABI_ALTERNATE_STRING_LAYOUT)
867879
static const size_type __endian_factor = 2;
868-
# else
869-
static const size_type __endian_factor = 1;
870-
# endif
871-
872-
# else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
873-
874-
# ifdef _LIBCPP_BIG_ENDIAN
880+
#else
875881
static const size_type __endian_factor = 1;
876-
# else
877-
static const size_type __endian_factor = 2;
878-
# endif
879-
880-
// Attribute 'packed' is used to keep the layout compatible with the
881-
// previous definition that did not use bit fields. This is because on
882-
// some platforms bit fields have a default size rather than the actual
883-
// size used, e.g., it is 4 bytes on AIX. See D128285 for details.
884-
struct __long {
885-
__long() = default;
882+
#endif
886883

887-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __long(__alloc_result __alloc, size_type __size)
888-
: __is_long_(true), __cap_(__alloc.count / __endian_factor), __size_(__size), __data_(__alloc.ptr) {
889-
_LIBCPP_ASSERT_INTERNAL(!__fits_in_sso(__alloc.count), "Long capacity should always be larger than the SSO");
890-
}
884+
# ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
891885

892-
struct _LIBCPP_PACKED {
893-
size_type __is_long_ : 1;
894-
size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
895-
};
896-
size_type __size_;
897-
pointer __data_;
886+
struct __short {
887+
value_type __data_[__min_cap];
888+
_LIBCPP_NO_UNIQUE_ADDRESS __padding<sizeof(value_type) - 1> __padding_;
889+
unsigned char __size_ : 7;
890+
unsigned char __is_long_ : 1;
898891
};
899892

900-
enum { __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 ? (sizeof(__long) - 1) / sizeof(value_type) : 2 };
893+
# else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
901894

902895
struct __short {
903896
struct _LIBCPP_PACKED {
@@ -2255,19 +2248,6 @@ private:
22552248
// These functions are only responsible for managing the buffer itself, not the value inside the buffer. As such,
22562249
// none of these facilities ensure that there is a null terminator at `data()[size()]`.
22572250

2258-
// Allocate a buffer of __capacity size with __alloc and return it
2259-
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 __long
2260-
__allocate_long_buffer(_Allocator& __alloc, size_type __capacity) {
2261-
auto __buffer = std::__allocate_at_least(__alloc, __recommend(__capacity) + 1);
2262-
2263-
if (__libcpp_is_constant_evaluated()) {
2264-
for (size_type __i = 0; __i != __buffer.count; ++__i)
2265-
std::__construct_at(std::addressof(__buffer.ptr[__i]));
2266-
}
2267-
2268-
return __long(__buffer, __capacity);
2269-
}
2270-
22712251
// Replace the current buffer with __new_rep. Deallocate the old long buffer if it exists.
22722252
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __reset_internal_buffer(__rep __new_rep = __short()) {
22732253
__annotate_delete();
@@ -2290,7 +2270,7 @@ private:
22902270
__annotate_new(__size);
22912271
return __get_short_pointer();
22922272
} else {
2293-
__rep_.__l = __allocate_long_buffer(__alloc_, __size);
2273+
__rep_ = __long(__alloc_, __size);
22942274
__annotate_new(__size);
22952275
return __get_long_pointer();
22962276
}
@@ -2447,7 +2427,7 @@ private:
24472427
__annotate_delete();
24482428
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
24492429
auto __alloc = __str.__alloc_;
2450-
__reset_internal_buffer(__allocate_long_buffer(__alloc, __str.size()));
2430+
__reset_internal_buffer(__long(__alloc, __str.size()));
24512431
__alloc_ = std::move(__alloc);
24522432
}
24532433
}
@@ -2700,8 +2680,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
27002680
size_type __cap =
27012681
__old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms;
27022682
__annotate_delete();
2703-
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
2704-
__long __buffer = __allocate_long_buffer(__alloc_, __cap);
2683+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
2684+
__long __buffer(__alloc_, __cap);
27052685
if (__n_copy != 0)
27062686
traits_type::copy(std::__to_address(__buffer.__data_), std::__to_address(__old_p), __n_copy);
27072687
if (__n_add != 0)
@@ -2737,7 +2717,7 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
27372717
pointer __old_p = __get_pointer();
27382718
size_type __cap =
27392719
__old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms;
2740-
__long __buffer = __allocate_long_buffer(__alloc_, __cap);
2720+
__long __buffer(__alloc_, __cap);
27412721
if (__n_copy != 0)
27422722
traits_type::copy(std::__to_address(__buffer.__data_), std::__to_address(__old_p), __n_copy);
27432723
size_type __sec_cp_sz = __old_sz - __n_del - __n_copy;
@@ -3394,7 +3374,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::re
33943374
return;
33953375

33963376
__annotation_guard __g(*this);
3397-
__long __buffer = __allocate_long_buffer(__alloc_, __requested_capacity);
3377+
__long __buffer(__alloc_, __requested_capacity);
33983378
__buffer.__size_ = size();
33993379
traits_type::copy(std::__to_address(__buffer.__data_), data(), __buffer.__size_ + 1);
34003380
__reset_internal_buffer(__buffer);
@@ -3425,7 +3405,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
34253405
try {
34263406
# endif // _LIBCPP_HAS_EXCEPTIONS
34273407
__annotation_guard __g(*this);
3428-
__long __buffer = __allocate_long_buffer(__alloc_, __size);
3408+
__long __buffer(__alloc_, __size);
34293409

34303410
// The Standard mandates shrink_to_fit() does not increase the capacity.
34313411
// With equal capacity keep the existing buffer. This avoids extra work

0 commit comments

Comments
 (0)