Optimize locale::_M_impl->_M_names for the most common cases...
authorPaolo Carlini <pcarlini@suse.de>
Mon, 3 May 2004 12:14:07 +0000 (12:14 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Mon, 3 May 2004 12:14:07 +0000 (12:14 +0000)
2004-05-03  Paolo Carlini  <pcarlini@suse.de>

Optimize locale::_M_impl->_M_names for the most common cases:
!_M_names[0] means unnamed; !_M_names[1] means all the categories
the same name (_M_names[0] && _M_names[1] means that the full set
of _M_names must be processed, the general case).
* include/bits/locale_classes.h (locale::_Impl::_M_check_same_name):
Tweak, saving work when !_M_names[1].
(locale::locale(const locale&, _Facet*): Simplify: now just setting
_M_names[0] = 0 means unnamed.
* src/locale.cc (locale::operator==): Deal first with the common,
easy cases, otherwise fall back to locale::name().
(locale::name()): Tweak, if !_M_names[0] just return "*".
(locale::_Impl::_Impl(const _Impl&, size_t): Tweak, early stop
copying __imp._M_names if !__imp._M_names[0] or !__imp._M_names[1].
* src/locale_init.cc (locale::_Impl::_Impl(size_t)): Tweak.
* src/localename.cc (locale::_Impl::_Impl(const char*, size_t):
Simplify when !std::strchr, just updating _M_names[0]; clean up.
(locale::_Impl::_M_replace_categories): When !_M_names[1] prepare
for the general case (full set of names), then do the usual work;
clean up.

* src/locale.cc (locale::name()): Reserve space in __ret.
* src/locale_init.cc (locale::global(const locale&)): Save
the name in a temporary.
* src/localename.cc (locale::locale(const char*)): Reserve space
in __str.

From-SVN: r81430

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/locale_classes.h
libstdc++-v3/src/locale.cc
libstdc++-v3/src/locale_init.cc
libstdc++-v3/src/localename.cc

index f61c644..ba311c5 100644 (file)
@@ -1,3 +1,31 @@
+2004-05-03  Paolo Carlini  <pcarlini@suse.de>
+
+       Optimize locale::_M_impl->_M_names for the most common cases:
+       !_M_names[0] means unnamed; !_M_names[1] means all the categories
+       the same name (_M_names[0] && _M_names[1] means that the full set
+       of _M_names must be processed, the general case).
+       * include/bits/locale_classes.h (locale::_Impl::_M_check_same_name):
+       Tweak, saving work when !_M_names[1].
+       (locale::locale(const locale&, _Facet*): Simplify: now just setting
+       _M_names[0] = 0 means unnamed.
+       * src/locale.cc (locale::operator==): Deal first with the common,
+       easy cases, otherwise fall back to locale::name().
+       (locale::name()): Tweak, if !_M_names[0] just return "*".
+       (locale::_Impl::_Impl(const _Impl&, size_t): Tweak, early stop
+       copying __imp._M_names if !__imp._M_names[0] or !__imp._M_names[1].
+       * src/locale_init.cc (locale::_Impl::_Impl(size_t)): Tweak.
+       * src/localename.cc (locale::_Impl::_Impl(const char*, size_t):
+       Simplify when !std::strchr, just updating _M_names[0]; clean up.
+       (locale::_Impl::_M_replace_categories): When !_M_names[1] prepare
+       for the general case (full set of names), then do the usual work;
+       clean up.
+
+       * src/locale.cc (locale::name()): Reserve space in __ret.
+       * src/locale_init.cc (locale::global(const locale&)): Save
+       the name in a temporary.
+       * src/localename.cc (locale::locale(const char*)): Reserve space
+       in __str.
+
 2004-04-29  Paolo Carlini  <pcarlini@suse.de>
 
        * src/locale.cc (locale::operator==): Always avoid constructing
index 926ce20..5366d65 100644 (file)
@@ -534,8 +534,10 @@ namespace std
     _M_check_same_name()
     {
       bool __ret = true;
-      for (size_t __i = 0; __ret && __i < _S_categories_size - 1; ++__i)
-       __ret = std::strcmp(_M_names[__i], _M_names[__i + 1]) == 0;
+      if (_M_names[1])
+       // We must actually compare all the _M_names: can be all equal!
+       for (size_t __i = 0; __ret && __i < _S_categories_size - 1; ++__i)
+         __ret = std::strcmp(_M_names[__i], _M_names[__i + 1]) == 0;
       return __ret;
     }
 
@@ -569,30 +571,15 @@ namespace std
     {
       _M_impl = new _Impl(*__other._M_impl, 1);
 
-      char* _M_tmp_names[_S_categories_size];
-      size_t __i = 0;
       try
-       {
-         for (; __i < _S_categories_size; ++__i)
-           {
-             _M_tmp_names[__i] = new char[2];
-             std::strcpy(_M_tmp_names[__i], "*");
-           }
-         _M_impl->_M_install_facet(&_Facet::id, __f);
-       }
+       { _M_impl->_M_install_facet(&_Facet::id, __f); }
       catch(...)
        {
          _M_impl->_M_remove_reference();
-         for (size_t __j = 0; __j < __i; ++__j)
-           delete [] _M_tmp_names[__j];
          __throw_exception_again;
        }
-
-      for (size_t __k = 0; __k < _S_categories_size; ++__k)
-       {
-         delete [] _M_impl->_M_names[__k];
-         _M_impl->_M_names[__k] = _M_tmp_names[__k];
-       }
+      delete [] _M_impl->_M_names[0];
+      _M_impl->_M_names[0] = 0;   // Unnamed.
     }
 } // namespace std
 
index af4f34d..64d0c62 100644 (file)
@@ -70,15 +70,21 @@ namespace std
   bool
   locale::operator==(const locale& __rhs) const throw()
   {
-    bool __ret = true;
+    // Deal first with the common cases, fast to process: refcopies,
+    // unnamed (i.e., !_M_names[0]), "simple" (!_M_names[1] => all the
+    // categories same name, i.e., _M_names[0]). Otherwise fall back
+    // to the general locale::name().
+    bool __ret;
     if (_M_impl == __rhs._M_impl)
-      ;
-    else if (!std::strcmp(_M_impl->_M_names[0], "*"))
+      __ret = true;
+    else if (!_M_impl->_M_names[0] || !__rhs._M_impl->_M_names[0]
+            || std::strcmp(_M_impl->_M_names[0],
+                           __rhs._M_impl->_M_names[0]) != 0)
       __ret = false;
+    else if (!_M_impl->_M_names[1] && !__rhs._M_impl->_M_names[1])
+      __ret = true;
     else
-      for (size_t __i = 0; __ret && __i < _S_categories_size; ++__i)
-       __ret = !std::strcmp(_M_impl->_M_names[__i],
-                            __rhs._M_impl->_M_names[__i]);
+      __ret = this->name() == __rhs.name();
     return __ret;
   }
 
@@ -95,10 +101,13 @@ namespace std
   locale::name() const
   {
     string __ret;
-    if (_M_impl->_M_check_same_name())
+    if (!_M_impl->_M_names[0])
+      __ret = '*';
+    else if (_M_impl->_M_check_same_name())
       __ret = _M_impl->_M_names[0];
     else
       {
+       __ret.reserve(128);
        __ret += _S_categories[0];
        __ret += '=';
        __ret += _M_impl->_M_names[0]; 
@@ -242,12 +251,13 @@ namespace std
        for (size_t __i = 0; __i < _S_categories_size; ++__i)
          _M_names[__i] = 0;
 
-       // Name all the categories.
-       for (size_t __i = 0; __i < _S_categories_size; ++__i)
+       // Name the categories.
+       for (size_t __i = 0; (__i < _S_categories_size
+                             && __imp._M_names[__i]); ++__i)
          {
-           char* __new = new char[std::strlen(__imp._M_names[__i]) + 1];
-           std::strcpy(__new, __imp._M_names[__i]);
-           _M_names[__i] = __new;
+           const size_t __len = std::strlen(__imp._M_names[__i]) + 1;
+           _M_names[__i] = new char[__len];
+           std::memcpy(_M_names[__i], __imp._M_names[__i], __len);
          }
       }
     catch(...)
@@ -354,7 +364,6 @@ namespace std
       }
   }
 
-
   // locale::id
   // Definitions for static const data members of locale::id
   _Atomic_word locale::id::_S_refcount;  // init'd to 0 by linker
index c1dac9f..d5a337f 100644 (file)
@@ -114,9 +114,10 @@ namespace std
     __glibcxx_mutex_lock(__gnu_internal::locale_global_mutex);
     _Impl* __old = _S_global;
     __other._M_impl->_M_add_reference();
-    _S_global = __other._M_impl; 
-    if (__other.name() != "*")
-      setlocale(LC_ALL, __other.name().c_str());
+    _S_global = __other._M_impl;
+    const string __other_name = __other.name();
+    if (__other_name != "*")
+      setlocale(LC_ALL, __other_name.c_str());
    __glibcxx_mutex_unlock(__gnu_internal::locale_global_mutex);
 
     // Reference count sanity check: one reference removed for the
@@ -255,13 +256,12 @@ namespace std
     for (size_t __i = 0; __i < _M_facets_size; ++__i)
       _M_facets[__i] = _M_caches[__i] = 0;
 
-    // Name all the categories.
+    // Name the categories.
     _M_names = new (&name_vec) char*[_S_categories_size];
-    for (size_t __i = 0; __i < _S_categories_size; ++__i)
-      {
-       _M_names[__i] = new (&name_c[__i]) char[2];
-       std::strcpy(_M_names[__i], locale::facet::_S_get_c_name());
-      }
+    _M_names[0] = new (&name_c[0]) char[2];
+    std::memcpy(_M_names[0], locale::facet::_S_get_c_name(), 2);
+    for (size_t __i = 1; __i < _S_categories_size; ++__i)
+      _M_names[__i] = 0;
 
     // This is needed as presently the C++ version of "C" locales
     // != data in the underlying locale model for __timepunct,
index 4cd1af1..ca09b06 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 // Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -34,7 +34,6 @@ namespace std
 {
   using namespace __gnu_cxx;
 
-  
   locale::locale(const char* __s)
   {
     if (__s)
@@ -95,6 +94,7 @@ namespace std
                if (__i < _S_categories_size)
                  {
                    string __str;
+                   __str.reserve(128);
                    for (size_t __j = 0; __j < __i; ++__j)
                      {
                        __str += _S_categories[__j];
@@ -199,15 +199,12 @@ namespace std
        for (size_t __i = 0; __i < _S_categories_size; ++__i)
          _M_names[__i] = 0;
 
-       // Name all the categories.
+       // Name the categories.
        const size_t __len = std::strlen(__s);
        if (!std::strchr(__s, ';'))
          {
-           for (size_t __i = 0; __i < _S_categories_size; ++__i)
-             {
-               _M_names[__i] = new char[__len + 1];
-               std::strcpy(_M_names[__i], __s);
-             }
+           _M_names[0] = new char[__len + 1];
+           std::memcpy(_M_names[0], __s, __len + 1);       
          }
        else
          {
@@ -218,10 +215,9 @@ namespace std
                const char* __end = std::strchr(__beg, ';');
                if (!__end)
                  __end = __s + __len;
-               char* __new = new char[__end - __beg + 1];
-               std::memcpy(__new, __beg, __end - __beg);
-               __new[__end - __beg] = '\0';
-               _M_names[__i] = __new;
+               _M_names[__i] = new char[__end - __beg + 1];
+               std::memcpy(_M_names[__i], __beg, __end - __beg);
+               _M_names[__i][__end - __beg] = '\0';
              }
          }
  
@@ -271,19 +267,35 @@ namespace std
   locale::_Impl::
   _M_replace_categories(const _Impl* __imp, category __cat)
   {
-    for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
+    category __mask = 1;
+    const bool __have_names = _M_names[0] && __imp->_M_names[0];
+    for (size_t __ix = 0; __ix < _S_categories_size; ++__ix, __mask <<= 1)
       {
-       const category __mask = 1 << __ix;
        if (__mask & __cat)
          {
            // Need to replace entry in _M_facets with other locale's info.
            _M_replace_category(__imp, _S_facet_categories[__ix]);
            // If both have names, go ahead and mangle.
-           if (std::strcmp(_M_names[__ix], "*") != 0 
-               && std::strcmp(__imp->_M_names[__ix], "*") != 0)
+           if (__have_names)
              {
-               char* __new = new char[std::strlen(__imp->_M_names[__ix]) + 1];
-               std::strcpy(__new, __imp->_M_names[__ix]);
+               if (!_M_names[1])
+                 {
+                   // A full set of _M_names must be prepared, all identical
+                   // to _M_names[0] to begin with. Then, below, a few will
+                   // be replaced by the corresponding __imp->_M_names. I.e.,
+                   // not a "simple" locale anymore (see locale::operator==).
+                   const size_t __len = std::strlen(_M_names[0]) + 1;
+                   for (size_t __i = 1; __i < _S_categories_size; ++__i)
+                     {
+                       _M_names[__i] = new char[__len];
+                       std::memcpy(_M_names[__i], _M_names[0], __len);
+                     }
+                 }
+               char* __src = __imp->_M_names[__ix] ? __imp->_M_names[__ix]
+                                                   : __imp->_M_names[0];
+               const size_t __len = std::strlen(__src) + 1;
+               char* __new = new char[__len];
+               std::memcpy(__new, __src, __len);
                delete [] _M_names[__ix];
                _M_names[__ix] = __new;
              }