This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ 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: [v3] Speed up <char> do_narrow/widen


Paolo Carlini writes:
 > Jerry Quinn wrote:
 > 
 > >Along the lines of the recent patch to improve performance for
 > >ctype<wchar_t>::do_narrow/widen, this patch improves performance for
 > >ctype<char>.
 > >  
 > >
 > Very good work. Thanks! Do you have some numbers at hand?

These are user times:

		Before		After

narrow		7.180s		3.610s
narrow array	6.330s		5.610s
widen		7.110s		4.150s
widen array	6.240s		5.610s

The array forms aren't hugely faster but they are noticable.

Here's the patch with the updates:

2003-12-12  Jerry Quinn  <jlquinn@optonline.net>

        * config/os/aix/ctype_noninline.h,
	config/os/bsd/freebsd/ctype_noninline.h,
	config/os/bsd/netbsd/ctype_noninline.h,
	config/os/djgpp/ctype_noninline.h,
	config/os/generic/ctype_noninline.h,
	config/os/gnu-linux/ctype_noninline.h,
	config/os/hpux/ctype_noninline.h,
	config/os/irix/irix5.2/ctype_noninline.h,
	config/os/irix/irix6.5/ctype_noninline.h,
	config/os/mingw32/ctype_noninline.h,
	config/os/newlib/ctype_noninline.h,
	config/os/qnx/qnx6.1/ctype_noninline.h,
	config/os/solaris/solaris2.5/ctype_noninline.h,
	config/os/solaris/solaris2.6/ctype_noninline.h,
	config/os/solaris/solaris2.7/ctype_noninline.h,
	config/os/vxworks/ctype_noninline.h,
	config/os/windiss/ctype_noninline.h (ctype):  Initialize
	_M_narrow, _M_widen.
	* include/bits/locale_facets.h (_M_widen, _M_widen_ok,
	_M_narrow, _M_narrow_ok): New.
	(widen, narrow): Use tables to bypass virtual functions.
	(_M_widen_init, _M_narrow_init): New.

