Skip to content

Commit ba94eeb

Browse files
committed
[libcxx] adds a size-based representation for vector's unstable ABI
**tl;dr** We can significantly improve the runtime performance of `std::vector` by changing its representation from three pointers to one pointer and two integers. This document explains the details of this change, along with the justifications for making it. See the [RFC] for more information. This commit changes `std::vector`'s representation in a similar manner to `__split_buffer` in #139632. We introduce a layout type that tracks implementation details that differ between the pointer-based vector and size-based vector representations. `vector` does not parameterise its layout type, unlike `__split_buffer`. `__split_buffer` is used by both `vector` and `deque`, and being able to take an ABI break on `vector` doesn't automatically mean that users can also tolerate a break on `deque`. The most convenient way to work around this problem is to parameterise the layout type. Users of `std::vector` should not depend on its layout, and libc++ has no internal reason to toggle it, so we keep the representation concrete. To use this feature, you'll need to configure libc++ so that it's built with `-DLIBCXX_UNSTABLE_ABI=Yes`. [RFC]: https://discourse.llvm.org/t/adding-a-size-based-vector-to-libc-s-unstable-abi/86306
1 parent 94c384c commit ba94eeb

File tree

5 files changed

+597
-284
lines changed

5 files changed

+597
-284
lines changed

libcxx/include/__configuration/abi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
# define _LIBCPP_ABI_NO_REVERSE_ITERATOR_SECOND_MEMBER
8080
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
8181
# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO
82+
# define _LIBCPP_ABI_SIZE_BASED_VECTOR
8283
# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
8384
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
8485
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW

libcxx/include/__split_buffer

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ public:
268268
__set_valid_range(pointer __new_begin, pointer __new_end) _NOEXCEPT {
269269
// Size-based __split_buffers track their size directly: we need to explicitly update the size
270270
// when the front is adjusted.
271-
__size_ -= __new_begin - __begin_;
272271
__begin_ = __new_begin;
273272
__set_sentinel(__new_end);
274273
}
@@ -277,7 +276,6 @@ public:
277276
__set_valid_range(pointer __new_begin, size_type __new_size) _NOEXCEPT {
278277
// Size-based __split_buffers track their size directly: we need to explicitly update the size
279278
// when the front is adjusted.
280-
__size_ -= __new_begin - __begin_;
281279
__begin_ = __new_begin;
282280
__set_sentinel(__new_size);
283281
}
@@ -316,9 +314,9 @@ public:
316314
}
317315

318316
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(
319-
__split_buffer_pointer_layout<__split_buffer<value_type, __alloc_rr&, __split_buffer_pointer_layout>,
320-
value_type,
321-
__alloc_rr&>& __other) _NOEXCEPT {
317+
__split_buffer_size_layout<__split_buffer<value_type, __alloc_rr&, __split_buffer_size_layout>,
318+
value_type,
319+
__alloc_rr&>& __other) _NOEXCEPT {
322320
std::swap(__front_cap_, __other.__front_cap_);
323321
std::swap(__begin_, __other.__begin_);
324322
std::swap(__cap_, __other.__cap_);

0 commit comments

Comments
 (0)