This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] libstdc++/16612
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Mon, 27 Sep 2004 21:08:55 +0200
- Subject: [Patch] libstdc++/16612
Hi all,
the below is what I have tested (with Benjamin's help) as a stop-gap fix
for the applications outlined in PR 16612: indeed, we have tested it
together with the soon-to-be-contributed shared memory allocator.
If --enable-fully-dynamic-string is passed at build time, the empty-string
optimization is completely disabled: this means that there are no major
performance disadvantages after construction time, only the empty string
construction becomes slower, roughly the same speed of a generic size-1 or
2 construction, in other terms. This seems sufficient for the applications
cited in the PR.
For v7, where the ABI can be breaked, *many* other options are possible,
which we'll be exploring in the next weeks...
I will wait 'til tomorrow in case of problematic comments.
Paolo.
///////////////
2004-09-28 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/16612
* include/bits/basic_string.h (_M_dispose, _M_refcopy,
basic_string()): When _GLIBCXX_FULLY_DYNAMIC_STRING is defined,
don't deal with _S_empty_rep.
* include/bits/basic_string.tcc (_S_construct, _M_destroy,
_M_leak_hard, _M_mutate): Likewise.
* acinclude.m4 (GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING): New.
* acconfig.h: Add corresponding undef.
* configure.ac: Use GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING.
* docs/html/configopts.html: Document --enable-fully-dynamic-string.
* configure: Regenerate.
* config.h.in: Likewise.
2004-09-28 Benjamin Kosnik <bkoz@redhat.com>
Paolo Carlini <pcarlini@suse.de>
* testsuite/21_strings/basic_string/operations/char/1.cc: New.
* testsuite/21_strings/basic_string/operations/wchar_t/1.cc: New.
* testsuite/21_strings/basic_string/element_access/char/empty.cc: New.
* testsuite/21_strings/basic_string/element_access/wchar_t/empty.cc:
New.
2004-09-28 Paolo Carlini <pcarlini@suse.de>
* README: Remove obsolete entry about include/c_shadow.
diff -urN libstdc++-v3-orig/README libstdc++-v3/README
--- libstdc++-v3-orig/README 2003-07-28 06:09:59.000000000 +0200
+++ libstdc++-v3/README 2004-09-27 19:04:43.000000000 +0200
@@ -35,13 +35,6 @@
names into the std:: namespace.
[NB: this is the default, and is the same as --enable-cheaders=c_std]
- include/c_shadow
- Headers intended to shadow standard C headers provided by an
- underlying OS or C library, and other headers depended on directly
- by C++ headers (e.g. unistd.h). These are meant to wrap the names
- defined there into the _C_legacy namespace.
- [NB: this can be enabled via --enable-cheaders=c_shadow]
-
include/bits
Files included by standard headers and by other files in
the bits directory.
diff -urN libstdc++-v3-orig/acconfig.h libstdc++-v3/acconfig.h
--- libstdc++-v3-orig/acconfig.h 2004-04-16 11:23:03.000000000 +0200
+++ libstdc++-v3/acconfig.h 2004-09-26 17:32:08.000000000 +0200
@@ -45,6 +45,9 @@
// Define if LFS support is available.
#undef _GLIBCXX_USE_LFS
+// Define if a fully dynamic basic_string is wanted.
+#undef _GLIBCXX_FULLY_DYNAMIC_STRING
+
// Define if NLS translations are to be used.
#undef _GLIBCXX_USE_NLS
diff -urN libstdc++-v3-orig/acinclude.m4 libstdc++-v3/acinclude.m4
--- libstdc++-v3-orig/acinclude.m4 2004-09-21 11:06:02.000000000 +0200
+++ libstdc++-v3/acinclude.m4 2004-09-26 17:32:08.000000000 +0200
@@ -594,6 +594,23 @@
dnl
+dnl Check for whether a fully dynamic basic_string implementation should be
+dnl turned on (mostly useful together with shared_allocator).
+dnl
+dnl --enable-fully-dynamic-string defines _GLIBCXX_FULLY_DYNAMIC_STRING
+dnl --disable-fully-dynamic-string leaves _GLIBCXX_FULLY_DYNAMIC_STRING undefined
+dnl + Usage: GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING[(DEFAULT)]
+dnl Where DEFAULT is either `yes' or `no'.
+dnl
+AC_DEFUN([GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING], [
+ GLIBCXX_ENABLE(fully-dynamic-string,$1,,[enables fully dynamic basic_string])
+ if test $enable_fully_dynamic_string = yes; then
+ AC_DEFINE(_GLIBCXX_FULLY_DYNAMIC_STRING)
+ fi
+])
+
+
+dnl
dnl Does any necessary configuration of the testsuite directory. Generates
dnl the testsuite_hooks.h header.
dnl
diff -urN libstdc++-v3-orig/configure.ac libstdc++-v3/configure.ac
--- libstdc++-v3-orig/configure.ac 2004-08-23 12:18:27.000000000 +0200
+++ libstdc++-v3/configure.ac 2004-09-26 17:32:08.000000000 +0200
@@ -94,6 +94,7 @@
GLIBCXX_ENABLE_DEBUG_FLAGS(["-g3 -O0"])
GLIBCXX_ENABLE_DEBUG([no])
GLIBCXX_ENABLE_CXX_FLAGS
+GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING([no])
# No surprises, no surprises...
if test $atomicity_dir = cpu/generic ; then
diff -urN libstdc++-v3-orig/docs/html/configopts.html libstdc++-v3/docs/html/configopts.html
--- libstdc++-v3-orig/docs/html/configopts.html 2004-08-04 16:40:47.000000000 +0200
+++ libstdc++-v3/docs/html/configopts.html 2004-09-27 19:16:24.000000000 +0200
@@ -144,9 +144,8 @@
<dt><code>--enable-cheaders=OPTION </code></dt>
<dd><p>This allows the user to define what kind of C headers are
- used. Options are: c, c_std, and c_shadow. These correspond
- to the source directory's include/c, include/c_std, and
- include/c_shadow directories. The default is c_std.
+ used. Options are c and c_std. These correspond to the source
+ directory's include/c and include/c_std. The default is c_std.
</p>
</dd>
@@ -261,6 +260,13 @@
</p>
</dd>
+ <dt><code>--enable-fully-dynamic-string </code></dt>
+ <dd><p>This option enables a special version of basic_string avoiding
+ the optimization that allocates empty objects in static memory.
+ Mostly useful together with shared memory allocators.
+ </p>
+ </dd>
+
<dt><code>--enable-concept-checks </code></dt>
<dd><p>This turns on additional compile-time checks for instantiated
library templates, in the form of specialized templates,
diff -urN libstdc++-v3-orig/include/bits/basic_string.h libstdc++-v3/include/bits/basic_string.h
--- libstdc++-v3-orig/include/bits/basic_string.h 2004-07-08 17:56:21.000000000 +0200
+++ libstdc++-v3/include/bits/basic_string.h 2004-09-27 11:45:06.000000000 +0200
@@ -211,7 +211,9 @@
void
_M_dispose(const _Alloc& __a)
{
+#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__builtin_expect(this != &_S_empty_rep(), false))
+#endif
if (__gnu_cxx::__exchange_and_add(&this->_M_refcount, -1) <= 0)
_M_destroy(__a);
} // XXX MT
@@ -222,7 +224,9 @@
_CharT*
_M_refcopy() throw()
{
+#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__builtin_expect(this != &_S_empty_rep(), false))
+#endif
__gnu_cxx::__atomic_add(&this->_M_refcount, 1);
return _M_refdata();
} // XXX MT
@@ -1957,11 +1961,14 @@
size_type __n2) const;
};
-
template<typename _CharT, typename _Traits, typename _Alloc>
inline basic_string<_CharT, _Traits, _Alloc>::
basic_string()
+#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
: _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc()) { }
+#else
+ : _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc()) { }
+#endif
// operator+
/**
diff -urN libstdc++-v3-orig/include/bits/basic_string.tcc libstdc++-v3/include/bits/basic_string.tcc
--- libstdc++-v3-orig/include/bits/basic_string.tcc 2004-06-12 10:10:22.000000000 +0200
+++ libstdc++-v3/include/bits/basic_string.tcc 2004-09-26 17:32:24.000000000 +0200
@@ -88,8 +88,10 @@
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
input_iterator_tag)
{
+#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refdata();
+#endif
// Avoid reallocation for common case.
_CharT __buf[128];
size_type __len = 0;
@@ -134,11 +136,12 @@
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
forward_iterator_tag)
{
+#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refdata();
-
+#endif
// NB: Not required, but considered best practice.
- if (__builtin_expect(__is_null_pointer(__beg), 0))
+ if (__builtin_expect(__is_null_pointer(__beg) && __beg != __end, 0))
__throw_logic_error(__N("basic_string::_S_construct NULL not valid"));
const size_type __dnew = static_cast<size_type>(std::distance(__beg,
@@ -162,9 +165,10 @@
basic_string<_CharT, _Traits, _Alloc>::
_S_construct(size_type __n, _CharT __c, const _Alloc& __a)
{
+#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__n == 0 && __a == _Alloc())
return _S_empty_rep()._M_refdata();
-
+#endif
// Check for out_of_range and length_error exceptions.
_Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
if (__n)
@@ -358,8 +362,10 @@
basic_string<_CharT, _Traits, _Alloc>::_Rep::
_M_destroy(const _Alloc& __a) throw ()
{
+#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (this == &_S_empty_rep())
- return;
+ return;
+#endif
const size_type __size = sizeof(_Rep_base) +
(this->_M_capacity + 1) * sizeof(_CharT);
_Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
@@ -369,8 +375,10 @@
void
basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard()
{
+#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (_M_rep() == &_S_empty_rep())
- return;
+ return;
+#endif
if (_M_rep()->_M_is_shared())
_M_mutate(0, 0, 0);
_M_rep()->_M_set_leaked();
@@ -385,8 +393,12 @@
const size_type __new_size = __old_size + __len2 - __len1;
const size_type __how_much = __old_size - __pos - __len1;
+#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (_M_rep() == &_S_empty_rep()
|| _M_rep()->_M_is_shared() || __new_size > capacity())
+#else
+ if (_M_rep()->_M_is_shared() || __new_size > capacity())
+#endif
{
// Must reallocate.
const allocator_type __a = get_allocator();
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/element_access/char/empty.cc libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/empty.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/element_access/char/empty.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/empty.cc 2004-09-26 17:32:08.000000000 +0200
@@ -0,0 +1,48 @@
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+//
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <string>
+#include <testsuite_hooks.h>
+
+// as per 21.3.4
+int main()
+{
+ bool test __attribute__((unused)) = true;
+
+ {
+ std::string empty;
+ char c = empty[0];
+ VERIFY( c == char() );
+ }
+
+ {
+ const std::string empty;
+ char c = empty[0];
+ VERIFY( c == char() );
+ }
+ return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/element_access/wchar_t/empty.cc libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/empty.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/element_access/wchar_t/empty.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/empty.cc 2004-09-26 17:32:08.000000000 +0200
@@ -0,0 +1,48 @@
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+//
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <string>
+#include <testsuite_hooks.h>
+
+// as per 21.3.4
+int main()
+{
+ bool test __attribute__((unused)) = true;
+
+ {
+ std::wstring empty;
+ wchar_t c = empty[0];
+ VERIFY( c == wchar_t() );
+ }
+
+ {
+ const std::wstring empty;
+ wchar_t c = empty[0];
+ VERIFY( c == wchar_t() );
+ }
+ return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/operations/char/1.cc libstdc++-v3/testsuite/21_strings/basic_string/operations/char/1.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/operations/char/1.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/21_strings/basic_string/operations/char/1.cc 2004-09-26 17:32:08.000000000 +0200
@@ -0,0 +1,42 @@
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 21.3.6 string operations
+
+#include <string>
+#include <testsuite_hooks.h>
+
+int test01(void)
+{
+ bool test __attribute__((unused)) = true;
+
+ std::string empty;
+
+ // data() for size == 0 is non-NULL.
+ VERIFY( empty.size() == 0 );
+ const std::string::value_type* p = empty.data();
+ VERIFY( p != NULL );
+
+ return 0;
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/operations/wchar_t/1.cc libstdc++-v3/testsuite/21_strings/basic_string/operations/wchar_t/1.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/operations/wchar_t/1.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/21_strings/basic_string/operations/wchar_t/1.cc 2004-09-26 17:32:08.000000000 +0200
@@ -0,0 +1,42 @@
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 21.3.6 string operations
+
+#include <string>
+#include <testsuite_hooks.h>
+
+int test01(void)
+{
+ bool test __attribute__((unused)) = true;
+
+ std::wstring empty;
+
+ // data() for size == 0 is non-NULL.
+ VERIFY( empty.size() == 0 );
+ const std::wstring::value_type* p = empty.data();
+ VERIFY( p != NULL );
+
+ return 0;
+}
+
+int main()
+{
+ test01();
+ return 0;
+}