--- testsuite/performance/narrow_widen_char.cc.old	1969-12-31 19:00:00.000000000 -0500
+++ testsuite/performance/narrow_widen_char.cc	2003-12-12 22:16:45.000000000 -0500
@@ -0,0 +1,75 @@
+// Copyright (C) 2003 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 <locale>
+#include <testsuite_performance.h>
+
+int main()
+{
+  using namespace std;
+  using namespace __gnu_test;
+
+  time_counter time;
+  resource_counter resource;
+  char bufin[] = "This was an attempt to bypass string construction just for test.";
+  char bufout[sizeof(bufin) + 1];
+
+  locale loc;
+  const ctype<char>& ct = use_facet<ctype<char> >(loc);
+
+  // narrow
+  start_counters(time, resource);
+  for (long i = 0; i < 1000000000; ++i)
+    ct.narrow(i % 128, '*');
+  stop_counters(time, resource);
+  report_performance(__FILE__, "narrow", time, resource);
+  clear_counters(time, resource);
+
+  // narrow array
+  start_counters(time, resource);
+  for (long i = 0; i < 100000000; ++i)
+    ct.narrow(bufin, bufin+sizeof(bufin), '*', bufout);
+  stop_counters(time, resource);
+  report_performance(__FILE__, "narrow_array", time, resource);
+  clear_counters(time, resource);
+
+  // widen
+  start_counters(time, resource);
+  for (long i = 0; i < 1000000000; ++i)
+    ct.widen(i % 128);
+  stop_counters(time, resource);
+  report_performance(__FILE__, "widen", time, resource);
+
+  // widen array
+  start_counters(time, resource);
+  for (long i = 0; i < 100000000; ++i)
+    ct.widen(bufin, bufin+sizeof(bufin), bufout);
+  stop_counters(time, resource);
+  report_performance(__FILE__, "widen_array", time, resource);
+
+  return 0;
+}
? src/floatconv.cc
? testsuite/performance/narrow_widen_char.cc
Index: config/os/aix/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/aix/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/aix/ctype_noninline.h	21 Oct 2003 14:22:37 -0000	1.2
+++ config/os/aix/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -42,13 +42,23 @@
   : facet(__refs), _M_del(__table != 0 && __del),
   _M_toupper(NULL), _M_tolower(NULL),
   _M_table(__table ? __table : classic_table())
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
   : facet(__refs), _M_del(__table != 0 && __del),
   _M_toupper(NULL), _M_tolower(NULL),
   _M_table(__table ? __table : classic_table())
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/bsd/freebsd/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/bsd/freebsd/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/bsd/freebsd/ctype_noninline.h	21 Oct 2003 14:22:37 -0000	1.2
+++ config/os/bsd/freebsd/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -42,13 +42,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/bsd/netbsd/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/bsd/netbsd/ctype_noninline.h,v
retrieving revision 1.3
diff -u -w -r1.3 ctype_noninline.h
--- config/os/bsd/netbsd/ctype_noninline.h	21 Oct 2003 14:22:38 -0000	1.3
+++ config/os/bsd/netbsd/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -44,13 +44,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table())
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table())
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/djgpp/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/djgpp/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/djgpp/ctype_noninline.h	21 Oct 2003 14:22:38 -0000	1.2
+++ config/os/djgpp/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -42,13 +42,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(__dj_ctype_toupper), _M_tolower(__dj_ctype_tolower),
   _M_table(__table ? __table : __dj_ctype_flags)  
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(__dj_ctype_toupper), _M_tolower(__dj_ctype_tolower),
   _M_table(__table ? __table : __dj_ctype_flags)  
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/generic/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/generic/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/generic/ctype_noninline.h	21 Oct 2003 14:22:38 -0000	1.2
+++ config/os/generic/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -43,13 +43,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table())
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/gnu-linux/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/gnu-linux/ctype_noninline.h,v
retrieving revision 1.6
diff -u -w -r1.6 ctype_noninline.h
--- config/os/gnu-linux/ctype_noninline.h	21 Oct 2003 14:22:38 -0000	1.6
+++ config/os/gnu-linux/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -65,6 +65,10 @@
     _M_toupper = _M_c_locale_ctype->__ctype_toupper;
     _M_tolower = _M_c_locale_ctype->__ctype_tolower;
     _M_table = __table ? __table : _M_c_locale_ctype->__ctype_b;
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
   }
 #else
   ctype<char>::ctype(__c_locale, const mask* __table, bool __del, 
@@ -85,6 +89,10 @@
     setlocale(LC_CTYPE, __old);
     free(__old);
     _M_c_locale_ctype = _S_get_c_locale();
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
   }
 #endif
 
@@ -96,6 +104,10 @@
     _M_toupper = _M_c_locale_ctype->__ctype_toupper;
     _M_tolower = _M_c_locale_ctype->__ctype_tolower;
     _M_table = __table ? __table : _M_c_locale_ctype->__ctype_b;
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
   }
 #else
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
@@ -115,6 +127,10 @@
     setlocale(LC_CTYPE, __old);
     free(__old);
     _M_c_locale_ctype = _S_get_c_locale();
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
   }
 #endif
 
Index: config/os/hpux/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/hpux/ctype_noninline.h,v
retrieving revision 1.3
diff -u -w -r1.3 ctype_noninline.h
--- config/os/hpux/ctype_noninline.h	21 Oct 2003 14:22:39 -0000	1.3
+++ config/os/hpux/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -43,13 +43,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : (const mask *) __SB_masks) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : (const mask *) __SB_masks) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/irix/irix5.2/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/irix/irix5.2/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/irix/irix5.2/ctype_noninline.h	21 Oct 2003 14:22:39 -0000	1.2
+++ config/os/irix/irix5.2/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -43,13 +43,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(!__table ? classic_table() : __table)
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(!__table ? classic_table() : __table)
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/irix/irix6.5/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/irix/irix6.5/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/irix/irix6.5/ctype_noninline.h	21 Oct 2003 14:22:40 -0000	1.2
+++ config/os/irix/irix6.5/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -43,14 +43,24 @@
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(!__table ? 
 	   (const mask*) (__libc_attr._ctype_tbl->_class + 1) : __table) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(!__table ? 
 	   (const mask*) (__libc_attr._ctype_tbl->_class + 1) : __table) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/mingw32/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/mingw32/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/mingw32/ctype_noninline.h	21 Oct 2003 14:22:40 -0000	1.2
