OSDN Git Service

* gcse.c (gcse_main): Do jump bypassing in CPROP2.
[pf3gnuchains/gcc-fork.git] / libjava / boehm.cc
index fc75bdb..3aa0acb 100644 (file)
@@ -1,6 +1,6 @@
 // boehm.cc - interface between libjava and Boehm GC.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation
 
    This file is part of libgcj.
@@ -26,6 +26,18 @@ details.  */
 #undef TRUE
 #undef FALSE
 
+// We include two autoconf headers. Avoid multiple definition warnings.
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+
+#ifdef HAVE_DLFCN_H
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#endif
+
 extern "C"
 {
 #include <gc_config.h>
@@ -58,6 +70,8 @@ static int array_kind_x;
 // Freelist used for Java arrays.
 static void **array_free_list;
 
+static int _Jv_GC_has_static_roots (const char *filename, void *, size_t);
+
 \f
 
 // This is called by the GC during the mark phase.  It marks a Java
@@ -93,9 +107,6 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void *env)
     p = (GC_PTR) obj->sync_info;
     MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj);
 # endif
-  // Mark the object's class.
-  p = (GC_PTR) klass;
-  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj);
 
   if (__builtin_expect (klass == &java::lang::Class::class$, false))
     {
@@ -156,6 +167,14 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void *env)
       MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       p = (GC_PTR) c->aux_info;
       MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
+
+      p = (GC_PTR) c->reflection_data;
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
+
+      // The class chain must be marked for runtime-allocated Classes
+      // loaded by the bootstrap ClassLoader.
+      p = (GC_PTR) c->next_or_version;
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
     }
   else
     {
@@ -208,7 +227,6 @@ _Jv_MarkArray (void *addr, void *msp, void *msl, void *env)
   // we may need to round up the size.
   if (__builtin_expect (! dt || !(dt -> get_finalizer()), false))
     return mark_stack_ptr;
-  jclass klass = dt->clas;
   GC_PTR p;
 
   p = (GC_PTR) dt;
@@ -219,9 +237,6 @@ _Jv_MarkArray (void *addr, void *msp, void *msl, void *env)
     p = (GC_PTR) array->sync_info;
     MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array);
 # endif
-  // Mark the object's class.
-  p = (GC_PTR) klass;
-  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, &(dt -> clas));
 
   for (int i = 0; i < JvGetArrayLength (array); ++i)
     {
@@ -365,6 +380,29 @@ _Jv_AllocRawObj (jsize size)
   return (void *) GC_MALLOC (size ? size : 1);
 }
 
