8212184: Incorrect oop ref strength used for referents in FinalReference
authorpliden
Fri, 02 Nov 2018 07:58:22 +0100
changeset 52383 71564a544d4c
parent 52382 2e280ecec246
child 52384 d6dc479bcdd3
8212184: Incorrect oop ref strength used for referents in FinalReference Reviewed-by: eosterlund, kbarrett
src/hotspot/share/classfile/javaClasses.hpp
src/hotspot/share/classfile/javaClasses.inline.hpp
src/hotspot/share/gc/shared/accessBarrierSupport.cpp
--- a/src/hotspot/share/classfile/javaClasses.hpp	Fri Nov 02 07:46:00 2018 +0100
+++ b/src/hotspot/share/classfile/javaClasses.hpp	Fri Nov 02 07:58:22 2018 +0100
@@ -912,6 +912,7 @@
   static inline oop queue(oop ref);
   static inline void set_queue(oop ref, oop value);
   static bool is_referent_field(oop obj, ptrdiff_t offset);
+  static inline bool is_final(oop ref);
   static inline bool is_phantom(oop ref);
 };
 
--- a/src/hotspot/share/classfile/javaClasses.inline.hpp	Fri Nov 02 07:46:00 2018 +0100
+++ b/src/hotspot/share/classfile/javaClasses.inline.hpp	Fri Nov 02 07:58:22 2018 +0100
@@ -127,6 +127,9 @@
 HeapWord* java_lang_ref_Reference::discovered_addr_raw(oop ref) {
   return ref->obj_field_addr_raw<HeapWord>(discovered_offset);
 }
+bool java_lang_ref_Reference::is_final(oop ref) {
+  return InstanceKlass::cast(ref->klass())->reference_type() == REF_FINAL;
+}
 bool java_lang_ref_Reference::is_phantom(oop ref) {
   return InstanceKlass::cast(ref->klass())->reference_type() == REF_PHANTOM;
 }
--- a/src/hotspot/share/gc/shared/accessBarrierSupport.cpp	Fri Nov 02 07:46:00 2018 +0100
+++ b/src/hotspot/share/gc/shared/accessBarrierSupport.cpp	Fri Nov 02 07:58:22 2018 +0100
@@ -28,8 +28,16 @@
 #include "oops/access.hpp"
 
 DecoratorSet AccessBarrierSupport::resolve_unknown_oop_ref_strength(DecoratorSet decorators, oop base, ptrdiff_t offset) {
+  // Note that the referent in a FinalReference is technically not strong.
+  // However, it always behaves like one in practice. The two cases are:
+  //   1) A mutator calls Reference.get(). However, a mutator can only ever
+  //      see inactive FinalReferences, whose referents really are strong.
+  //   2) A GC heap walking operation. In this case the GC can see active
+  //      FinalReferences, but the GC always wants to follow the referent
+  //      as if it was strong.
   DecoratorSet ds = decorators & ~ON_UNKNOWN_OOP_REF;
-  if (!java_lang_ref_Reference::is_referent_field(base, offset)) {
+  if (!java_lang_ref_Reference::is_referent_field(base, offset) ||
+      java_lang_ref_Reference::is_final(base)) {
     ds |= ON_STRONG_OOP_REF;
   } else if (java_lang_ref_Reference::is_phantom(base)) {
     ds |= ON_PHANTOM_OOP_REF;