+++ config/os/mingw32/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -46,13 +46,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL),
   _M_table(__table ? __table : classic_table())  
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL),
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/newlib/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/newlib/ctype_noninline.h,v
retrieving revision 1.3
diff -u -w -r1.3 ctype_noninline.h
--- config/os/newlib/ctype_noninline.h	21 Oct 2003 14:22:40 -0000	1.3
+++ config/os/newlib/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -42,13 +42,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/qnx/qnx6.1/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/qnx/qnx6.1/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/qnx/qnx6.1/ctype_noninline.h	21 Oct 2003 14:22:40 -0000	1.2
+++ config/os/qnx/qnx6.1/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -41,12 +41,22 @@
 		     size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), _M_table(__table ? __table : _Ctype)
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), _M_table(__table ? __table : _Ctype)
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/solaris/solaris2.5/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/solaris/solaris2.5/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/solaris/solaris2.5/ctype_noninline.h	21 Oct 2003 14:22:41 -0000	1.2
+++ config/os/solaris/solaris2.5/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -42,13 +42,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/solaris/solaris2.6/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/solaris/solaris2.6/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/solaris/solaris2.6/ctype_noninline.h	21 Oct 2003 14:22:41 -0000	1.2
+++ config/os/solaris/solaris2.6/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -42,13 +42,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(__trans_upper), _M_tolower(__trans_lower), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(__trans_upper), _M_tolower(__trans_lower), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/solaris/solaris2.7/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/solaris/solaris2.7/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/solaris/solaris2.7/ctype_noninline.h	21 Oct 2003 14:22:41 -0000	1.2
+++ config/os/solaris/solaris2.7/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -43,13 +43,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(__trans_upper), _M_tolower(__trans_lower),
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(__trans_upper), _M_tolower(__trans_lower),
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/vxworks/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/vxworks/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/vxworks/ctype_noninline.h	23 Oct 2003 05:33:49 -0000	1.2
+++ config/os/vxworks/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -42,13 +42,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table()) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table ? __table : classic_table())
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: config/os/windiss/ctype_noninline.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/windiss/ctype_noninline.h,v
retrieving revision 1.2
diff -u -w -r1.2 ctype_noninline.h
--- config/os/windiss/ctype_noninline.h	21 Oct 2003 14:22:42 -0000	1.2
+++ config/os/windiss/ctype_noninline.h	13 Dec 2003 04:42:41 -0000
@@ -43,13 +43,23 @@
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table == 0 ? classic_table() : __table) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) 
   : facet(__refs), _M_del(__table != 0 && __del), 
   _M_toupper(NULL), _M_tolower(NULL), 
   _M_table(__table == 0 ? classic_table() : __table) 
-  { }
+  { 
+    memset(_M_widen, 0, sizeof(_M_widen));
+    _M_widen_ok = 0;
+    memset(_M_narrow, 0, sizeof(_M_narrow));
+    _M_narrow_ok = 0;
+  }
 
   char
   ctype<char>::do_toupper(char __c) const
Index: include/bits/locale_facets.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_facets.h,v
retrieving revision 1.74
diff -u -w -r1.74 locale_facets.h
--- include/bits/locale_facets.h	12 Dec 2003 19:44:15 -0000	1.74
+++ include/bits/locale_facets.h	13 Dec 2003 04:42:42 -0000
@@ -325,6 +325,11 @@
       __to_type 	       	_M_toupper;
       __to_type  	       	_M_tolower;
       const mask*              	_M_table;
