This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [1/2] Add option to disable c++11 std::string small-size


Updated.


On 05/29/2018 09:53 AM, Mikhail Kashkarov wrote:
> Add option to disable c++11 std::string small-sizeoptimization usage.
>
>       * include/bits/basic_string.h [_GLIBCXX_DISABLE_STRING_SSO_USAGE]:
>       (basic_string::_M_is_local, basic_string::_M_destroy)
>       (basic_string::basic_string, basic_string::basic_string(const _Alloc&))
>       (basic_string::basic_string(basic_string&&))
>       (basic_string::basic_string(basic_string&&, const _Alloc&))
>       (basic_string::operator=(const basic_string&))
>       (basic_string::operator=(basic_string&&))
>       (basic_string::clear()): Disable usage of _M_local_buf if
>        _GLIBCXX_DISABLE_STRING_SSO_USAGE is defined.
>       * include/bits/basic_string.tcc [_GLIBCXX_DISABLE_STRING_SSO_USAGE]:
>       (basic_string::_M_construct, basic_string::reserve)
>       (basic_string::_M_replace): Disable usage of _M_local_buf if
>       _GLIBCXX_DISABLE_STRING_SSO_USAGE is defined.
>       * testsuite/basic_string/allocator/char/copy_assign.cc: Support for
>       std::string without SSO.
>       * testsuite/basic_string/allocator/wchar_t/copy_assign.cc: Likewise.
>       * testsuite/21_strings/basic_string/init-list.cc: Likewise.
>       * testsuite/rand/assoc/rand_regression_test.hpp: Likewise.
>       * testsuite/rand/priority_queue/rand_regression_test.hpp: Likewise.
>

-- 
Best regards,
Kashkarov Mikhail
Samsung R&D Institute Russia

From 49c34919fba3000d751ac505b498eb6b21b0f4b3 Mon Sep 17 00:00:00 2001
From: Mikhail Kashkarov <m.kashkarov@partner.samsung.com>
Date: Fri, 8 Jun 2018 12:22:33 +0300
Subject: [PATCH 1/2] Add option to disable c++11 std::basic_string SSO
 optimization.

	* include/bits/basic_string.h [_GLIBCXX_DISABLE_STRING_SSO_USAGE]:
	(basic_string::_M_is_local())
	(basic_string::_M_destroy(size_type __size))
	(basic_string::basic_string())
	(basic_string::basic_string(const _Alloc& __a))
	(basic_string::basic_string(basic_string&& __str))
	(basic_string::basic_string(basic_string&& __str, const _Alloc& __a))
	(basic_string::operator=(const basic_string& __str))
	(basic_string::operator=(basic_string&& __str))
	(basic_string::clear()): Disable usage of _M_local_buf if
	 _GLIBCXX_DISABLE_STRING_SSO_USAGE is defined.
	* include/bits/basic_string.tcc [_GLIBCXX_DISABLE_STRING_SSO_USAGE]:
	(basic_string::_M_construct, basic_string::reserve)
	(basic_string::_M_replace): Disable usage of _M_local_buf if
	_GLIBCXX_DISABLE_STRING_SSO_USAGE is defined.
	* testsuite/basic_string/allocator/char/copy_assign.cc: Support for
	std::string without SSO.
	* testsuite/basic_string/allocator/wchar_t/copy_assign.cc: Likewise.
	* testsuite/21_strings/basic_string/init-list.cc: Likewise.
	* testsuite/rand/assoc/rand_regression_test.hpp: Likewise.
	* testsuite/rand/priority_queue/rand_regression_test.hpp: Likewise.
---
 libstdc++-v3/include/bits/basic_string.h           | 104 +++++++++++++++++++--
 libstdc++-v3/include/bits/basic_string.tcc         |  46 ++++++++-
 .../basic_string/allocator/char/copy_assign.cc     |   4 +
 .../basic_string/allocator/wchar_t/copy_assign.cc  |   4 +
 .../testsuite/21_strings/basic_string/init-list.cc |   2 +
 .../regression/rand/assoc/rand_regression_test.hpp |   5 +
 .../rand/priority_queue/rand_regression_test.hpp   |   5 +
 7 files changed, 156 insertions(+), 14 deletions(-)

diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 5bffa1c..9d971c0 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -208,7 +208,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 
       bool
       _M_is_local() const
