8205163: ZGC: Keeps finalizable marked PhantomReference referents strongly alive
Reviewed-by: pliden, kbarrett
--- a/src/hotspot/share/gc/z/zBarrier.hpp Thu Jun 07 10:11:36 2018 +0200
+++ b/src/hotspot/share/gc/z/zBarrier.hpp Tue Jun 19 08:44:31 2018 +0200
@@ -83,6 +83,7 @@
static oop load_barrier_on_phantom_oop_field_preloaded(volatile oop* p, oop o);
// Weak load barrier
+ static oop weak_load_barrier_on_oop_field(volatile oop* p);
static oop weak_load_barrier_on_oop_field_preloaded(volatile oop* p, oop o);
static oop weak_load_barrier_on_weak_oop(oop o);
static oop weak_load_barrier_on_weak_oop_field(volatile oop* p);
--- a/src/hotspot/share/gc/z/zBarrier.inline.hpp Thu Jun 07 10:11:36 2018 +0200
+++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp Tue Jun 19 08:44:31 2018 +0200
@@ -191,6 +191,12 @@
//
// Weak load barrier
//
+inline oop ZBarrier::weak_load_barrier_on_oop_field(volatile oop* p) {
+ assert(!ZResurrection::is_blocked(), "Should not be called during resurrection blocked phase");
+ const oop o = *p;
+ return weak_load_barrier_on_oop_field_preloaded(p, o);
+}
+
inline oop ZBarrier::weak_load_barrier_on_oop_field_preloaded(volatile oop* p, oop o) {
return weak_barrier<is_weak_good_or_null_fast_path, weak_load_barrier_on_oop_slow_path>(p, o);
}
--- a/src/hotspot/share/gc/z/zReferenceProcessor.cpp Thu Jun 07 10:11:36 2018 +0200
+++ b/src/hotspot/share/gc/z/zReferenceProcessor.cpp Tue Jun 19 08:44:31 2018 +0200
@@ -105,19 +105,21 @@
return *reference_referent_addr(obj);
}
-bool ZReferenceProcessor::is_referent_alive_or_null(oop obj, ReferenceType type) const {
- volatile oop* const p = reference_referent_addr(obj);
+bool ZReferenceProcessor::is_referent_strongly_alive_or_null(oop obj, ReferenceType type) const {
+ // Check if the referent is strongly alive or null, in which case we don't want to
+ // discover the reference. It can only be null if the application called
+ // Reference.enqueue() or Reference.clear().
+ //
+ // PhantomReferences with finalizable marked referents should technically not have
+ // to be discovered. However, InstanceRefKlass::oop_oop_iterate_ref_processing()
+ // does not know about the finalizable mark concept, and will therefore mark
+ // referents in non-discovered PhantomReferences as strongly live. To prevent
+ // this, we always discover PhantomReferences with finalizable marked referents.
+ // They will automatically be dropped during the reference processing phase.
- // Check if the referent is alive or null, in which case we don't want to discover
- // the reference. It can only be null if the application called Reference.enqueue()
- // or Reference.clear().
- if (type == REF_PHANTOM) {
- const oop o = ZBarrier::weak_load_barrier_on_phantom_oop_field(p);
- return o == NULL || ZHeap::heap()->is_object_live(ZOop::to_address(o));
- } else {
- const oop o = ZBarrier::weak_load_barrier_on_weak_oop_field(p);
- return o == NULL || ZHeap::heap()->is_object_strongly_live(ZOop::to_address(o));
- }
+ volatile oop* const p = reference_referent_addr(obj);
+ const oop o = ZBarrier::weak_load_barrier_on_oop_field(p);
+ return o == NULL || ZHeap::heap()->is_object_strongly_live(ZOop::to_address(o));
}
bool ZReferenceProcessor::is_referent_softly_alive(oop obj, ReferenceType type) const {
@@ -191,7 +193,7 @@
_encountered_count.get()[type]++;
if (is_reference_inactive(obj) ||
- is_referent_alive_or_null(obj, type) ||
+ is_referent_strongly_alive_or_null(obj, type) ||
is_referent_softly_alive(obj, type)) {
// Not discovered
return false;
--- a/src/hotspot/share/gc/z/zReferenceProcessor.hpp Thu Jun 07 10:11:36 2018 +0200
+++ b/src/hotspot/share/gc/z/zReferenceProcessor.hpp Tue Jun 19 08:44:31 2018 +0200
@@ -53,7 +53,7 @@
volatile oop* reference_referent_addr(oop obj) const;
oop reference_referent(oop obj) const;
bool is_reference_inactive(oop obj) const;
- bool is_referent_alive_or_null(oop obj, ReferenceType type) const;
+ bool is_referent_strongly_alive_or_null(oop obj, ReferenceType type) const;
bool is_referent_softly_alive(oop obj, ReferenceType type) const;
bool should_drop_reference(oop obj, ReferenceType type) const;
bool should_mark_referent(ReferenceType type) const;