Index: vm/vmcore/include/environment.h =================================================================== --- vm/vmcore/include/environment.h (revision 490549) +++ vm/vmcore/include/environment.h (working copy) @@ -180,6 +180,7 @@ Class* java_lang_ArithmeticException_Class; Class* java_lang_ClassCastException_Class; Class* java_lang_OutOfMemoryError_Class; + Class* java_lang_InternalError_Class; Class* java_lang_ThreadDeath_Class; ObjectHandle java_lang_Object; @@ -200,10 +201,8 @@ Class* java_lang_reflect_Field_Class; Class* java_lang_reflect_Method_Class; - Class* finalizer_thread; + Class* java_lang_FinalizerThread_Class; // pointers to 2 static fields in FinalizerThread class. - jboolean* finalizer_shutdown; - jboolean* finalizer_on_exit; Class* java_lang_EMThreadSupport_Class; // VTable for the java_lang_String class Index: vm/vmcore/include/finalize.h =================================================================== --- vm/vmcore/include/finalize.h (revision 490549) +++ vm/vmcore/include/finalize.h (working copy) @@ -41,12 +41,14 @@ void vm_run_pending_finalizers(); int vm_do_finalization(int quantity); int vm_get_finalizable_objects_quantity(); +void vm_obtain_finalizer_fields(); #ifndef USE_GC_STATIC VMEXPORT #endif void vm_enumerate_objects_to_be_finalized(); void vm_enumerate_references_to_enqueue(); +int vm_get_references_quantity(); void vm_enqueue_references(); Index: vm/vmcore/src/class_support/Environment.cpp =================================================================== --- vm/vmcore/src/class_support/Environment.cpp (revision 490549) +++ vm/vmcore/src/class_support/Environment.cpp (working copy) @@ -177,11 +177,14 @@ java_lang_ArithmeticException_Class = NULL; java_lang_ClassCastException_Class = NULL; java_lang_OutOfMemoryError_Class = NULL; + java_lang_InternalError_Class = NULL; java_lang_ThreadDeath_Class = NULL; java_lang_OutOfMemoryError = NULL; popFrameException = NULL; + java_lang_FinalizerThread_Class = NULL; + java_io_Serializable_Class = NULL; java_lang_Cloneable_Class = NULL; java_lang_Thread_Class = NULL; Index: vm/vmcore/src/gc/stop_the_world_root_set_enum.cpp =================================================================== --- vm/vmcore/src/gc/stop_the_world_root_set_enum.cpp (revision 490549) +++ vm/vmcore/src/gc/stop_the_world_root_set_enum.cpp (working copy) @@ -192,8 +192,8 @@ // *after* it releases global GC lock. // Several Reference Queues may need to be notified because the GC added References to them. Do that now. - LOG2("ref", "Enqueueing references"); - vm_enqueue_references(); + //LOG2("ref", "Enqueueing references"); + //vm_enqueue_references(); // For now we run the finalizers immediately in the context of the thread which requested GC. // Eventually we may have a different scheme, e.g., a dedicated finalize thread. Index: vm/vmcore/src/init/finalize.cpp =================================================================== --- vm/vmcore/src/init/finalize.cpp (revision 490549) +++ vm/vmcore/src/init/finalize.cpp (working copy) @@ -27,10 +27,12 @@ #include "lock_manager.h" #include "object_layout.h" #include "open/types.h" +#include #include "Class.h" #include "open/vm_util.h" #include "environment.h" #include "ini.h" +#include "m2n.h" #include "exceptions.h" #include "compile.h" #include "nogc.h" @@ -114,15 +116,30 @@ Class* CharsetEncoder; Class* FileDescriptor; Class* FileOutputStream; + + //jobject get_work_lock(); + //jboolean* get_work_lock(); + //jboolean* get_work_lock(); + bool fields_obtained; + void check_fields_obtained(); + Lock_Manager obtain_fields_lock; + jobject work_lock; + jboolean* shutdown; + jboolean* on_exit; public: Objects_To_Finalize() : Object_Queue("finalize") { classes_cached = false; + fields_obtained = false; + work_lock = NULL; + work_lock = NULL; + on_exit = NULL; }; // redefine of add method void add_object(ManagedObject *p_obj); void run_finalizers(); int do_finalization(int quantity); + void obtain_fields(); }; //Objects_To_Finalize class References_To_Enqueue: public Object_Queue @@ -253,7 +270,8 @@ void Objects_To_Finalize::add_object(ManagedObject *p_obj) { - Class* finalizer_thread = VM_Global_State::loader_env->finalizer_thread; + Class* finalizer_thread = + VM_Global_State::loader_env->java_lang_FinalizerThread_Class; if (!finalizer_thread) { return; @@ -301,41 +319,107 @@ || (test==FileOutputStream)); } +void Objects_To_Finalize::check_fields_obtained() { + if (!fields_obtained) { + obtain_fields(); + } +} + +void Objects_To_Finalize::obtain_fields() { + obtain_fields_lock._lock(); + + if (!fields_obtained) { + Class* finalizer_thread = + VM_Global_State::loader_env->java_lang_FinalizerThread_Class; + + if (!finalizer_thread) { + obtain_fields_lock._unlock(); + return; + } + + Field* work_lock_field = class_lookup_field_recursive( + finalizer_thread, + "workLock", "Ljava/lang/Object;"); + Field* shutdown_field = class_lookup_field_recursive( + finalizer_thread, + "shutdown", "Z"); + Field* on_exit_field = class_lookup_field_recursive( + finalizer_thread, + "onExit", "Z"); + + assert(work_lock_field); + assert(shutdown_field); + assert(on_exit_field); + + tmn_suspend_disable(); + ManagedObject* work_lock_addr = get_raw_reference_pointer( + (ManagedObject **)work_lock_field->get_address()); + assert(work_lock_addr); + work_lock = oh_allocate_global_handle(); + work_lock->object = work_lock_addr; + assert(work_lock); + tmn_suspend_enable(); + + shutdown = (jboolean*) shutdown_field->get_address(); + on_exit = (jboolean*) on_exit_field->get_address(); + assert(shutdown); + assert(on_exit); + + fields_obtained = true; + } + obtain_fields_lock._unlock(); +} + void Objects_To_Finalize::run_finalizers() { assert(hythread_is_suspend_enabled()); - Class* finalizer_thread = VM_Global_State::loader_env->finalizer_thread; + Class* finalizer_thread = + VM_Global_State::loader_env->java_lang_FinalizerThread_Class; if (!finalizer_thread) { return; } - int num_objects = getLength(); + check_fields_obtained(); + int num_objects = getLength() + vm_get_references_quantity(); + if (num_objects == 0) { - return; + //return; } if ((p_TLS_vmthread->finalize_thread_flags & (FINALIZER_STARTER | FINALIZER_THREAD)) != 0) { TRACE2("finalize", "recursive finalization prevented"); - return; + //return; } p_TLS_vmthread->finalize_thread_flags |= FINALIZER_STARTER; TRACE2("finalize", "run_finalizers() started"); - jvalue args[1]; - args[0].z = false; + if (FRAME_COMPILATION == + (FRAME_COMPILATION | m2n_get_frame_type(m2n_get_last_frame()))) { + assert(work_lock); - Method* finalize_meth = class_lookup_method_recursive(finalizer_thread, - "startFinalization", "(Z)V"); - assert(finalize_meth); + IDATA r = jthread_monitor_try_enter(work_lock); - tmn_suspend_disable(); - vm_execute_java_method_array((jmethodID) finalize_meth, 0, args); - tmn_suspend_enable(); + if (r == TM_ERROR_NONE) { + jthread_monitor_notify_all(work_lock); + jthread_monitor_exit(work_lock); + } + } else { + Method* finalize_meth = class_lookup_method_recursive(finalizer_thread, + "startFinalization", "(Z)V"); + assert(finalize_meth); + jvalue args[1]; + args[0].z = false; + + tmn_suspend_disable(); + vm_execute_java_method_array((jmethodID) finalize_meth, 0, args); + tmn_suspend_enable(); + } + #ifndef NDEBUG if (exn_raised()) { INFO2("finalize", "Uncaught exception " @@ -365,15 +449,13 @@ args[0].l = (jobject) handle; /* BEGIN: modified for NATIVE FINALIZER THREAD */ - jboolean *finalizer_shutdown, *finalizer_on_exit; if(!native_finalizer_thread_flag){ - assert(VM_Global_State::loader_env->finalizer_thread); - finalizer_shutdown = VM_Global_State::loader_env->finalizer_shutdown; - assert(finalizer_shutdown); - finalizer_on_exit = VM_Global_State::loader_env->finalizer_on_exit; - assert(finalizer_on_exit); - native_finalizer_shutdown = (Boolean)*finalizer_shutdown; - native_finalizer_on_exit = (Boolean)*finalizer_on_exit; + assert(VM_Global_State::loader_env->java_lang_FinalizerThread_Class); + check_fields_obtained(); + assert(shutdown); + assert(on_exit); + native_finalizer_shutdown = (Boolean)*shutdown; + native_finalizer_on_exit = (Boolean)*on_exit; } /* END: modified for NATIVE FINALIZER THREAD */ @@ -402,13 +484,19 @@ assert(clss); /* BEGIN: modified for NATIVE FINALIZER THREAD */ - if(native_finalizer_thread_flag) + if(native_finalizer_thread_flag) { native_finalizer_on_exit = get_finalizer_on_exit_flag(); - if (native_finalizer_on_exit && is_class_ignored(clss)) { + + if (native_finalizer_on_exit && is_class_ignored(clss)) { + tmn_suspend_enable(); + continue; + } + } + /* END: modified for NATIVE FINALIZER THREAD */ + if ((*on_exit) && is_class_ignored(clss)) { tmn_suspend_enable(); continue; } - /* END: modified for NATIVE FINALIZER THREAD */ Method *finalize = class_lookup_method_recursive(clss, VM_Global_State::loader_env->FinalizeName_String, @@ -526,6 +614,11 @@ { return objects_to_finalize.getLength(); } + +void vm_obtain_finalizer_fields() { + objects_to_finalize.obtain_fields(); +} + // -- Code to deal with Reference Queues that need to be notified. static References_To_Enqueue references_to_enqueue; @@ -544,7 +637,7 @@ } // vm_enqueue_reference void vm_enqueue_references() -{ +{ /* BEGIN: modified for NATIVE REFERENCE ENQUEUE THREAD */ if(get_native_ref_enqueue_thread_flag()) activate_ref_enqueue_thread(); @@ -553,6 +646,11 @@ /* END: modified for NATIVE REFERENCE ENQUEUE THREAD */ } //vm_enqueue_references +int vm_get_references_quantity() +{ + return references_to_enqueue.getLength(); +} + /* added for NATIVE REFERENCE ENQUEUE THREAD */ void vm_ref_enqueue_func(void) { Index: vm/vmcore/src/init/vm_init.cpp =================================================================== --- vm/vmcore/src/init/vm_init.cpp (revision 490549) +++ vm/vmcore/src/init/vm_init.cpp (working copy) @@ -46,6 +46,7 @@ #include "vm_strings.h" #include "slot.h" #include "classpath_const.h" +#include "finalize.h" #include "finalizer_thread.h" /* added for NATIVE FINALIZER THREAD */ #include "ref_enqueue_thread.h" /* added for NATIVE REFERENCE ENQUEUE THREAD */ @@ -396,6 +397,8 @@ preload_class(vm_env, "java/lang/ClassCastException"); vm_env->java_lang_OutOfMemoryError_Class = preload_class(vm_env, "java/lang/OutOfMemoryError"); + vm_env->java_lang_InternalError_Class = + preload_class(vm_env, "java/lang/InternalError"); vm_env->java_lang_ThreadDeath_Class = preload_class(vm_env, "java/lang/ThreadDeath"); @@ -727,7 +730,9 @@ class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_StackOverflowError_Class); // Precompile ThreadDeath. class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_ThreadDeath_Class); - + // Precompile InternalError. + class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_InternalError_Class); + hythread_suspend_enable(); // Mark j.l.Throwable() constructor as a side effects free. @@ -796,22 +801,12 @@ if (get_boolean_property("vm.finalize", TRUE, VM_PROPERTIES)) { // Load and initialize finalizer thread. - vm_env->finalizer_thread = preload_class(vm_env, "java/lang/FinalizerThread"); - assert(vm_env->finalizer_thread); + vm_env->java_lang_FinalizerThread_Class = + preload_class(vm_env, "java/lang/FinalizerThread"); + assert(vm_env->java_lang_FinalizerThread_Class); - Field * finalizer_shutdown_field = - class_lookup_field_recursive(vm_env->finalizer_thread, "shutdown", "Z"); - Field* finalizer_on_exit_field = - class_lookup_field_recursive(vm_env->finalizer_thread, "onExit", "Z"); - assert(finalizer_shutdown_field); - assert(finalizer_on_exit_field); - vm_env->finalizer_shutdown = (jboolean*) finalizer_shutdown_field->get_address(); - vm_env->finalizer_on_exit = (jboolean*) finalizer_on_exit_field->get_address(); - assert(vm_env->finalizer_shutdown); - assert(vm_env->finalizer_on_exit); - class_initialize_from_jni(vm_env->finalizer_thread); - } else { - vm_env->finalizer_thread = NULL; + class_initialize_from_jni(vm_env->java_lang_FinalizerThread_Class); + vm_obtain_finalizer_fields(); } if(vm_env->TI->isEnabled() && vm_env->TI->needCreateEventThread() ) { vm_env->TI->TIenvs_lock._lock(); Index: vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.cpp =================================================================== --- vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.cpp (revision 490549) +++ vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.cpp (working copy) @@ -62,6 +62,7 @@ JNIEXPORT jint JNICALL Java_java_lang_FinalizerThread_doFinalization (JNIEnv *, jclass, jint quantity) { + vm_enqueue_references(); return (jint) vm_do_finalization(quantity); } /** @@ -75,7 +76,8 @@ JNIEXPORT jint JNICALL Java_java_lang_FinalizerThread_getFinalizersQuantity (JNIEnv *, jclass) { - return (jint) vm_get_finalizable_objects_quantity(); + return (jint) vm_get_finalizable_objects_quantity() + + vm_get_references_quantity(); } /**