--- old/src/share/vm/prims/unsafe.cpp 2018-04-13 18:29:17.376733003 +0200 +++ new/src/share/vm/prims/unsafe.cpp 2018-04-13 18:29:17.312701001 +0200 @@ -199,37 +199,40 @@ // Get/SetObject must be special-cased, since it works with handles. +// We could be accessing the referent field in a reference +// object. If G1 is enabled then we need to register non-null +// referent with the SATB barrier. + +#if INCLUDE_ALL_GCS +static bool is_java_lang_ref_Reference_access(oop o, jlong offset) { + if (offset == java_lang_ref_Reference::referent_offset && o != NULL) { + Klass* k = o->klass(); + if (InstanceKlass::cast(k)->reference_type() != REF_NONE) { + assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity"); + return true; + } + } + return false; +} +#endif + +static void ensure_satb_referent_alive(oop o, jlong offset, oop v) { +#if INCLUDE_ALL_GCS + if (UseG1GC && v != NULL && is_java_lang_ref_Reference_access(o, offset)) { + G1SATBCardTableModRefBS::enqueue(v); + } +#endif +} + // The xxx140 variants for backward compatibility do not allow a full-width offset. UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) UnsafeWrapper("Unsafe_GetObject"); if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); GET_OOP_FIELD(obj, offset, v) - jobject ret = JNIHandles::make_local(env, v); -#if INCLUDE_ALL_GCS - // We could be accessing the referent field in a reference - // object. If G1 is enabled then we need to register a non-null - // referent with the SATB barrier. - if (UseG1GC) { - bool needs_barrier = false; - - if (ret != NULL) { - if (offset == java_lang_ref_Reference::referent_offset) { - oop o = JNIHandles::resolve_non_null(obj); - Klass* k = o->klass(); - if (InstanceKlass::cast(k)->reference_type() != REF_NONE) { - assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity"); - needs_barrier = true; - } - } - } - if (needs_barrier) { - oop referent = JNIHandles::resolve(ret); - G1SATBCardTableModRefBS::enqueue(referent); - } - } -#endif // INCLUDE_ALL_GCS - return ret; + ensure_satb_referent_alive(p, offset, v); + + return JNIHandles::make_local(env, v); UNSAFE_END UNSAFE_ENTRY(void, Unsafe_SetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset, jobject x_h)) @@ -262,32 +265,10 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) UnsafeWrapper("Unsafe_GetObject"); GET_OOP_FIELD(obj, offset, v) - jobject ret = JNIHandles::make_local(env, v); -#if INCLUDE_ALL_GCS - // We could be accessing the referent field in a reference - // object. If G1 is enabled then we need to register non-null - // referent with the SATB barrier. - if (UseG1GC) { - bool needs_barrier = false; - - if (ret != NULL) { - if (offset == java_lang_ref_Reference::referent_offset && obj != NULL) { - oop o = JNIHandles::resolve(obj); - Klass* k = o->klass(); - if (InstanceKlass::cast(k)->reference_type() != REF_NONE) { - assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity"); - needs_barrier = true; - } - } - } - if (needs_barrier) { - oop referent = JNIHandles::resolve(ret); - G1SATBCardTableModRefBS::enqueue(referent); - } - } -#endif // INCLUDE_ALL_GCS - return ret; + ensure_satb_referent_alive(p, offset, v); + + return JNIHandles::make_local(env, v); UNSAFE_END UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) @@ -312,6 +293,9 @@ } else { (void)const_cast(v = *(volatile oop*) addr); } + + ensure_satb_referent_alive(p, offset, v); + OrderAccess::acquire(); return JNIHandles::make_local(env, v); UNSAFE_END