* src/vm/finalizer.cpp, src/vm/finalizer.hpp: Generalize internal finalizer
authorStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 21 Feb 2011 23:06:28 +0000 (00:06 +0100)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 21 Feb 2011 23:06:28 +0000 (00:06 +0100)
handling.
* src/threads/lock.cpp: Use the new mechanism for lock record removal finalizers.

src/threads/lock.cpp
src/vm/finalizer.cpp
src/vm/finalizer.hpp

index 87851a731f1af33fb61a249c8510ac7a60caee70..372695e9a8cb44fb064f880a9bbf227b8af59167 100644 (file)
@@ -1,6 +1,6 @@
 /* src/threads/lock.cpp - lock implementation
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008, 2010
+   Copyright (C) 1996-2011
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -420,7 +420,7 @@ void lock_hashtable_cleanup(void)
 *******************************************************************************/
 
 #if defined(ENABLE_GC_BOEHM)
-static void lock_record_finalizer(void *object, void *p);
+static void lock_record_finalizer(java_handle_t *object, void *p);
 #endif
 
 static lock_record_t *lock_hashtable_get(java_handle_t* o)
@@ -465,14 +465,7 @@ static lock_record_t *lock_hashtable_get(java_handle_t* o)
 #if defined(ENABLE_GC_BOEHM)
                /* register new finalizer to clean up the lock record */
 
-               GC_finalization_proc ofinal = 0;
-               GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(o), lock_record_finalizer, 0, &ofinal, 0);
-
-               /* There was a finalizer -- reinstall it. We do not want to disrupt the
-                  normal finalizer operation. We hold the monitor on this object, so
-                  this is thread-safe. */
-               if (ofinal)
-                       GC_REGISTER_FINALIZER_NO_ORDER(LLNI_DIRECT(o), ofinal, 0, 0, 0);
+               Finalizer::attach_custom_finalizer(o, lock_record_finalizer, 0);
 #endif
 
                /* enter it in the hashtable */
@@ -496,30 +489,6 @@ static lock_record_t *lock_hashtable_get(java_handle_t* o)
        return lr;
 }
 
-/* lock_schedule_lockrecord_removal ********************************************
-
-   Gives the locking system a chance to schedule the removal of an unused lock
-   record. This function is called after an object's finalizer has run.
-
-   IN:
-         o....the object which has been finalized
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_BOEHM)
-void lock_schedule_lockrecord_removal(java_handle_t *o)
-{
-       Lockword lockword(*lock_lockword_get(o));
-       if (!lockword.is_fat_lock())
-               /* there is no lock record */
-               return;
-
-       /* register new finalizer to clean up the lock record */
-       GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(o), lock_record_finalizer, 0, 0, 0);
-}
-#endif
-
-
 /* lock_hashtable_remove *******************************************************
 
    Remove the lock record for the given object from the hashtable
@@ -590,25 +559,16 @@ static void lock_hashtable_remove(threadobject *t, java_handle_t *o)
 
 *******************************************************************************/
 
