diff --git a/vmcore/include/classloader.h b/vmcore/include/classloader.h index d822c59..c7924a6 100644 --- a/vmcore/include/classloader.h +++ b/vmcore/include/classloader.h @@ -155,7 +155,7 @@ private: public: ClassLoader() : m_loader(NULL), m_parent(NULL), m_name(NULL), m_package_table(NULL), m_loadedClasses(NULL), m_loadingClasses(NULL), m_reportedClasses(NULL), - m_javaTypes(NULL), m_nativeLibraries(NULL), m_verifyData(NULL) + m_javaTypes(NULL), m_nativeLibraries(NULL), m_verifyData(NULL), m_markBit(false) { apr_pool_create(&pool, 0); } @@ -208,6 +208,8 @@ protected: public: bool IsBootstrap() { return m_loader == NULL; } + void Mark() { m_markBit = true; } + bool isMarked() { return m_markBit; } ManagedObject* GetLoader() { return m_loader; } const String* GetName() { return m_name; } ClassLoader* GetParent() { return m_parent; } @@ -225,6 +227,7 @@ public: VMEXPORT static ClassLoader* LookupLoader( ManagedObject* loader ); static void UnloadClassLoader( ManagedObject* loader ); static void gc_enumerate(); + static void ClearMarkBits(); static unsigned GetClassLoaderNumber() { return m_nextEntry; } static ClassLoader** GetClassLoaderTable() { return m_table; } static void DeleteClassLoaderTable(){ @@ -273,6 +276,7 @@ protected: NativeLibraryList m_nativeLibraries; Lock_Manager m_lock; Lock_Manager m_types_cache_lock; + bool m_markBit; void* m_verifyData; apr_pool_t* pool; PoolManager *CodeMemoryManager; diff --git a/vmcore/include/unloading.h b/vmcore/include/unloading.h index 2e33a15..b3140be 100644 --- a/vmcore/include/unloading.h +++ b/vmcore/include/unloading.h @@ -22,5 +22,6 @@ #ifndef __UNLOADING_H__ #define __UNLOADING_H__ +void class_unloading_clear_mark_bits(); #endif diff --git a/vmcore/src/class_support/classloader.cpp b/vmcore/src/class_support/classloader.cpp index 2abd5d9..e39dde2 100644 --- a/vmcore/src/class_support/classloader.cpp +++ b/vmcore/src/class_support/classloader.cpp @@ -484,6 +484,21 @@ void ClassLoader::gc_enumerate() } +void ClassLoader::ClearMarkBits() +{ + TRACE2("classloader.unloading.clear", "Clearing mark bits"); + LMAutoUnlock aulock( &(ClassLoader::m_tableLock) ); + ClassTable::iterator cti; + for(unsigned i = 0; i < m_nextEntry; i++) { + TRACE2("classloader.unloading.debug", " Clearing mark bits in classloader " + << m_table[i] << " (" << m_table[i]->m_loader << " : " + << m_table[i]->m_loader->vt_unsafe()->clss->get_name()->bytes << ") and its classes"); + m_table[i]->m_markBit = 0; + } + TRACE2("classloader.unloading.clear", "Finished clearing mark bits"); +} + + ClassLoader* ClassLoader::AddClassLoader( ManagedObject* loader ) { SuspendDisabledChecker sdc; @@ -997,6 +1012,9 @@ GenericFunctionPointer ClassLoader::Look return NULL; } +void class_unloading_clear_mark_bits() { + ClassLoader::ClearMarkBits(); +} inline void BootstrapClassLoader::SetClasspathFromString(char* bcp, apr_pool_t* tmp_pool) diff --git a/vmcore/src/gc/root_set_enum_common.cpp b/vmcore/src/gc/root_set_enum_common.cpp index 8abd608..09003fc 100644 --- a/vmcore/src/gc/root_set_enum_common.cpp +++ b/vmcore/src/gc/root_set_enum_common.cpp @@ -255,6 +255,24 @@ #endif << "." << method_get_name(cci->get_method()) << method_get_descriptor(cci->get_method())); cci->get_jit()->get_root_set_from_stack_frame(cci->get_method(), 0, si_get_jit_context(si)); + const ClassLoader* cl = cci->get_method()->get_class()->get_class_loader(); + assert (cl); + // force cl classloader to be enumerated as strong reference + const_cast( cl )->Mark(); + if (cci->has_inline_info()) { + JIT *jit = cci->get_jit(); + NativeCodePtr ip = si_get_ip(si); + uint32 inlined_depth = si_get_inline_depth(si); + uint32 offset = (POINTER_SIZE_INT)ip - (POINTER_SIZE_INT)cci->get_code_block_addr(); + for (uint32 i = 0; i < inlined_depth; i++) { + Method* m = jit->get_inlined_method(cci->get_inline_info(), offset, i); + assert (m); + cl = m->get_class()->get_class_loader(); + assert (cl); + // force cl classloader to be enumerated as strong reference + const_cast( cl )->Mark(); + } + } TRACE2("enumeration", "enumerated eip=" << (void *) si_get_ip(si) << " is_first=" << !si_get_jit_context(si)->is_ip_past << " " << class_get_name(method_get_class(cci->get_method())) @@ -268,6 +286,13 @@ #endif << (m2n_get_method(si_get_m2n(si)) ? method_get_name(m2n_get_method(si_get_m2n(si))) : "") << (m2n_get_method(si_get_m2n(si)) ? method_get_descriptor(m2n_get_method(si_get_m2n(si))) : "")); oh_enumerate_handles(m2n_get_local_handles(si_get_m2n(si))); + Method* m = m2n_get_method(si_get_m2n(si)); + if (m) { + const ClassLoader* cl = m->get_class()->get_class_loader(); + assert (cl); + // force cl classloader to be enumerated as strong reference + const_cast( cl )->Mark(); + } } si_goto_previous(si, false); } diff --git a/vmcore/src/gc/stop_the_world_root_set_enum.cpp b/vmcore/src/gc/stop_the_world_root_set_enum.cpp index 5e0720c..32d6e7a 100644 --- a/vmcore/src/gc/stop_the_world_root_set_enum.cpp +++ b/vmcore/src/gc/stop_the_world_root_set_enum.cpp @@ -98,6 +98,8 @@ stop_the_world_root_set_enumeration() jvmti_send_gc_start_event(); + class_unloading_clear_mark_bits(); + current_vm_thread = p_TLS_vmthread; // Run through list of active threads and enumerate each one of them. hythread_t tm_thread = hythread_iterator_next(&iterator);