-      { return _M_data() == _M_local_data(); }
+      {
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	return false;
+#else
+	return _M_data() == _M_local_data();
+#endif
+      }
 
       // Create & Destroy
       pointer
@@ -223,7 +229,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 
       void
       _M_destroy(size_type __size) throw()
-      { _Alloc_traits::deallocate(_M_get_allocator(), _M_data(), __size + 1); }
+      {
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	if (!_M_allocated_capacity)
+	  return;
+#endif
+        _Alloc_traits::deallocate(_M_get_allocator(), _M_data(), __size + 1);
+      }
 
       // _M_construct_aux is used to implement the 21.3.1 para 15 which
       // requires special behaviour if _InIterator is an integral type
@@ -420,7 +432,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       basic_string()
       _GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Alloc>::value)
       : _M_dataplus(_M_local_data())
-      { _M_set_length(0); }
+      {
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	_M_length(0);
+	_M_capacity(0);
+#else
+	_M_set_length(0);
+#endif
+      }
 
       /**
        *  @brief  Construct an empty string using allocator @a a.
@@ -428,7 +447,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       explicit
       basic_string(const _Alloc& __a) _GLIBCXX_NOEXCEPT
       : _M_dataplus(_M_local_data(), __a)
-      { _M_set_length(0); }
+      {
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	_M_length(0);
+	_M_capacity(0);
+#else
+	_M_set_length(0);
+#endif
+      }
 
       /**
        *  @brief  Construct string with copy of value of @a __str.
@@ -531,12 +557,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       basic_string(basic_string&& __str) noexcept
       : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator()))
       {
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
 	if (__str._M_is_local())
 	  {
 	    traits_type::copy(_M_local_buf, __str._M_local_buf,
 			      _S_local_capacity + 1);
 	  }
 	else
+#endif
 	  {
 	    _M_data(__str._M_data());
 	    _M_capacity(__str._M_allocated_capacity);
@@ -546,8 +574,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 	// basic_stringbuf relies on writing into unallocated capacity so
 	// we mess up the contents if we put a '\0' in the string.
 	_M_length(__str.length());
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	__str._M_data(nullptr);
+	__str._M_length(0);
+	__str._M_capacity(0);
+#else
 	__str._M_data(__str._M_local_data());
 	__str._M_set_length(0);
+#endif
       }
 
       /**
@@ -567,6 +601,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       noexcept(_Alloc_traits::_S_always_equal())
       : _M_dataplus(_M_local_data(), __a)
       {
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
 	if (__str._M_is_local())
 	  {
 	    traits_type::copy(_M_local_buf, __str._M_local_buf,
@@ -574,14 +609,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 	    _M_length(__str.length());
 	    __str._M_set_length(0);
 	  }
-	else if (_Alloc_traits::_S_always_equal()
+	else
+#endif
+	  if (_Alloc_traits::_S_always_equal()
 	    || __str.get_allocator() == __a)
 	  {
 	    _M_data(__str._M_data());
 	    _M_length(__str.length());
 	    _M_capacity(__str._M_allocated_capacity);
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	    __str._M_data(nullptr);
+	    __str._M_length(0);
+	    __str._M_capacity(0);
+#else
 	    __str._M_data(__str._M_local_buf);
 	    __str._M_set_length(0);
+#endif
+
 	  }
 	else
 	  _M_construct(__str.begin(), __str.end());
@@ -661,6 +705,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 	      {
 		// Propagating allocator cannot free existing storage so must
 		// deallocate it before replacing current allocator.
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
 		if (__str.size() <= _S_local_capacity)
 		  {
 		    _M_destroy(_M_allocated_capacity);
@@ -668,14 +713,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 		    _M_set_length(0);
 		  }
 		else
+#endif
 		  {
 		    const auto __len = __str.size();
 		    auto __alloc = __str._M_get_allocator();
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+		    const auto __new_cap = __len > size_type(_S_local_capacity)
+		      ? __len : size_type(_S_local_capacity);
+#else
+		    const auto __new_cap = __len;
+#endif
 		    // If this allocation throws there are no effects:
-		    auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1);
+		    auto __ptr = _Alloc_traits::allocate(__alloc, __new_cap + 1);
 		    _M_destroy(_M_allocated_capacity);
 		    _M_data(__ptr);
-		    _M_capacity(__len);
+		    _M_capacity(__new_cap);
 		    _M_set_length(__len);
 		  }
 	      }
@@ -728,8 +780,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 	  {
 	    // Destroy existing storage before replacing allocator.
 	    _M_destroy(_M_allocated_capacity);
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	    _M_length(0);
+	    _M_capacity(0);
+#else
 	    _M_data(_M_local_data());
 	    _M_set_length(0);
+#endif
 	  }
 	// Replace allocator if POCMA is true.
 	std::__alloc_on_move(_M_get_allocator(), __str._M_get_allocator());
@@ -740,15 +797,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 	  {
 	    pointer __data = nullptr;
 	    size_type __capacity;
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	    size_type __length;
+#endif
 	    if (!_M_is_local())
 	      {
 		if (_Alloc_traits::_S_always_equal())
 		  {
 		    __data = _M_data();
 		    __capacity = _M_allocated_capacity;
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+		    __length = _M_string_length;
+#endif
 		  }
-		else
+		else {
 		  _M_destroy(_M_allocated_capacity);
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+		  _M_length(0);
+		  _M_capacity(0);
+#endif
+		}
 	      }
 
 	    _M_data(__str._M_data());
@@ -758,9 +826,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 	      {
 		__str._M_data(__data);
 		__str._M_capacity(__capacity);
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+		__str._M_length(__length);
+#endif
 	      }
-	    else
+	    else {
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	      __str._M_data(nullptr);
+	      __str._M_length(0);
+	      __str._M_capacity(0);
+#else
 	      __str._M_data(__str._M_local_buf);
+#endif
+      }
 	  }
 	else
 	    assign(__str);
@@ -1002,7 +1080,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        */
       void
       clear() _GLIBCXX_NOEXCEPT
