--- old/src/share/vm/runtime/jniHandles.hpp 2017-04-25 16:45:49.159172610 +0200 +++ new/src/share/vm/runtime/jniHandles.hpp 2017-04-25 16:45:49.011172615 +0200 @@ -40,14 +40,76 @@ static JNIHandleBlock* _weak_global_handles; // First weak global handle block static oop _deleted_handle; // Sentinel marking deleted handles + inline static oop* oop_addr(jobject handle); inline static bool is_jweak(jobject handle); - inline static oop& jobject_ref(jobject handle); // NOT jweak! - inline static oop& jweak_ref(jobject handle); template inline static oop guard_value(oop value); template inline static oop resolve_impl(jobject handle); template static oop resolve_jweak(jweak handle); + static oop resolve_handle(jobject handle); + + enum ResolveType { + DEFAULT, + EXTERNAL_GUARD, + NOT_NULL + }; + + template + class JNIHandleResolver: public StackObj { + oop _value; + + bool is_not_null() const { + return type == NOT_NULL; + } + + bool is_external_guard() const { + return type == EXTERNAL_GUARD; + } + + bool is_default() const { + return type == DEFAULT; + } + + bool is_dead(oop value) const { + return value == NULL || value == badJNIHandle || value == deleted_handle(); + } + + void assert_not_dead(oop value) const { + if (!is_external_guard()) { + assert(value != badJNIHandle, "Pointing to zapped jni handle area"); + assert(value == NULL || value != deleted_handle(), "Used a deleted global handle"); + } + } + + public: + JNIHandleResolver(jobject handle) { + oop value; + assert(!is_not_null() || handle != NULL, "JNI handle should not be null"); + if (!is_not_null() && handle == NULL) { + value = NULL; + } else { + value = *oop_addr(handle); + assert_not_dead(value); + if (is_external_guard() && is_dead(value)) { + value = NULL; + } else { + value = resolve_handle(handle); + } + } + _value = value; + } + + oop value() const { + return _value; + } + + ~JNIHandleResolver() { + assert_not_dead(_value); + assert(!is_not_null() || _value != NULL, "NULL read from jni handle"); + } + }; + public: // Low tag bit in jobject used to distinguish a jweak. jweak is // type equivalent to jobject, but there are places where we need to @@ -203,55 +265,12 @@ return (reinterpret_cast(handle) & weak_tag_mask) != 0; } -inline oop& JNIHandles::jobject_ref(jobject handle) { - assert(!is_jweak(handle), "precondition"); - return *reinterpret_cast(handle); -} - -inline oop& JNIHandles::jweak_ref(jobject handle) { - assert(is_jweak(handle), "precondition"); - char* ptr = reinterpret_cast(handle) - weak_tag_value; - return *reinterpret_cast(ptr); -} - -// external_guard is true if called from resolve_external_guard. -// Treat deleted (and possibly zapped) as NULL for external_guard, -// else as (asserted) error. -template -inline oop JNIHandles::guard_value(oop value) { - if (!external_guard) { - assert(value != badJNIHandle, "Pointing to zapped jni handle area"); - assert(value != deleted_handle(), "Used a deleted global handle"); - } else if ((value == badJNIHandle) || (value == deleted_handle())) { - value = NULL; - } - return value; -} - -// external_guard is true if called from resolve_external_guard. -template -inline oop JNIHandles::resolve_impl(jobject handle) { - assert(handle != NULL, "precondition"); - oop result; - if (is_jweak(handle)) { // Unlikely - result = resolve_jweak(handle); - } else { - result = jobject_ref(handle); - // Construction of jobjects canonicalize a null value into a null - // jobject, so for non-jweak the pointee should never be null. - assert(external_guard || result != NULL, - "Invalid value read from jni handle"); - result = guard_value(result); - } - return result; +inline oop* JNIHandles::oop_addr(jobject handle) { + return (oop*)(reinterpret_cast(handle) & ~(weak_tag_mask)); } inline oop JNIHandles::resolve(jobject handle) { - oop result = NULL; - if (handle != NULL) { - result = resolve_impl(handle); - } - return result; + return JNIHandleResolver(handle).value(); } // Resolve some erroneous cases to NULL, rather than treating them as @@ -259,23 +278,16 @@ // treated as NULL (though a deleted and later reallocated handle // isn't detected). inline oop JNIHandles::resolve_external_guard(jobject handle) { - oop result = NULL; - if (handle != NULL) { - result = resolve_impl(handle); - } - return result; + return JNIHandleResolver(handle).value(); } inline oop JNIHandles::resolve_non_null(jobject handle) { - assert(handle != NULL, "JNI handle should not be null"); - oop result = resolve_impl(handle); - assert(result != NULL, "NULL read from jni handle"); - return result; + return JNIHandleResolver(handle).value(); } inline void JNIHandles::destroy_local(jobject handle) { if (handle != NULL) { - jobject_ref(handle) = deleted_handle(); + *oop_addr(handle) = deleted_handle(); } }