Index: vmcore/include/object_handles.h =================================================================== --- vmcore/include/object_handles.h (revision 680597) +++ vmcore/include/object_handles.h (working copy) @@ -155,6 +155,20 @@ */ void oh_enumerate_global_handles(); +/* + * Weak global handles + */ + +/** + * Creates weak global handle, which needs to be explicitly freed. + */ +ObjectHandle oh_allocate_weak_global_handle_from_jni(); +/** + * Frees weak global handle. + */ +void oh_deallocate_weak_global_handle(ObjectHandle); +/* For interface simplicity, weak global handles are also enumerated in function oh_enumerate_global_handles */ + ////////////////////////////////////////////////////////////////////////// // Local Handles Index: vmcore/src/jni/jni.cpp =================================================================== --- vmcore/src/jni/jni.cpp (revision 680597) +++ vmcore/src/jni/jni.cpp (working copy) @@ -970,14 +970,30 @@ return JNI_TRUE; } - if(!(ref1 && ref2)) { - // One reference is null and the other is not. - return JNI_FALSE; - } - ObjectHandle h1 = (ObjectHandle)ref1; ObjectHandle h2 = (ObjectHandle)ref2; + jboolean result; + if(!h1) { + assert(h2); + tmn_suspend_disable(); + if(h2->object) + result = JNI_FALSE; + else // h1 is NULL and h2 points to NULL object + result = JNI_TRUE; + tmn_suspend_enable(); + return result; + } else if(!h2) { + assert(h1); + tmn_suspend_disable(); + if(h1->object) + result = JNI_FALSE; + else // h2 is NULL and h1 points to NULL object + result = JNI_TRUE; + tmn_suspend_enable(); + return result; + } + tmn_suspend_disable(); //---------------------------------v ManagedObject *java_ref1 = h1->object; @@ -985,7 +1001,7 @@ TRACE2("jni-same", "IsSameObject: Obj1 = " << java_ref1->vt()->clss->get_name()->bytes << " Obj2 = " << java_ref2->vt()->clss->get_name()->bytes << " objects are " << ((java_ref1 == java_ref2) ? "same" : "different")); - jboolean result = (jboolean)((java_ref1 == java_ref2) ? JNI_TRUE : JNI_FALSE); + result = (jboolean)((java_ref1 == java_ref2) ? JNI_TRUE : JNI_FALSE); tmn_suspend_enable(); //---------------------------------^ @@ -1418,14 +1434,47 @@ { TRACE("NewWeakGlobalRef called"); assert(hythread_is_suspend_enabled()); - return NewGlobalRef(jni_env, obj); + + if (exn_raised() || !obj) return NULL; + + if(obj == NULL) { + return NULL; + } + + assert(hythread_is_suspend_enabled()); + ObjectHandle new_handle = oh_allocate_weak_global_handle_from_jni(); + + if (new_handle == NULL) { + return NULL; + } + + ObjectHandle old_handle = (ObjectHandle)obj; + + tmn_suspend_disable(); //---------------------------------v + + new_handle->object = old_handle->object; + TRACE("NewWeakGlobalRef class = " << old_handle->object->vt()->clss); + + tmn_suspend_enable(); //---------------------------------^ + + return (jweak)new_handle; } VMEXPORT void JNICALL DeleteWeakGlobalRef(JNIEnv * jni_env, jweak obj) { TRACE("DeleteWeakGlobalRef called"); assert(hythread_is_suspend_enabled()); - DeleteGlobalRef(jni_env, obj); + + if (obj == NULL) return; + +#ifdef _DEBUG + tmn_suspend_disable(); + ObjectHandle h = (ObjectHandle)obj; + TRACE("DeleteGlobalRef class = " << h->object->vt()->clss); + tmn_suspend_enable(); +#endif + + oh_deallocate_weak_global_handle((ObjectHandle)obj); } jboolean JNICALL ExceptionCheck(JNIEnv * jni_env) Index: vmcore/src/object/object_handles.cpp =================================================================== --- vmcore/src/object/object_handles.cpp (revision 680597) +++ vmcore/src/object/object_handles.cpp (working copy) @@ -258,15 +258,93 @@ STD_FREE(h); } //vm_delete_global_object_handle +void oh_enumerate_weak_global_handles(); + void oh_enumerate_global_handles() { TRACE2("enumeration", "enumerating global handles"); for(ObjectHandlesOld* g = global_object_handles; g; g=g->next) if (g->handle.object) vm_enumerate_root_reference((void**)&g->handle.object, FALSE); + oh_enumerate_weak_global_handles(); } ////////////////////////////////////////////////////////////////////////// +// Weak Global Handles +static ObjectHandlesOld* weak_global_object_handles = NULL; + +static ObjectHandle oh_allocate_weak_global_handle_internal() +{ + Global_Env * vm_env = VM_Global_State::loader_env; + + // Allocate and init handle + ObjectHandlesOld* h = oh_allocate_object_handle(); //(ObjectHandlesOld*)m_malloc(sizeof(ObjectHandlesOld)); + + if (h == NULL) { + return NULL; + } + + h->handle.object = NULL; + h->allocated_on_the_stack = false; + + hythread_suspend_disable(); // ----------------vvv + vm_env->p_handle_lock->_lock(); + // Insert at beginning of globals list + h->prev = NULL; + h->next = weak_global_object_handles; + weak_global_object_handles = h; + if(h->next) + h->next->prev = h; + vm_env->p_handle_lock->_unlock(); + hythread_suspend_enable(); //--------------------------------------------^^^ + return &h->handle; +} //vm_create_weak_global_object_handle + +ObjectHandle oh_allocate_weak_global_handle_from_jni() +{ + ObjectHandle res = oh_allocate_weak_global_handle_internal(); + + if (res == NULL) { + exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError); + } + return res; +} + +static bool UNUSED is_weak_global_handle(ObjectHandle handle) +{ + for(ObjectHandlesOld* g = weak_global_object_handles; g; g=g->next) + if (g==(ObjectHandlesOld*)handle) return true; + return false; +} + +void oh_deallocate_weak_global_handle(ObjectHandle handle) +{ + Global_Env * vm_env = VM_Global_State::loader_env; + + tmn_suspend_disable(); // ----------vvv + vm_env->p_handle_lock->_lock(); + assert(is_weak_global_handle(handle)); + + handle->object = NULL; + ObjectHandlesOld* h = (ObjectHandlesOld*)handle; + if (h->next) h->next->prev = h->prev; + if (h->prev) h->prev->next = h->next; + if (h==weak_global_object_handles) weak_global_object_handles = h->next; + + vm_env->p_handle_lock->_unlock(); + tmn_suspend_enable(); // -------------------------------------^^^ + STD_FREE(h); +} //vm_delete_global_object_handle + +static void oh_enumerate_weak_global_handles() +{ + TRACE2("enumeration", "enumerating weak global handles"); + for(ObjectHandlesOld* g = weak_global_object_handles; g; g=g->next) + if (g->handle.object) + vm_enumerate_weak_root_reference((void**)&g->handle.object, FALSE); +} + +////////////////////////////////////////////////////////////////////////// // ObjectHandles static ObjectHandlesOld* oh_allocate_object_handle()