-      { _M_set_length(0); }
+      {
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	_M_allocated_capacity ? _M_set_length(0) : _M_length(0);
+#else
+	_M_set_length(0);
+#endif
+      }
 
       /**
        *  Returns true if the %string is empty.  Equivalent to 
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index be8815c..6b6c7eb 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -137,6 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (__capacity > max_size())
 	std::__throw_length_error(__N("basic_string::_M_create"));
 
+
       // The below implements an exponential growth policy, necessary to
       // meet amortized linear time requirements of the library: see
       // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
@@ -165,7 +166,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		   std::input_iterator_tag)
       {
 	size_type __len = 0;
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	size_type __capacity = size_type(0);
+	_M_capacity(0);
+#else
 	size_type __capacity = size_type(_S_local_capacity);
+#endif
 
 	while (__beg != __end && __len < __capacity)
 	  {
@@ -181,6 +187,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		  {
 		    // Allocate more space.
 		    __capacity = __len + 1;
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+		    if (__capacity < size_type(_S_local_capacity))
+		      __capacity = size_type(_S_local_capacity);
+#endif
 		    pointer __another = _M_create(__capacity, __len);
 		    this->_S_copy(__another, _M_data(), __len);
 		    _M_dispose();
@@ -213,11 +223,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				       "_M_construct null not valid"));
 
 	size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
+	size_type __new_capacity = __dnew;
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	if (__new_capacity < size_type(_S_local_capacity))
+	  __new_capacity = size_type(_S_local_capacity);
+#endif
 
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
 	if (__dnew > size_type(_S_local_capacity))
+#endif
 	  {
-	    _M_data(_M_create(__dnew, size_type(0)));
-	    _M_capacity(__dnew);
+	    _M_data(_M_create(__new_capacity, size_type(0)));
+	    _M_capacity(__new_capacity);
 	  }
 
 	// Check for out_of_range and length_error exceptions.
@@ -237,10 +254,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     basic_string<_CharT, _Traits, _Alloc>::
     _M_construct(size_type __n, _CharT __c)
     {
+      size_type __new_capacity = __n;
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+      if (__new_capacity < size_type(_S_local_capacity))
+	__new_capacity = size_type(_S_local_capacity);
+#endif 
+
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
       if (__n > size_type(_S_local_capacity))
+#endif
 	{
-	  _M_data(_M_create(__n, size_type(0)));
-	  _M_capacity(__n);
+	  _M_data(_M_create(__new_capacity, size_type(0)));
+	  _M_capacity(__new_capacity);
 	}
 
       if (__n)
@@ -271,7 +296,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  if (__rsize)
 	    this->_S_copy(_M_data(), __str._M_data(), __rsize);
 
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+	  _M_allocated_capacity ? _M_set_length(__rsize) : _M_length(__rsize);
+#else
 	  _M_set_length(__rsize);
+#endif
 	}
     }
 
@@ -287,8 +316,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const size_type __capacity = capacity();
       if (__res != __capacity)
 	{
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
 	  if (__res > __capacity
 	      || __res > size_type(_S_local_capacity))
+#endif
 	    {
 	      pointer __tmp = _M_create(__res, __capacity);
 	      this->_S_copy(__tmp, _M_data(), length() + 1);
@@ -296,12 +327,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	      _M_data(__tmp);
 	      _M_capacity(__res);
 	    }
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
 	  else if (!_M_is_local())
 	    {
 	      this->_S_copy(_M_local_data(), _M_data(), length() + 1);
 	      _M_destroy(__capacity);
 	      _M_data(_M_local_data());
 	    }
+#endif
 	}
     }
 
@@ -465,7 +498,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       else
 	this->_M_mutate(__pos, __len1, __s, __len2);
 
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+      this->_M_allocated_capacity ? this->_M_set_length(__new_size) :
+	this->_M_length(__new_size);
+#else
       this->_M_set_length(__new_size);
+#endif
       return *this;
     }
 
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc
index 2e4a71e..91a8f88 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc
@@ -122,7 +122,11 @@ void test03()
   VERIFY( v1 == s1 );
   VERIFY( v1.get_allocator() == a1 );
 
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
   throw_alloc::set_limit(1); // Allow one more allocation (and no more).
+#else
+  throw_alloc::set_limit(2); // Allow allocations if sso is disabled
+#endif
   test_type v3(s1, a1);
   // No allocation when allocators are equal and capacity is sufficient:
   VERIFY( v1.capacity() >= v3.size() );
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc
index 5de9c9e..70c1461 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc
@@ -122,7 +122,11 @@ void test03()
   VERIFY( v1 == s1 );
   VERIFY( v1.get_allocator() == a1 );
 
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
   throw_alloc::set_limit(1); // Allow one more allocation (and no more).
+#else
+  throw_alloc::set_limit(2); // Allow allocations if sso is disabled
+#endif
   test_type v3(s1, a1);
   // No allocation when allocators are equal and capacity is sufficient:
   VERIFY( v1.capacity() >= v3.size() );
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/init-list.cc b/libstdc++-v3/testsuite/21_strings/basic_string/init-list.cc
index 2cc9cff..b1e0333 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/init-list.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/init-list.cc
@@ -62,7 +62,9 @@ void test01(void)
 
 int main()
 {
+#if !_GLIBCXX_DISABLE_STRING_SSO_USAGE
   __gnu_test::set_memory_limits();
+#endif
   test01();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/util/regression/rand/assoc/rand_regression_test.hpp b/libstdc++-v3/testsuite/util/regression/rand/assoc/rand_regression_test.hpp
index 274a70c..c645d19 100644
--- a/libstdc++-v3/testsuite/util/regression/rand/assoc/rand_regression_test.hpp
+++ b/libstdc++-v3/testsuite/util/regression/rand/assoc/rand_regression_test.hpp
@@ -105,7 +105,12 @@ namespace detail
     size_t n = iter;
     size_t m = keys;
     size_t sd = twister_rand_gen::get_time_determined_seed();
+    // Without SSO string can allocate memory when sso-string would not.
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+    double tp = 0.0;
+#else
     double tp = 0.2;
+#endif
     double ip = 0.6;
     double ep = 0.2;
     double cp = 0.001;
diff --git a/libstdc++-v3/testsuite/util/regression/rand/priority_queue/rand_regression_test.hpp b/libstdc++-v3/testsuite/util/regression/rand/priority_queue/rand_regression_test.hpp
index 62eb19a..ca6e197 100644
--- a/libstdc++-v3/testsuite/util/regression/rand/priority_queue/rand_regression_test.hpp
+++ b/libstdc++-v3/testsuite/util/regression/rand/priority_queue/rand_regression_test.hpp
@@ -104,7 +104,12 @@ namespace detail
     size_t n = iter;
     size_t m = keys;
     size_t sd = twister_rand_gen::get_time_determined_seed();
+    // Without SSO string can allocate memory when sso-string would not.
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+    double tp = 0.0;
+#else
     double tp = 0.2;
+#endif
     double ip = 0.6;
     double dp = 0.1;
     double ep = 0.2;
-- 
2.7.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]