diff --git a/libjava/ChangeLog b/libjava/ChangeLog index d78dc4884544b4b1cdcc50fb32dcd8bc324480b8..fd0bd3fd64f770cd67520058f6da41b7007b8fb6 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,17 @@ +2005-09-27 Tom Tromey <tromey@redhat.com> + + PR libgcj/23367: + * include/jvm.h (_Jv_FreeMethodCache): Declare. + * java/lang/natClass.cc (MCACHE_SIZE): Conditional on HAVE_TLS. + (struct _Jv_mcache): Likewise. + (method_cache): Likewise. + (_Jv_FindMethodInCache): Do nothing unless TLS is available. + (_Jv_AddMethodToCache): Likewise. + (_Jv_FreeMethodCache): New function. + * java/lang/natThread.cc (finish_): Call _Jv_FreeMethodCache. + * aclocal.m4, configure, include/config.h.in: Rebuilt. + * configure.ac: Invoke GCC_CHECK_TLS. + 2005-09-27 Tom Tromey <tromey@redhat.com> * configure, Makefile.in: Rebuilt. diff --git a/libjava/Makefile.in b/libjava/Makefile.in index 3a0a45b2f3bb097dfb6ea1e5cfe68d6b96c0ab53..9218b5358f340f4f0554095bf2046cdae3308b8a 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -74,6 +74,7 @@ subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ + $(top_srcdir)/../config/enable.m4 \ $(top_srcdir)/../config/gxx-include-dir.m4 \ $(top_srcdir)/../config/iconv.m4 \ $(top_srcdir)/../config/lcmessage.m4 \ @@ -82,9 +83,9 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/lib-link.m4 \ $(top_srcdir)/../config/lib-prefix.m4 \ $(top_srcdir)/../config/no-executables.m4 \ - $(top_srcdir)/../libtool.m4 $(top_srcdir)/mingwld.m4 \ - $(top_srcdir)/pkg.m4 $(top_srcdir)/shlibpath.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../libtool.m4 \ + $(top_srcdir)/mingwld.m4 $(top_srcdir)/pkg.m4 \ + $(top_srcdir)/shlibpath.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ diff --git a/libjava/aclocal.m4 b/libjava/aclocal.m4 index 2f5e00b0e5b6cbecc18f42ec85fe5cdbf3b8ac83..02f34e6d2acd2ab7e971407971ca4f6575fc31c4 100644 --- a/libjava/aclocal.m4 +++ b/libjava/aclocal.m4 @@ -1097,6 +1097,7 @@ AC_SUBST([am__untar]) m4_include([../config/acx.m4]) m4_include([../config/depstand.m4]) +m4_include([../config/enable.m4]) m4_include([../config/gxx-include-dir.m4]) m4_include([../config/iconv.m4]) m4_include([../config/lcmessage.m4]) @@ -1105,6 +1106,7 @@ m4_include([../config/lib-ld.m4]) m4_include([../config/lib-link.m4]) m4_include([../config/lib-prefix.m4]) m4_include([../config/no-executables.m4]) +m4_include([../config/tls.m4]) m4_include([../libtool.m4]) m4_include([mingwld.m4]) m4_include([pkg.m4]) diff --git a/libjava/configure b/libjava/configure index 995160f1066ac4f3361b074c12e654ecb3b76391..8b3a80b23bceba46e9132804478c6ff27e3df772 100755 --- a/libjava/configure +++ b/libjava/configure @@ -876,6 +876,8 @@ Optional Features: --enable-gtk-cairo build the cairo Graphics2D implementation on GTK --enable-java-gc=TYPE choose garbage collector (default is boehm) --disable-rpath do not hardcode runtime library paths + _g_switchUse thread-local storage + [default=yes] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -5584,7 +5586,7 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic" case $host in *-*-irix6*) # Find out which ABI we are using. - echo '#line 5587 "configure"' > conftest.$ac_ext + echo '#line 5589 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6587,7 +6589,7 @@ if test "${enable_sjlj_exceptions+set}" = set; then : else cat > conftest.$ac_ext << EOF -#line 6590 "configure" +#line 6592 "configure" struct S { ~S(); }; void bar(); void foo() @@ -16740,6 +16742,134 @@ else multilib_arg= fi +# See if we support thread-local storage. + + # Check whether --enable-tls or --disable-tls was given. +if test "${enable_tls+set}" = set; then + enableval="$enable_tls" + + case "$enableval" in + yes|no) ;; + *) { { echo "$as_me:$LINENO: error: Argument to enable/disable tls must be yes or no" >&5 +echo "$as_me: error: Argument to enable/disable tls must be yes or no" >&2;} + { (exit 1); exit 1; }; } ;; + esac + +else + enable_tls=yes +fi; + + echo "$as_me:$LINENO: checking whether the target supports thread-local storage" >&5 +echo $ECHO_N "checking whether the target supports thread-local storage... $ECHO_C" >&6 +if test "${have_tls+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + cat >conftest.$ac_ext <<_ACEOF +__thread int foo; +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + have_tls=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +have_tls=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +else + cat >conftest.$ac_ext <<_ACEOF +__thread int a; int b; int main() { return a = b; } +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + save_LDFLAGS="$LDFLAGS" + LDFLAGS="-static $LDFLAGS" + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +__thread int a; int b; int main() { return a = b; } +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + have_tls=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +have_tls=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + LDFLAGS="$save_LDFLAGS" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +have_tls=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $have_tls" >&5 +echo "${ECHO_T}$have_tls" >&6 + if test "$enable_tls $have_tls" = "yes yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TLS 1 +_ACEOF + + fi here=`${PWDCMD-pwd}` diff --git a/libjava/configure.ac b/libjava/configure.ac index 2517ac84a8237696b2e4e526ab55c0b7e49dd182..fbd2a3d15e7c4fdeb51c4ec4a02989ae7668d768 100644 --- a/libjava/configure.ac +++ b/libjava/configure.ac @@ -1439,6 +1439,8 @@ else multilib_arg= fi +# See if we support thread-local storage. +GCC_CHECK_TLS here=`${PWDCMD-pwd}` diff --git a/libjava/gcj/Makefile.in b/libjava/gcj/Makefile.in index 0070b2e81a51bf2dd3d3d50c812ece85878fb516..5f0efcef1a52d886956210fecbf187d69d6d443e 100644 --- a/libjava/gcj/Makefile.in +++ b/libjava/gcj/Makefile.in @@ -44,6 +44,7 @@ DIST_COMMON = $(gcj_HEADERS) $(srcdir)/Makefile.am \ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ + $(top_srcdir)/../config/enable.m4 \ $(top_srcdir)/../config/gxx-include-dir.m4 \ $(top_srcdir)/../config/iconv.m4 \ $(top_srcdir)/../config/lcmessage.m4 \ @@ -52,9 +53,9 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/lib-link.m4 \ $(top_srcdir)/../config/lib-prefix.m4 \ $(top_srcdir)/../config/no-executables.m4 \ - $(top_srcdir)/../libtool.m4 $(top_srcdir)/mingwld.m4 \ - $(top_srcdir)/pkg.m4 $(top_srcdir)/shlibpath.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../libtool.m4 \ + $(top_srcdir)/mingwld.m4 $(top_srcdir)/pkg.m4 \ + $(top_srcdir)/shlibpath.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) CONFIG_HEADER = $(top_builddir)/include/config.h libgcj-config.h diff --git a/libjava/include/Makefile.in b/libjava/include/Makefile.in index aa4da5259e2d5d47cd7991d41433283e3c52096c..77775a1372b9204dd61ca2252ef08a502967aaba 100644 --- a/libjava/include/Makefile.in +++ b/libjava/include/Makefile.in @@ -43,6 +43,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ + $(top_srcdir)/../config/enable.m4 \ $(top_srcdir)/../config/gxx-include-dir.m4 \ $(top_srcdir)/../config/iconv.m4 \ $(top_srcdir)/../config/lcmessage.m4 \ @@ -51,9 +52,9 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/lib-link.m4 \ $(top_srcdir)/../config/lib-prefix.m4 \ $(top_srcdir)/../config/no-executables.m4 \ - $(top_srcdir)/../libtool.m4 $(top_srcdir)/mingwld.m4 \ - $(top_srcdir)/pkg.m4 $(top_srcdir)/shlibpath.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../libtool.m4 \ + $(top_srcdir)/mingwld.m4 $(top_srcdir)/pkg.m4 \ + $(top_srcdir)/shlibpath.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) CONFIG_HEADER = config.h $(top_builddir)/gcj/libgcj-config.h diff --git a/libjava/include/config.h.in b/libjava/include/config.h.in index ffb3d3fc886dc4437cd8a1a2916e10674790f469..990b88562fb068235c84d4e6d7380e1c59969989 100644 --- a/libjava/include/config.h.in +++ b/libjava/include/config.h.in @@ -319,6 +319,9 @@ /* Define if global 'timezone' exists. */ #undef HAVE_TIMEZONE +/* Define to 1 if the target supports thread-local storage. */ +#undef HAVE_TLS + /* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use `HAVE_STRUCT_TM_TM_ZONE' instead. */ #undef HAVE_TM_ZONE diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index 459d4594278c9db37f61246da8aa7eae71522da2..6061300a74ddc77d9dcef6d6c2dbc33d95fb87d1 100644 --- a/libjava/include/jvm.h +++ b/libjava/include/jvm.h @@ -359,6 +359,10 @@ void _Jv_SetInitialHeapSize (const char *arg); _Jv_GCSetMaximumHeapSize. */ void _Jv_SetMaximumHeapSize (const char *arg); +/* Free the method cache, if one was allocated. This is only called + during thread deregistration. */ +void _Jv_FreeMethodCache (); + extern "C" void JvRunMain (jclass klass, int argc, const char **argv); void _Jv_RunMain (jclass klass, const char *name, int argc, const char **argv, bool is_jar); diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index fa52713cc36bd399087c3e469830aa5bdd33d612..bd68eb224358375ad40687b9125770126ce2857b 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -879,8 +879,10 @@ _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name, return NULL; } +#ifdef HAVE_TLS + // NOTE: MCACHE_SIZE should be a power of 2 minus one. -#define MCACHE_SIZE 1023 +#define MCACHE_SIZE 31 struct _Jv_mcache { @@ -888,37 +890,60 @@ struct _Jv_mcache _Jv_Method *method; }; -static _Jv_mcache method_cache[MCACHE_SIZE + 1]; +static __thread _Jv_mcache *method_cache; +#endif // HAVE_TLS static void * _Jv_FindMethodInCache (jclass klass, _Jv_Utf8Const *name, _Jv_Utf8Const *signature) { - int index = name->hash16 () & MCACHE_SIZE; - _Jv_mcache *mc = method_cache + index; - _Jv_Method *m = mc->method; - - if (mc->klass == klass - && m != NULL // thread safe check - && _Jv_equalUtf8Consts (m->name, name) - && _Jv_equalUtf8Consts (m->signature, signature)) - return mc->method->ncode; +#ifdef HAVE_TLS + _Jv_mcache *cache = method_cache; + if (cache) + { + int index = name->hash16 () & MCACHE_SIZE; + _Jv_mcache *mc = &cache[index]; + _Jv_Method *m = mc->method; + + if (mc->klass == klass + && _Jv_equalUtf8Consts (m->name, name) + && _Jv_equalUtf8Consts (m->signature, signature)) + return mc->method->ncode; + } +#endif // HAVE_TLS return NULL; } static void -_Jv_AddMethodToCache (jclass klass, - _Jv_Method *method) +_Jv_AddMethodToCache (jclass klass, _Jv_Method *method) { - _Jv_MonitorEnter (&java::lang::Class::class$); - - int index = method->name->hash16 () & MCACHE_SIZE; - - method_cache[index].method = method; - method_cache[index].klass = klass; +#ifdef HAVE_TLS + if (method_cache == NULL) + method_cache = (_Jv_mcache *) _Jv_MallocUnchecked((MCACHE_SIZE + 1) + * sizeof (_Jv_mcache)); + // If the allocation failed, just keep going. + if (method_cache != NULL) + { + int index = method->name->hash16 () & MCACHE_SIZE; + method_cache[index].method = method; + method_cache[index].klass = klass; + } +#endif // HAVE_TLS +} - _Jv_MonitorExit (&java::lang::Class::class$); +// Free this thread's method cache. We explicitly manage this memory +// as the GC does not yet know how to scan TLS on all platforms. +void +_Jv_FreeMethodCache () +{ +#ifdef HAVE_TLS + if (method_cache != NULL) + { + _Jv_Free(method_cache); + method_cache = NULL; + } +#endif // HAVE_TLS } void * diff --git a/libjava/java/lang/natThread.cc b/libjava/java/lang/natThread.cc index f1064f17c690cab3f50b780e7e5b7b569c16699d..80cdae324ff90472279911339b3f6d67e49e08d0 100644 --- a/libjava/java/lang/natThread.cc +++ b/libjava/java/lang/natThread.cc @@ -214,7 +214,10 @@ java::lang::Thread::finish_ () #endif group = NULL; - + + // If a method cache was created, free it. + _Jv_FreeMethodCache(); + // Signal any threads that are waiting to join() us. _Jv_MutexLock (&nt->join_mutex); diff --git a/libjava/testsuite/Makefile.in b/libjava/testsuite/Makefile.in index a9f205bb59859e8b98364b246f2d4dc6dcde5a83..270c23d828c1089f00bc04430f401e736d0e81c1 100644 --- a/libjava/testsuite/Makefile.in +++ b/libjava/testsuite/Makefile.in @@ -41,6 +41,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ + $(top_srcdir)/../config/enable.m4 \ $(top_srcdir)/../config/gxx-include-dir.m4 \ $(top_srcdir)/../config/iconv.m4 \ $(top_srcdir)/../config/lcmessage.m4 \ @@ -49,9 +50,9 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/lib-link.m4 \ $(top_srcdir)/../config/lib-prefix.m4 \ $(top_srcdir)/../config/no-executables.m4 \ - $(top_srcdir)/../libtool.m4 $(top_srcdir)/mingwld.m4 \ - $(top_srcdir)/pkg.m4 $(top_srcdir)/shlibpath.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../libtool.m4 \ + $(top_srcdir)/mingwld.m4 $(top_srcdir)/pkg.m4 \ + $(top_srcdir)/shlibpath.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) CONFIG_HEADER = $(top_builddir)/include/config.h \