[v3] Speed up <char> do_narrow/widen

Jerry Quinn jlquinn@optonline.net
Sat Dec 13 04:58:00 GMT 2003


Along the lines of the recent patch to improve performance for
ctype<wchar_t>::do_narrow/widen, this patch improves performance for
ctype<char>.

Passes with no regressions on i686-pc-gnu-linux.

Jerry Quinn


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.


? 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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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:22:11 -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.72
diff -u -w -r1.72 locale_facets.h
--- include/bits/locale_facets.h	26 Nov 2003 11:47:01 -0000	1.72
+++ include/bits/locale_facets.h	13 Dec 2003 04:22:12 -0000
@@ -347,6 +347,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;
@@ -389,20 +394,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* 
@@ -448,6 +479,54 @@
       {
 	memcpy(__dest, __lo, __hi - __lo);
 	return __hi;
+      }
+
+    private:
+
+      void _M_widen_init() const
+      {
+	char __tmp[sizeof(_M_widen)];
+	for (unsigned __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 (unsigned __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 (unsigned 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 (unsigned __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;
       }
     };
  
--- 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;
+}



More information about the Libstdc++ mailing list