This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java 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]

Patch: FYI: fix PR libgcj/23367


I'm checking this in on the trunk.  I updated the 4.0 tracking PR to
reflect this patch as well.

This fixes PR 23367.  The problem was that our interface method cache
(used by the interpreter) was not properly thread safe.  This patch
makes the cache thread-local on systems that support this, and simply
removes the cache on systems which do not.

Tom

Index: ChangeLog
from  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.

Index: configure.ac
===================================================================
RCS file: /cvs/gcc/gcc/libjava/configure.ac,v
retrieving revision 1.41
diff -u -r1.41 configure.ac
--- configure.ac 27 Sep 2005 18:51:34 -0000 1.41
+++ configure.ac 27 Sep 2005 19:13:03 -0000
@@ -1439,6 +1439,8 @@
   multilib_arg=
 fi
 
+# See if we support thread-local storage.
+GCC_CHECK_TLS
 
 
 here=`${PWDCMD-pwd}`
Index: include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.89
diff -u -r1.89 jvm.h
--- include/jvm.h 17 Aug 2005 20:44:08 -0000 1.89
+++ include/jvm.h 27 Sep 2005 19:13:03 -0000
@@ -359,6 +359,10 @@
    _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);
Index: java/lang/natClass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClass.cc,v
retrieving revision 1.90
diff -u -r1.90 natClass.cc
--- java/lang/natClass.cc 6 Sep 2005 16:01:28 -0000 1.90
+++ java/lang/natClass.cc 27 Sep 2005 19:13:03 -0000
@@ -879,8 +879,10 @@
   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 @@
   _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 *
Index: java/lang/natThread.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natThread.cc,v
retrieving revision 1.31
diff -u -r1.31 natThread.cc
--- java/lang/natThread.cc 29 Jun 2005 17:36:16 -0000 1.31
+++ java/lang/natThread.cc 27 Sep 2005 19:13:04 -0000
@@ -214,7 +214,10 @@
 #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);
 


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