This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[1/2] Add option to disable c++11 std::string small-size
- From: Mikhail Kashkarov <m dot kashkarov at partner dot samsung dot com>
- To: "libstdc++ at gcc dot gnu dot org" <libstdc++ at gcc dot gnu dot org>
- Cc: Vyacheslav Barinov <v dot barinov at samsung dot com>, Ivan Baravy <i dot baravy at samsung dot com>
- Date: Tue, 29 May 2018 09:53:36 +0300
- Subject: [1/2] Add option to disable c++11 std::string small-size
- Cms-type: 201P
- Dkim-filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20180529065340euoutp02c84bb31fcf81e2a914b6f8cd6db8a100~zCwZXrRnT0774907749euoutp02G
- References: <c8b18d2a-d5c7-e3a2-53be-30b39eadeb49@partner.samsung.com> <CGME20180529065338eucas1p127354210f72c34ce750608240d909a32@eucas1p1.samsung.com>
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.
From 3da36c25a1626445e910656d68603655016f39cf Mon Sep 17 00:00:00 2001
From: Michel K <fruitclover@gmail.com>
Date: Tue, 29 May 2018 00:42:46 +0300
Subject: [PATCH 1/2] Add options to disable c++11 std::string small-size
optimization 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.
---
libstdc++-v3/include/bits/basic_string.h | 94 ++++++++++++++++++++--
libstdc++-v3/include/bits/basic_string.tcc | 47 ++++++++---
.../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, 144 insertions(+), 17 deletions(-)
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 5bffa1c..d37aa0f 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,6 +713,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_M_set_length(0);
}
else
+#endif
{
const auto __len = __str.size();
auto __alloc = __str._M_get_allocator();
@@ -728,8 +774,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 +791,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 +820,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 +1074,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..744831b 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -165,7 +165,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)
{
@@ -213,11 +218,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"_M_construct null not valid"));
size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
-
- if (__dnew > size_type(_S_local_capacity))
+ size_type __new_capacity = __dnew;
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+ bool __need_capacity = true;
+ if (__new_capacity < size_type(_S_local_capacity))
+ __new_capacity = size_type(_S_local_capacity);
+#else
+ bool __need_capacity = __dnew > size_type(_S_local_capacity);
+#endif
+ if (__need_capacity)
{
- _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 +249,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_string<_CharT, _Traits, _Alloc>::
_M_construct(size_type __n, _CharT __c)
{
- if (__n > size_type(_S_local_capacity))
+ size_type __new_capacity = __n;
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+ bool __need_capacity = true;
+ if (__new_capacity < size_type(_S_local_capacity))
+ __new_capacity = size_type(_S_local_capacity);
+#else
+ bool __need_capacity = __n > size_type(_S_local_capacity);
+#endif
+ if (__need_capacity)
{
- _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)
@@ -287,8 +307,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const size_type __capacity = capacity();
if (__res != __capacity)
{
- if (__res > __capacity
- || __res > size_type(_S_local_capacity))
+#if _GLIBCXX_DISABLE_STRING_SSO_USAGE
+ bool __need_capacity = true;
+#else
+ bool __need_capacity = (__res > __capacity || __res > size_type(_S_local_capacity));
+#endif
+ if (__need_capacity)
{
pointer __tmp = _M_create(__res, __capacity);
this->_S_copy(__tmp, _M_data(), length() + 1);
@@ -465,7 +489,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