From c471330216003cc9adb30b889e39c8f051a51deb Mon Sep 17 00:00:00 2001 From: Stefan Ring Date: Tue, 22 Feb 2011 00:06:28 +0100 Subject: [PATCH] * src/vm/finalizer.cpp, src/vm/finalizer.hpp: Generalize internal finalizer handling. * src/threads/lock.cpp: Use the new mechanism for lock record removal finalizers. --- src/threads/lock.cpp | 52 +++-------------------- src/vm/finalizer.cpp | 98 ++++++++++++++++++++++++++++++++++++++++---- src/vm/finalizer.hpp | 13 ++++-- 3 files changed, 107 insertions(+), 56 deletions(-) diff --git a/src/threads/lock.cpp b/src/threads/lock.cpp index 87851a731..372695e9a 100644 --- a/src/threads/lock.cpp +++ b/src/threads/lock.cpp @@ -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(); diff --git a/src/vm/finalizer.cpp b/src/vm/finalizer.cpp index 7a4ecd471..e69653ceb 100644 --- a/src/vm/finalizer.cpp +++ b/src/vm/finalizer.cpp @@ -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. @@ -44,6 +44,13 @@ #include "vm/jit/asmpart.h" +#include "finalizer.hpp" + +#include + +#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 final_map; + +static void custom_finalizer_handler(void *object, void *data) +{ + typedef std::multimap::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::iterator MI; + std::pair 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::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 diff --git a/src/vm/finalizer.hpp b/src/vm/finalizer.hpp index 04abf9ed0..3e7c5ae1c 100644 --- a/src/vm/finalizer.hpp +++ b/src/vm/finalizer.hpp @@ -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. @@ -29,6 +29,13 @@ #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 -- 2.25.1