[libcxx-commits] [PATCH] D75211: Partially inline basic_string::operator=(const basic_string&)

Martijn Vels via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Mon Mar 2 07:04:23 PST 2020


This revision was not accepted when it landed; it landed in state "Needs Revision".
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf87d30cba2b5: Partially inline basic_string::operator=(const basic_string&) (authored by mvels).

Changed prior to commit:
  https://reviews.llvm.org/D75211?vs=246857&id=247634#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75211/new/

https://reviews.llvm.org/D75211

Files:
  libcxx/include/__string
  libcxx/include/string


Index: libcxx/include/string
===================================================================
--- libcxx/include/string
+++ libcxx/include/string
@@ -1571,6 +1571,12 @@
                                size_type __n_copy,  size_type __n_del,
                                size_type __n_add, const value_type* __p_new_stuff);
 
+    // __assign_no_alias is invoked for assignment operations where we
+    // have proof that the input does not alias the current instance.
+    // For example, operator=(basic_string) performs a 'self' check.
+    template <bool __is_short>
+    void __assign_no_alias(const value_type* __s, size_type __n);
+
     _LIBCPP_INLINE_VISIBILITY
     void __erase_to_end(size_type __pos);
 
@@ -2203,6 +2209,23 @@
 // assign
 
 template <class _CharT, class _Traits, class _Allocator>
+template <bool __is_short>
+void basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(
+    const value_type* __s, size_type __n) {
+  size_type __cap = __is_short ? __min_cap : __get_long_cap();
+  if (__n < __cap) {
+    pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer();
+    __is_short ? __set_short_size(__n) : __set_long_size(__n);
+    traits_type::copy(_VSTD::__to_address(__p), __s, __n);
+    traits_type::assign(__p[__n], value_type());
+    __invalidate_iterators_past(__n);
+  } else {
+    size_type __sz = __is_short ? __get_short_size() : __get_long_size();
+    __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s);
+  }
+}
+
+template <class _CharT, class _Traits, class _Allocator>
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n)
 {
@@ -2268,16 +2291,19 @@
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
 {
-    if (this != &__str)
-    {
-        __copy_assign_alloc(__str);
-        const bool __str_is_long = __str.__is_long(); // Force single branch
-        if (__is_long() || __str_is_long) {
-          return assign(__str.data(), __str.size());
-        }
+  if (this != &__str) {
+    __copy_assign_alloc(__str);
+    if (!__is_long()) {
+      if (!__str.__is_long()) {
         __r_.first().__r = __str.__r_.first().__r;
+      } else {
+        __assign_no_alias<true>(__str.data(), __str.size());
+      }
+    } else {
+      __assign_no_alias<false>(__str.data(), __str.size());
     }
-    return *this;
+  }
+  return *this;
 }
 
 #ifndef _LIBCPP_CXX03_LANG
Index: libcxx/include/__string
===================================================================
--- libcxx/include/__string
+++ libcxx/include/__string
@@ -165,6 +165,8 @@
   _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
   _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
   _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \
+  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__assign_no_alias<false>(value_type const*, size_type)) \
+  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__assign_no_alias<true>(value_type const*, size_type)) \
   _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
   _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
   _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
@@ -179,7 +181,6 @@
   _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
   _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
   _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \
-  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \
   _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
   _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
   _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D75211.247634.patch
Type: text/x-patch
Size: 4617 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20200302/163274a1/attachment.bin>


More information about the libcxx-commits mailing list