-static void lock_record_finalizer(void *object, void *p)
+static void lock_record_finalizer(java_handle_t *o, void *p)
 {
-       java_handle_t *o;
+#if !defined(NDEBUG)
        classinfo     *c;
 
-       o = (java_handle_t *) object;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
-       /* XXX this is only a dirty hack to make Boehm work with handles */
-
-       o = LLNI_WRAP((java_object_t *) o);
-#endif
-
        LLNI_class_get(o, c);
 
-#if !defined(NDEBUG)
        if (opt_DebugFinalizer) {
                log_start();
-               log_print("[finalizer lockrecord: o=%p p=%p class=", object, p);
+               log_print("[finalizer lockrecord: o=%p p=%p class=", o, p);
                class_print(c);
                log_print("]");
                log_finish();
index 7a4ecd4711e86c50f9beb68d519a9c8a9e506ff2..e69653cebfe57764feb7bd79ff3a4f46d6b09cd3 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/finalizer.c - finalizer linked list and thread
+/* src/vm/finalizer.cpp - finalizer linked list and thread
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2011
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 #include "vm/jit/asmpart.h"
 
+#include "finalizer.hpp"
+
+#include <map>
+
+#if defined(ENABLE_GC_BOEHM)
+# include "mm/boehm-gc/include/gc.h"
+#endif
 
 /* global variables ***********************************************************/
 
@@ -52,9 +59,7 @@ static Mutex     *finalizer_thread_mutex;
 static Condition *finalizer_thread_cond;
 #endif
 
-#if defined(__cplusplus)
 extern "C" {
-#endif
 
 /* finalizer_init **************************************************************
 
@@ -223,11 +228,90 @@ void finalizer_run(void *o, void *p)
        exceptions_clear_exception();
 
 #if defined(ENABLE_GC_BOEHM)
-    lock_schedule_lockrecord_removal(h);
+       Finalizer::reinstall_custom_finalizer(h);
 #endif
 }
 
-#if defined(__cplusplus)
+}
+
+#if defined(ENABLE_GC_BOEHM)
+
+struct FinalizerData {
+       Finalizer::FinalizerFunc f;
+       void *data;
+       FinalizerData(Finalizer::FinalizerFunc f, void *data): f(f), data(data) { }
+};
+
+Mutex final_mutex;
+// final_map contains registered custom finalizers for a given Java
+// object. Must be accessed with held final_mutex.
+std::multimap<java_handle_t *, FinalizerData> final_map;
+
+static void custom_finalizer_handler(void *object, void *data)
+{
+       typedef std::multimap<java_handle_t *, FinalizerData>::iterator MI;
+       java_handle_t *hdl = (java_handle_t *) object;
+       MutexLocker l(final_mutex);
+       MI it_first = final_map.lower_bound(hdl), it = it_first;
+       assert(it->first == hdl);
+       for (; it->first == hdl; ++it) {
+               final_mutex.unlock();
+               it->second.f(hdl, it->second.data);
+               final_mutex.lock();
+       }
+       final_map.erase(it_first, it);
+}
+
+/* attach_custom_finalizer *****************************************************
+
+   Register a custom handler that is run when the object becomes
+   unreachable. This is intended for internal cleanup actions. If the
+   handler already exists, it is not registered again, and its data
+   pointer is returned.
+
+*******************************************************************************/
+
+void *Finalizer::attach_custom_finalizer(java_handle_t *h, Finalizer::FinalizerFunc f, void *data)
+{
+       MutexLocker l(final_mutex);
+
+       GC_finalization_proc ofinal = 0;
+       void *odata = 0;
+
+       GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(h), custom_finalizer_handler, 0, &ofinal, &odata);
+
+       /* There was a finalizer -- reinstall it. We do not want to
+          disrupt the normal finalizer operation. This is thread-safe
+          because the other finalizer is only installed at object
+          creation time. */
+       if (ofinal && ofinal != custom_finalizer_handler)
+               GC_REGISTER_FINALIZER_NO_ORDER(LLNI_DIRECT(h), ofinal, odata, 0, 0);
+
+       typedef std::multimap<java_handle_t *, FinalizerData>::iterator MI;
+       std::pair<MI, MI> r = final_map.equal_range(h);
+       for (MI it = r.first; it != r.second; ++it)
+               if (it->second.f == f)
+                       return it->second.data;
+       final_map.insert(r.first, std::make_pair(h, FinalizerData(f, data)));
+       return data;
+}
+
+/* reinstall_custom_finalizer **************************************************
+
+   Arranges for the custom finalizers to be called after the Java
+   finalizer, possibly much later, because the object needs to become
+   unreachable.
+
+*******************************************************************************/
+
+void Finalizer::reinstall_custom_finalizer(java_handle_t *h)
+{
+       MutexLocker l(final_mutex);
+       std::multimap<java_handle_t *, FinalizerData>::iterator it = final_map.find(h);
+       if (it == final_map.end())
+               return;
+
+       GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(h), custom_finalizer_handler, 0, 0, 0);
 }
 #endif
 
@@ -237,7 +321,7 @@ void finalizer_run(void *o, void *p)
  * Emacs will automagically detect them.
  * ---------------------------------------------------------------------
  * Local variables:
- * mode: c
+ * mode: c++
  * indent-tabs-mode: t
  * c-basic-offset: 4
  * tab-width: 4
index 04abf9ed0e791dd6988de54f38a2462d14057320..3e7c5ae1c1dca876bb37b2589a6999521566d00c 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/finalizer.h - finalizer linked list and thread header
+/* src/vm/finalizer.hpp - finalizer linked list and thread header
 
-   Copyright (C) 1996-2005, 2006, 2008
+   Copyright (C) 1996-2011
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include "config.h"
 
 #ifdef __cplusplus
+
+struct Finalizer {
+       typedef void (*FinalizerFunc)(java_handle_t *h, void *data);
+       static void *attach_custom_finalizer(java_handle_t *h, FinalizerFunc f, void *data);
+       static void reinstall_custom_finalizer(java_handle_t *h);
+};
+
 extern "C" {
 #endif
 
@@ -57,7 +64,7 @@ void finalizer_run(void *o, void *p);
  * Emacs will automagically detect them.
  * ---------------------------------------------------------------------
  * Local variables:
- * mode: c
+ * mode: c++
  * indent-tabs-mode: t
  * c-basic-offset: 4
  * tab-width: 4