diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1545,11 +1545,31 @@ #define _LIBCPP_BUILTIN_CONSTANT_P(x) false #endif +#if defined(__BIONIC__) && defined(__USE_FILE_OFFSET64) && __ANDROID_API__ < 24 +#define _LIBCPP_HAS_NO_FGETPOS_FSETPOS +#endif + +// define try / catch / throw macros. +// The intended use case is to deal with exceptions transparently for rollbacks: +// _LIBCCP_TRY { +// ++__p_; +// __this_may_fail(__p); +// } _CATCH_ALL { +// --__p_; +// _LIBCPP_THROW; +// } +// When compiling with exceptions disabled, the CATCH_ALL block is elided. // Support for _FILE_OFFSET_BITS=64 landed gradually in Android, so the full set // of functions used in cstdio may not be available for low API levels when // using 64-bit file offsets on LP32. -#if defined(__BIONIC__) && defined(__USE_FILE_OFFSET64) && __ANDROID_API__ < 24 -#define _LIBCPP_HAS_NO_FGETPOS_FSETPOS +#ifdef _LIBCPP_NO_EXCEPTIONS +#define _LIBCPP_TRY +#define _LIBCPP_CATCH_ALL if (false) +#define _LIBCPP_THROW +#else +#define _LIBCPP_TRY try +#define _LIBCPP_CATCH_ALL catch(...) +#define _LIBCPP_THROW throw #endif #endif // __cplusplus diff --git a/libcxx/include/vector b/libcxx/include/vector --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -490,6 +490,10 @@ typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; + typedef typename _VSTD::conditional< + _VSTD::is_same >::value, allocator_type, + allocator_type&>::type __allocator_ref; + static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); @@ -663,6 +667,7 @@ bool empty() const _NOEXCEPT {return this->__begin_ == this->__end_;} size_type max_size() const _NOEXCEPT; + static size_type __max_size(__allocator_ref __a) _NOEXCEPT; void reserve(size_type __n); void shrink_to_fit() _NOEXCEPT; @@ -804,6 +809,8 @@ void __vallocate(size_type __n); void __vdeallocate() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const; + static _LIBCPP_INLINE_VISIBILITY size_type + __recommend(__allocator_ref __a, size_type __old_cap, size_type __new_size); void __construct_at_end(size_type __n); _LIBCPP_INLINE_VISIBILITY void __construct_at_end(size_type __n, const_reference __x); @@ -820,6 +827,25 @@ iterator __make_iter(pointer __p) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY const_iterator __make_iter(const_pointer __p) const _NOEXCEPT; + inline void __apply(_VSTD::pair __r, + size_type __byte_size) _NOEXCEPT { + __invalidate_all_iterators(); + this->__begin_ = __r.first; + this->__end_cap() = __r.second; + + // What we would like to express: + // __builtin_assume((__byte_size % sizeof(value_type)) == 0); + // this->__end_ = __r.first + __byte_size / sizeof(value_type); + // What works: + this->__end_ = + pointer_traits::pointer_to(*reinterpret_cast( + reinterpret_cast(_VSTD::__to_address(__r.first)) + + __byte_size)); + } + + static _VSTD::pair __swap_out_circular_buffer( + __split_buffer& __v, pointer __begin, + pointer __end, pointer __end_cap); void __swap_out_circular_buffer(__split_buffer& __v); pointer __swap_out_circular_buffer(__split_buffer& __v, pointer __p); void __move_range(pointer __from_s, pointer __from_e, pointer __to); @@ -836,18 +862,26 @@ __annotate_shrink(__old_size); } + inline size_type __byte_size() const _NOEXCEPT { + return sizeof(value_type) * + static_cast(this->__end_ - this->__begin_); + } + #ifndef _LIBCPP_CXX03_LANG template - _LIBCPP_INLINE_VISIBILITY - inline pointer __push_back_slow_path(_Up&& __x); + static _LIBCPP_INLINE_VISIBILITY inline _VSTD::pair + __push_back_slow_path(__allocator_ref __a, pointer __begin, pointer __end, + _Up&& __x); template - _LIBCPP_INLINE_VISIBILITY - inline pointer __emplace_back_slow_path(_Args&&... __args); + static _LIBCPP_INLINE_VISIBILITY inline _VSTD::pair + __emplace_back_slow_path(__allocator_ref __a, pointer __begin, + pointer __end, _Args&&... __args); #else template - _LIBCPP_INLINE_VISIBILITY - inline pointer __push_back_slow_path(_Up& __x); + static _LIBCPP_INLINE_VISIBILITY inline _VSTD::pair + __push_back_slow_path(__allocator_ref __a, pointer __begin, pointer __end, + _Up& __x); #endif // The following functions are no-ops outside of AddressSanitizer mode. @@ -855,19 +889,27 @@ // may not meet the AddressSanitizer alignment constraints. // See the documentation for __sanitizer_annotate_contiguous_container for more details. #ifndef _LIBCPP_HAS_NO_ASAN - void __annotate_contiguous_container(const void *__beg, const void *__end, - const void *__old_mid, - const void *__new_mid) const - { - + static void __annotate_contiguous_container(const void* __beg, + const void* __end, + const void* __old_mid, + const void* __new_mid) { if (__beg && is_same::value) __sanitizer_annotate_contiguous_container(__beg, __end, __old_mid, __new_mid); } #else _LIBCPP_INLINE_VISIBILITY - void __annotate_contiguous_container(const void*, const void*, const void*, - const void*) const _NOEXCEPT {} + static void __annotate_contiguous_container(const void*, const void*, + const void*, + const void*) _NOEXCEPT {} #endif + _LIBCPP_INLINE_VISIBILITY + static void __annotate(const_pointer __beg, const_pointer __end, + const_pointer __old_mid, const_pointer __new_mid) _NOEXCEPT { + __annotate_contiguous_container( + _VSTD::__to_address(__beg), _VSTD::__to_address(__end), + _VSTD::__to_address(__old_mid), _VSTD::__to_address(__new_mid)); + } + _LIBCPP_INLINE_VISIBILITY void __annotate_new(size_type __current_size) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), @@ -919,39 +961,6 @@ _ConstructTransaction& operator=(_ConstructTransaction const&) = delete; }; -#if defined(_LIBCPP_HAS_NO_ASAN) - struct _AsanTransaction { - explicit _AsanTransaction(vector&, size_type) {} - void __commit(size_type) {} - }; -#elif defined(_LIBCPP_NO_EXCEPTIONS) - struct _AsanTransaction { - explicit _AsanTransaction(vector &, size_type __n) { - __v_.__annotate_increase(__n); - } - void __commit(size_type) {} - }; -#else // _LIBCPP_NO_EXCEPTIONS - struct _AsanTransaction { - _AsanTransaction(vector& __v, size_type __n) : __v_(__v), __n(__n) { - __v_.__annotate_increase(__n); - } - ~_AsanTransaction() { __v_.__annotate_shrink(__n_); } - void __commit(size_type __n) { __n_ -= __n; } - vector& __v_; - size_t __n_; - }; -#endif // _LIBCPP_NO_EXCEPTIONS - - template - _LIBCPP_INLINE_VISIBILITY void __construct_one_at(pointer __pos, - _Args&&... __args) { - _AsanTransaction tx(*this, 1); - __alloc_traits::construct(this->__alloc(), _VSTD::__to_address(__pos), - _VSTD::forward<_Args>(__args)...); - tx.__commit(1); - } - template _LIBCPP_INLINE_VISIBILITY void __construct_one_at_end(_Args&& ...__args) { @@ -978,6 +987,23 @@ -> vector::value_type, _Alloc>; #endif +template +_VSTD::pair::pointer, + typename vector<_Tp, _Allocator>::pointer> +vector<_Tp, _Allocator>::__swap_out_circular_buffer( + __split_buffer& __v, pointer __begin, + pointer __end, pointer __end_cap) { + __alloc_traits::__construct_backward_with_exception_guarantees( + __v.__alloc(), __begin, __end, __v.__begin_); + __annotate(__begin, __end_cap, __end, __end_cap); + __annotate(__v.__begin_, __v.__end_cap(), __v.__end_cap(), __v.__end_); + _VSTD::pair __r(__v.__begin_, __v.__end_cap()); + __v.__first_ = __v.__begin_ = __begin; + __v.__end_ = __end; + __v.__end_cap() = __end_cap; + return __r; +} + template void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v) @@ -1051,6 +1077,24 @@ numeric_limits::max()); } +template +typename vector<_Tp, _Allocator>::size_type vector<_Tp, _Allocator>::__max_size( + __allocator_ref __a) _NOEXCEPT { + return _VSTD::min(__alloc_traits::max_size(__a), + numeric_limits::max()); +} + +// Precondition: __new_size > old_cap +template +inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type +vector<_Tp, _Allocator>::__recommend(__allocator_ref __a, size_type __old_cap, + size_type __new_size) { + const size_type __ms = __max_size(__a); + if (__new_size > __ms) _VSTD::__throw_length_error("vector"); + if (__old_cap >= __ms / 2) return __ms; + return _VSTD::max(2 * __old_cap, __new_size); +} + // Precondition: __new_size > capacity() template inline _LIBCPP_INLINE_VISIBILITY @@ -1647,20 +1691,26 @@ template template -typename vector<_Tp, _Allocator>::pointer +_VSTD::pair::pointer, + typename vector<_Tp, _Allocator>::pointer> #ifndef _LIBCPP_CXX03_LANG -vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x) +vector<_Tp, _Allocator>::__push_back_slow_path(__allocator_ref __a, + pointer __begin, pointer __end, + _Up&& __x) #else -vector<_Tp, _Allocator>::__push_back_slow_path(_Up& __x) +vector<_Tp, _Allocator>::__push_back_slow_path(__allocator_ref __a, + pointer __begin, pointer __end, + _Up& __x) #endif { - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + 1), size(), __a); - // __v.push_back(_VSTD::forward<_Up>(__x)); - __alloc_traits::construct(__a, _VSTD::__to_address(__v.__end_), _VSTD::forward<_Up>(__x)); - __v.__end_++; - __swap_out_circular_buffer(__v); - return this->__end_; + const size_type __size = __end - __begin; + const size_type __n = __recommend(__a, __size, __size + 1); + __split_buffer __v(__n, __size, __a); + // __v.push_back(_VSTD::forward<_Up>(__x)); + __alloc_traits::construct(__a, _VSTD::__to_address(__v.__end_), + _VSTD::forward<_Up>(__x)); + __v.__end_++; + return __swap_out_circular_buffer(__v, __begin, __end, __end); } template @@ -1668,47 +1718,46 @@ void vector<_Tp, _Allocator>::push_back(const_reference __x) { - pointer __end = this->__end_; - if (__end != this->__end_cap()) - { - __construct_one_at(__end, __x); - } - else { - __end = __push_back_slow_path(__x) - 1; - } - this->__end_ = __end + 1; + if (this->__end_ != this->__end_cap()) { + __construct_one_at_end(__x); + } else { + const size_type __next_byte_size = this->__byte_size() + sizeof(value_type); + __apply(__push_back_slow_path(this->__alloc(), this->__begin_, this->__end_, + __x), + __next_byte_size); + } } #ifndef _LIBCPP_CXX03_LANG template -inline _LIBCPP_INLINE_VISIBILITY -void -vector<_Tp, _Allocator>::push_back(value_type&& __x) -{ - pointer __end = this->__end_; - if (__end != this->__end_cap()) - { - __construct_one_at(__end, _VSTD::move(__x)); - } - else { - __end = __push_back_slow_path(std::move(__x)) - 1; - } - this->__end_ = __end + 1; +inline _LIBCPP_INLINE_VISIBILITY void vector<_Tp, _Allocator>::push_back( + value_type&& __x) { + if (this->__end_ != this->__end_cap()) { + __construct_one_at_end(_VSTD::move(__x)); + } else { + const size_type __next_byte_size = this->__byte_size() + sizeof(value_type); + __apply(__push_back_slow_path(this->__alloc(), this->__begin_, this->__end_, + _VSTD::move(__x)), + __next_byte_size); + } } template template -typename vector<_Tp, _Allocator>::pointer -vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) -{ - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + 1), size(), __a); -// __v.emplace_back(_VSTD::forward<_Args>(__args)...); - __alloc_traits::construct(__a, _VSTD::__to_address(__v.__end_), _VSTD::forward<_Args>(__args)...); - __v.__end_++; - __swap_out_circular_buffer(__v); - return this->__end_; +_VSTD::pair::pointer, + typename vector<_Tp, _Allocator>::pointer> +vector<_Tp, _Allocator>::__emplace_back_slow_path(__allocator_ref __a, + pointer __begin, + pointer __end, + _Args&&... __args) { + const size_type __size = __end - __begin; + const size_type __n = __recommend(__a, __size, __size + 1); + __split_buffer __v(__n, __size, __a); + __alloc_traits::construct(__a, _VSTD::__to_address(__v.__end_), + _VSTD::forward<_Args>(__args)...); + __v.__end_++; + return __swap_out_circular_buffer(__v, __begin, __end, __end); } template @@ -1721,17 +1770,17 @@ #endif vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) { - pointer __end = this->__end_; - if (__end < this->__end_cap()) - { - __construct_one_at(__end, _VSTD::forward<_Args>(__args)...); - } - else { - __end = __emplace_back_slow_path(_VSTD::forward<_Args>(__args)...) - 1; - } - this->__end_ = __end + 1; + if (this->__end_ != this->__end_cap()) { + __construct_one_at_end(_VSTD::forward<_Args>(__args)...); + } else { + const size_type __next_byte_size = this->__byte_size() + sizeof(value_type); + __apply( + __emplace_back_slow_path(this->__alloc(), this->__begin_, this->__end_, + _VSTD::forward<_Args>(__args)...), + __next_byte_size); + } #if _LIBCPP_STD_VER > 14 - return *__end; + return this->back(); #endif }