+typedef _Jv_ClosureList *closure_list_pointer;
+
+/* Release closures in a _Jv_ClosureList.  */
+static void
+finalize_closure_list (GC_PTR obj, GC_PTR)
+{
+  _Jv_ClosureList **clpp = (_Jv_ClosureList **)obj;
+  _Jv_ClosureList::releaseClosures (clpp);
+}
+
+/* Allocate a double-indirect pointer to a _Jv_ClosureList that will
+   get garbage-collected after this double-indirect pointer becomes
+   unreachable by any other objects, including finalizable ones.  */
+_Jv_ClosureList **
+_Jv_ClosureListFinalizer ()
+{
+  _Jv_ClosureList **clpp;
+  clpp = (_Jv_ClosureList **)_Jv_AllocBytes (sizeof (*clpp));
+  GC_REGISTER_FINALIZER_UNREACHABLE (clpp, finalize_closure_list,
+                                    NULL, NULL, NULL);
+  return clpp;
+}
+
 static void
 call_finalizer (GC_PTR obj, GC_PTR client_data)
 {
@@ -469,10 +507,21 @@ void
 _Jv_InitGC (void)
 {
   int proc;
+  static bool gc_initialized;
+
+  if (gc_initialized)
+    return;
+
+  gc_initialized = 1;
 
   // Ignore pointers that do not point to the start of an object.
   GC_all_interior_pointers = 0;
 
+#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
+  // Tell the collector to ask us before scanning DSOs.
+  GC_register_has_static_roots_callback (_Jv_GC_has_static_roots);
+#endif
+
   // Configure the collector to use the bitmap marking descriptors that we
   // stash in the class vtable.
   // We always use mark proc descriptor 0, since the compiler knows
@@ -560,3 +609,145 @@ _Jv_GCCanReclaimSoftReference (jobject)
   // For now, always reclaim soft references.  FIXME.
   return true;
 }
+
+\f
+
+#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
+
+// We keep a store of the filenames of DSOs that need to be
+// conservatively scanned by the garbage collector.  During collection
+// the gc calls _Jv_GC_has_static_roots() to see if the data segment
+// of a DSO should be scanned.
+typedef struct filename_node
+{
+  char *name;
+  struct filename_node *link;
+} filename_node;
+
+#define FILENAME_STORE_SIZE 17
+static filename_node *filename_store[FILENAME_STORE_SIZE];
+
+// Find a filename in filename_store.
+static filename_node **
+find_file (const char *filename)
+{
+  int index = strlen (filename) % FILENAME_STORE_SIZE;
+  filename_node **node = &filename_store[index];
+  
+  while (*node)
+    {
+      if (strcmp ((*node)->name, filename) == 0)
+       return node;
+      node = &(*node)->link;
+    }
+
+  return node;
+}  
+
+// Print the store of filenames of DSOs that need collection.
+void
+_Jv_print_gc_store (void)
+{
+  for (int i = 0; i < FILENAME_STORE_SIZE; i++)
+    {
+      filename_node *node = filename_store[i];
+      while (node)
+       {
+         fprintf (stderr, "%s\n", node->name);
+         node = node->link;
+       }
+    }
+}
+
+// Create a new node in the store of libraries to collect.
+static filename_node *
+new_node (const char *filename)
+{
+  filename_node *node = (filename_node*)_Jv_Malloc (sizeof (filename_node));
+  node->name = (char *)_Jv_Malloc (strlen (filename) + 1);
+  node->link = NULL;
+  strcpy (node->name, filename);
+  
+  return node;
+}
+
+// Nonzero if the gc should scan this lib.
+static int 
+_Jv_GC_has_static_roots (const char *filename, void *, size_t)
+{
+  if (filename == NULL || strlen (filename) == 0)
+    // No filename; better safe than sorry.
+    return 1;
+
+  filename_node **node = find_file (filename);
+  if (*node)
+    return 1;
+
+  return 0;
+}
+
+#endif
+
+// Register the DSO that contains p for collection.
+void
+_Jv_RegisterLibForGc (const void *p __attribute__ ((__unused__)))
+{
+#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
+  Dl_info info;
+
+  if (dladdr (const_cast<void *>(p), &info) != 0)
+    {
+      filename_node **node = find_file (info.dli_fname);
+      if (! *node)
+       *node = new_node (info.dli_fname);
+    }
+#endif
+}
+
+void
+_Jv_SuspendThread (_Jv_Thread_t *thread)
+{
+#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
+     && !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS)
+  GC_suspend_thread (_Jv_GetPlatformThreadID (thread));
+#endif
+}
+
+void
+_Jv_ResumeThread (_Jv_Thread_t *thread)
+{
+#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
+     && !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS)
+  GC_resume_thread (_Jv_GetPlatformThreadID (thread));
+#endif
+}
+
+int
+_Jv_IsThreadSuspended (_Jv_Thread_t *thread)
+{
+#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
+     && !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS)
+  return GC_is_thread_suspended (_Jv_GetPlatformThreadID (thread));
+#else
+  return 0;
+#endif
+}
+
+void
+_Jv_GCAttachThread ()
+{
+  // The registration interface is only defined on posixy systems and
+  // only actually works if pthread_getattr_np is defined.
+  // FIXME: until gc7 it is simpler to disable this on solaris.
+#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS)
+  GC_register_my_thread ();
+#endif
+}
+
+void
+_Jv_GCDetachThread ()
+{
+#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS)
+  GC_unregister_my_thread ();
+#endif
+}