From 389d2b0e371f72e07d537125119ca5cb447645e8 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Tue, 29 Oct 2024 16:28:33 -0400 Subject: [PATCH 1/2] Refactor __split_buffer to eliminate code duplication --- libcxx/include/__split_buffer | 67 +++++++---------------------------- 1 file changed, 12 insertions(+), 55 deletions(-) diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index 6fc3d9255946c..de3779b981047 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -152,6 +152,8 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_front(_Args&&... __args); template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args); @@ -456,28 +458,17 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) { - if (__begin_ == __first_) { - if (__end_ < __end_cap()) { - difference_type __d = __end_cap() - __end_; - __d = (__d + 1) / 2; - __begin_ = std::move_backward(__begin_, __end_, __end_ + __d); - __end_ += __d; - } else { - size_type __c = std::max(2 * static_cast(__end_cap() - __first_), 1); - __split_buffer __t(__c, (__c + 3) / 4, __alloc()); - __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); - std::swap(__first_, __t.__first_); - std::swap(__begin_, __t.__begin_); - std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); - } - } - __alloc_traits::construct(__alloc(), std::__to_address(__begin_ - 1), __x); - --__begin_; + emplace_front(__x); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) { + emplace_front(std::move(__x)); +} + +template +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_front(_Args&&... __args) { if (__begin_ == __first_) { if (__end_ < __end_cap()) { difference_type __d = __end_cap() - __end_; @@ -494,53 +485,19 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_front(v std::swap(__end_cap(), __t.__end_cap()); } } - __alloc_traits::construct(__alloc(), std::__to_address(__begin_ - 1), std::move(__x)); + __alloc_traits::construct(__alloc(), std::__to_address(__begin_ - 1), std::forward<_Args>(__args)...); --__begin_; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void __split_buffer<_Tp, _Allocator>::push_back(const_reference __x) { - if (__end_ == __end_cap()) { - if (__begin_ > __first_) { - difference_type __d = __begin_ - __first_; - __d = (__d + 1) / 2; - __end_ = std::move(__begin_, __end_, __begin_ - __d); - __begin_ -= __d; - } else { - size_type __c = std::max(2 * static_cast(__end_cap() - __first_), 1); - __split_buffer __t(__c, __c / 4, __alloc()); - __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); - std::swap(__first_, __t.__first_); - std::swap(__begin_, __t.__begin_); - std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); - } - } - __alloc_traits::construct(__alloc(), std::__to_address(__end_), __x); - ++__end_; + emplace_back(__x); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) { - if (__end_ == __end_cap()) { - if (__begin_ > __first_) { - difference_type __d = __begin_ - __first_; - __d = (__d + 1) / 2; - __end_ = std::move(__begin_, __end_, __begin_ - __d); - __begin_ -= __d; - } else { - size_type __c = std::max(2 * static_cast(__end_cap() - __first_), 1); - __split_buffer __t(__c, __c / 4, __alloc()); - __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); - std::swap(__first_, __t.__first_); - std::swap(__begin_, __t.__begin_); - std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); - } - } - __alloc_traits::construct(__alloc(), std::__to_address(__end_), std::move(__x)); - ++__end_; + emplace_back(std::move(__x)); } template From 4a2ff6baa73fa16486bab2cdd1d941591ad560c2 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Thu, 31 Oct 2024 09:19:33 -0400 Subject: [PATCH 2/2] Replace all usages of __split_buffer::push_{back,front} by emplace_{back,front} --- libcxx/include/__split_buffer | 25 --------------- libcxx/include/__vector/vector.h | 4 +-- libcxx/include/deque | 52 ++++++++++++++++---------------- 3 files changed, 28 insertions(+), 53 deletions(-) diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index de3779b981047..102df63e814ae 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -147,10 +147,6 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(const_reference __x); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x); template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_front(_Args&&... __args); @@ -456,16 +452,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi } } -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) { - emplace_front(__x); -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) { - emplace_front(std::move(__x)); -} - template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_front(_Args&&... __args) { @@ -489,17 +475,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_fron --__begin_; } -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void -__split_buffer<_Tp, _Allocator>::push_back(const_reference __x) { - emplace_back(__x); -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) { - emplace_back(std::move(__x)); -} - template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) { diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h index 844e5d6a21056..7d95e5deef5f3 100644 --- a/libcxx/include/__vector/vector.h +++ b/libcxx/include/__vector/vector.h @@ -1263,7 +1263,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) } else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); - __v.push_back(__x); + __v.emplace_back(__x); __p = __swap_out_circular_buffer(__v, __p); } return __make_iter(__p); @@ -1283,7 +1283,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) { } else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); - __v.push_back(std::move(__x)); + __v.emplace_back(std::move(__x)); __p = __swap_out_circular_buffer(__v, __p); } return __make_iter(__p); diff --git a/libcxx/include/deque b/libcxx/include/deque index 11219d1a99244..1a83465b39ef8 100644 --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -2041,20 +2041,20 @@ void deque<_Tp, _Allocator>::__add_front_capacity() { __start_ += __block_size; pointer __pt = __map_.back(); __map_.pop_back(); - __map_.push_front(__pt); + __map_.emplace_front(__pt); } // Else if __map_.size() < __map_.capacity() then we need to allocate 1 buffer else if (__map_.size() < __map_.capacity()) { // we can put the new buffer into the map, but don't shift things around // until all buffers are allocated. If we throw, we don't need to fix // anything up (any added buffers are undetectible) if (__map_.__front_spare() > 0) - __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_front(__alloc_traits::allocate(__a, __block_size)); else { - __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_back(__alloc_traits::allocate(__a, __block_size)); // Done allocating, reorder capacity pointer __pt = __map_.back(); __map_.pop_back(); - __map_.push_front(__pt); + __map_.emplace_front(__pt); } __start_ = __map_.size() == 1 ? __block_size / 2 : __start_ + __block_size; } @@ -2065,11 +2065,11 @@ void deque<_Tp, _Allocator>::__add_front_capacity() { typedef __allocator_destructor<_Allocator> _Dp; unique_ptr __hold(__alloc_traits::allocate(__a, __block_size), _Dp(__a, __block_size)); - __buf.push_back(__hold.get()); + __buf.emplace_back(__hold.get()); __hold.release(); for (__map_pointer __i = __map_.begin(); __i != __map_.end(); ++__i) - __buf.push_back(*__i); + __buf.emplace_back(*__i); std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); @@ -2095,7 +2095,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { for (; __back_capacity > 0; --__back_capacity) { pointer __pt = __map_.back(); __map_.pop_back(); - __map_.push_front(__pt); + __map_.emplace_front(__pt); } } // Else if __nb <= __map_.capacity() - __map_.size() then we need to allocate __nb buffers @@ -2106,17 +2106,17 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { for (; __nb > 0; --__nb, __start_ += __block_size - (__map_.size() == 1)) { if (__map_.__front_spare() == 0) break; - __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_front(__alloc_traits::allocate(__a, __block_size)); __annotate_whole_block(0, __asan_poison); } for (; __nb > 0; --__nb, ++__back_capacity) - __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_back(__alloc_traits::allocate(__a, __block_size)); // Done allocating, reorder capacity __start_ += __back_capacity * __block_size; for (; __back_capacity > 0; --__back_capacity) { pointer __pt = __map_.back(); __map_.pop_back(); - __map_.push_front(__pt); + __map_.emplace_front(__pt); __annotate_whole_block(0, __asan_poison); } } @@ -2129,7 +2129,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __nb > 0; --__nb) { - __buf.push_back(__alloc_traits::allocate(__a, __block_size)); + __buf.emplace_back(__alloc_traits::allocate(__a, __block_size)); // ASan: this is empty container, we have to poison whole block __annotate_poison_block(std::__to_address(__buf.back()), std::__to_address(__buf.back() + __block_size)); } @@ -2142,11 +2142,11 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { } #endif // _LIBCPP_HAS_EXCEPTIONS for (; __back_capacity > 0; --__back_capacity) { - __buf.push_back(__map_.back()); + __buf.emplace_back(__map_.back()); __map_.pop_back(); } for (__map_pointer __i = __map_.begin(); __i != __map_.end(); ++__i) - __buf.push_back(*__i); + __buf.emplace_back(*__i); std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); @@ -2164,20 +2164,20 @@ void deque<_Tp, _Allocator>::__add_back_capacity() { __start_ -= __block_size; pointer __pt = __map_.front(); __map_.pop_front(); - __map_.push_back(__pt); + __map_.emplace_back(__pt); } // Else if __nb <= __map_.capacity() - __map_.size() then we need to allocate __nb buffers else if (__map_.size() < __map_.capacity()) { // we can put the new buffer into the map, but don't shift things around // until it is allocated. If we throw, we don't need to fix // anything up (any added buffers are undetectible) if (__map_.__back_spare() != 0) - __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_back(__alloc_traits::allocate(__a, __block_size)); else { - __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_front(__alloc_traits::allocate(__a, __block_size)); // Done allocating, reorder capacity pointer __pt = __map_.front(); __map_.pop_front(); - __map_.push_back(__pt); + __map_.emplace_back(__pt); } __annotate_whole_block(__map_.size() - 1, __asan_poison); } @@ -2188,11 +2188,11 @@ void deque<_Tp, _Allocator>::__add_back_capacity() { typedef __allocator_destructor<_Allocator> _Dp; unique_ptr __hold(__alloc_traits::allocate(__a, __block_size), _Dp(__a, __block_size)); - __buf.push_back(__hold.get()); + __buf.emplace_back(__hold.get()); __hold.release(); for (__map_pointer __i = __map_.end(); __i != __map_.begin();) - __buf.push_front(*--__i); + __buf.emplace_front(*--__i); std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); @@ -2217,7 +2217,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { for (; __front_capacity > 0; --__front_capacity) { pointer __pt = __map_.front(); __map_.pop_front(); - __map_.push_back(__pt); + __map_.emplace_back(__pt); } } // Else if __nb <= __map_.capacity() - __map_.size() then we need to allocate __nb buffers @@ -2228,11 +2228,11 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { for (; __nb > 0; --__nb) { if (__map_.__back_spare() == 0) break; - __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_back(__alloc_traits::allocate(__a, __block_size)); __annotate_whole_block(__map_.size() - 1, __asan_poison); } for (; __nb > 0; --__nb, ++__front_capacity, __start_ += __block_size - (__map_.size() == 1)) { - __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_front(__alloc_traits::allocate(__a, __block_size)); __annotate_whole_block(0, __asan_poison); } // Done allocating, reorder capacity @@ -2240,7 +2240,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { for (; __front_capacity > 0; --__front_capacity) { pointer __pt = __map_.front(); __map_.pop_front(); - __map_.push_back(__pt); + __map_.emplace_back(__pt); } } // Else need to allocate __nb buffers, *and* we need to reallocate __map_. @@ -2254,7 +2254,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __nb > 0; --__nb) { - __buf.push_back(__alloc_traits::allocate(__a, __block_size)); + __buf.emplace_back(__alloc_traits::allocate(__a, __block_size)); // ASan: this is an empty container, we have to poison the whole block __annotate_poison_block(std::__to_address(__buf.back()), std::__to_address(__buf.back() + __block_size)); } @@ -2267,11 +2267,11 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { } #endif // _LIBCPP_HAS_EXCEPTIONS for (; __front_capacity > 0; --__front_capacity) { - __buf.push_back(__map_.front()); + __buf.emplace_back(__map_.front()); __map_.pop_front(); } for (__map_pointer __i = __map_.end(); __i != __map_.begin();) - __buf.push_front(*--__i); + __buf.emplace_front(*--__i); std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_);