From d260ea7199bce566fb4229eac5cc4c5d4843c5f0 Mon Sep 17 00:00:00 2001 From: Martijn Vels Date: Wed, 26 Feb 2020 13:25:43 -0500 Subject: [PATCH] Inline basic_string::erase for fastpath where __n == npos Summary: This change checks for the case where people want to erase a string to the end, i.e., __n == npos, and inlines the call if so. This also demonstrates keeping the ABI intact for V1, but inlining the erase() method for unstable. Reviewers: EricWF, mclow.lists, ldionne Reviewed By: EricWF, ldionne Subscribers: smeenai, dexonsmith, christof, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D73743 --- libcxx/include/__string | 2 +- libcxx/include/string | 29 +++++++++++++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/libcxx/include/__string b/libcxx/include/__string index 6a95245..2aeaeb8 100644 --- a/libcxx/include/__string +++ b/libcxx/include/__string @@ -170,7 +170,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::erase(size_type, size_type)) \ + _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__erase_external_with_move(size_type, size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \ diff --git a/libcxx/include/string b/libcxx/include/string index 42767e2..2c90dae 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1574,6 +1574,10 @@ private: _LIBCPP_INLINE_VISIBILITY void __erase_to_end(size_type __pos); + // __erase_external_with_move is invoked for erase() invocations where + // `n ~= npos`, likely requiring memory moves on the string data. + void __erase_external_with_move(size_type __pos, size_type __n); + _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const basic_string& __str) {__copy_assign_alloc(__str, integral_constant::replace(const_iterator __i1, const_it // erase +// 'externally instantiated' erase() implementation, called when __n != npos. +// Does not check __pos against size() template -basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n) +void +basic_string<_CharT, _Traits, _Allocator>::__erase_external_with_move( + size_type __pos, size_type __n) { - size_type __sz = size(); - if (__pos > __sz) - this->__throw_out_of_range(); if (__n) { + size_type __sz = size(); value_type* __p = _VSTD::__to_address(__get_pointer()); __n = _VSTD::min(__n, __sz - __pos); size_type __n_move = __sz - __pos - __n; @@ -3016,7 +3021,19 @@ basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n) __invalidate_iterators_past(__sz); traits_type::assign(__p[__sz], value_type()); } - return *this; +} + +template +basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, + size_type __n) { + if (__pos > size()) this->__throw_out_of_range(); + if (__n == npos) { + __erase_to_end(__pos); + } else { + __erase_external_with_move(__pos, __n); + } + return *this; } template -- 2.7.4