+      mutable char		_M_widen_ok;
+      mutable char		_M_widen[1 + static_cast<unsigned char>(-1)];
+      mutable char		_M_narrow[1 + static_cast<unsigned char>(-1)];
+      mutable char		_M_narrow_ok;	// 0 uninitialized, 1 init,
+						// 2 non-consecutive
       
     public:
       static locale::id        id;
@@ -367,20 +372,46 @@
 
       char_type 
       widen(char __c) const
-      { return this->do_widen(__c); }
+      { 
+	if (_M_widen_ok) return _M_widen[__c];
+	this->_M_widen_init();
+	return this->do_widen(__c);
+      }
 
       const char*
       widen(const char* __lo, const char* __hi, char_type* __to) const
-      { return this->do_widen(__lo, __hi, __to); }
+      {
+	if (_M_widen_ok == 1)
+	  {
+	    memcpy(__to, __lo, __hi - __lo);
+	    return __hi;
+	  }
+	if (!_M_widen_ok) _M_widen_init();
+	return this->do_widen(__lo, __hi, __to);
+      }
 
       char 
       narrow(char_type __c, char __dfault) const
-      { return this->do_narrow(__c, __dfault); }
+      {
+	if (_M_narrow[__c]) return _M_narrow[__c];
+	char __t = do_narrow(__c, __dfault);
+	if (__t != __dfault) _M_narrow[__c] = __t;
+	return __t;
+      }
 
       const char_type*
       narrow(const char_type* __lo, const char_type* __hi,
 	      char __dfault, char *__to) const
-      { return this->do_narrow(__lo, __hi, __dfault, __to); }
+      {
+	if (__builtin_expect(_M_narrow_ok==1,true))
+	  {
+	    memcpy(__to, __lo, __hi - __lo);
+	    return __hi;
+	  }
+	if (!_M_narrow_ok)
+	  _M_narrow_init();
+	return this->do_narrow(__lo, __hi, __dfault, __to);
+      }
 
     protected:
       const mask* 
@@ -426,6 +457,54 @@
       {
 	memcpy(__dest, __lo, __hi - __lo);
 	return __hi;
+      }
+
+    private:
+
+      void _M_widen_init() const
+      {
+	char __tmp[sizeof(_M_widen)];
+	for (size_t __i = 0; __i < sizeof(_M_widen); ++__i)
+	  __tmp[__i] = __i;
+	do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen);
+	    
+	_M_widen_ok = 1;
+	// Set _M_widen_ok to 2 if memcpy can't be used.
+	for (size_t __i = 0; __i < sizeof(_M_widen); ++__i)
+	  if (__tmp[__i] != _M_widen[__i])
+	    {
+	      _M_widen_ok = 2;
+	      break;
+	    }
+      }
+
+      // Fill in the narrowing cache and flag whether all values are
+      // valid or not.  _M_narrow_ok is set to 1 if the whole table is
+      // narrowed, 2 if only some values could be narrowed.
+      void _M_narrow_init() const
+      {
+	char __tmp[sizeof(_M_narrow)];
+	for (size_t __i = 0; __i < sizeof(_M_narrow); ++__i)
+	  __tmp[__i] = __i;
+	do_narrow(__tmp, __tmp + sizeof(__tmp), 0, _M_narrow);
+
+	// Check if any default values were created.  Do this by
+	// renarrowing with a different default value and comparing.
+	bool __consecutive = true;
+	for (size_t __i = 0; __i < sizeof(_M_narrow); ++__i)
+	  {
+	    char __c[1];
+	    if (!_M_narrow[__i])
+	      {
+		do_narrow(__tmp + __i, __tmp + __i + 1, 1, __c);
+		if (__c[0] == 1)
+		  {
+		    __consecutive = false;
+		    break;
+		  }
+	      }
+	  }
+	_M_narrow_ok = __consecutive ? 1 : 2;
       }
     };
  


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