src/hotspot/share/gc/shared/referenceProcessor.cpp
changeset 50277 f84ae8aa5d88
parent 50097 ed8a43d83fcc
child 50401 bf7eb61349d2
--- a/src/hotspot/share/gc/shared/referenceProcessor.cpp	Fri May 25 14:10:21 2018 -0700
+++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp	Sat May 26 03:11:50 2018 -0400
@@ -303,9 +303,6 @@
 }
 
 void DiscoveredListIterator::enqueue() {
-  // Self-loop next, so as to make Ref not active.
-  java_lang_ref_Reference::set_next_raw(_current_discovered, _current_discovered);
-
   HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(_current_discovered,
                                             java_lang_ref_Reference::discovered_offset,
                                             _next_discovered);
@@ -364,38 +361,35 @@
                              iter.removed(), iter.processed(), p2i(&refs_list));
 }
 
+inline void log_dropped_ref(const DiscoveredListIterator& iter, const char* reason) {
+  log_develop_trace(gc, ref)("Dropping %s reference " PTR_FORMAT ": %s",
+                             reason, p2i(iter.obj()),
+                             iter.obj()->klass()->internal_name());
+}
+
+// Traverse the list and remove any Refs whose referents are alive,
+// or NULL if discovery is not atomic.
 void ReferenceProcessor::process_phase2(DiscoveredList&    refs_list,
                                         BoolObjectClosure* is_alive,
                                         OopClosure*        keep_alive,
                                         VoidClosure*       complete_gc) {
-  if (discovery_is_atomic()) {
-    // complete_gc is ignored in this case for this phase
-    pp2_work(refs_list, is_alive, keep_alive);
-  } else {
-    assert(complete_gc != NULL, "Error");
-    pp2_work_concurrent_discovery(refs_list, is_alive,
-                                  keep_alive, complete_gc);
-  }
-}
-// Traverse the list and remove any Refs that are not active, or
-// whose referents are either alive or NULL.
-void
-ReferenceProcessor::pp2_work(DiscoveredList&    refs_list,
-                             BoolObjectClosure* is_alive,
-                             OopClosure*        keep_alive) {
-  assert(discovery_is_atomic(), "Error");
+  // complete_gc is unused.
   DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
   while (iter.has_next()) {
-    iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */));
-    DEBUG_ONLY(oop next = java_lang_ref_Reference::next(iter.obj());)
-    assert(next == NULL, "Should not discover inactive Reference");
-    if (iter.is_referent_alive()) {
-      log_develop_trace(gc, ref)("Dropping strongly reachable reference (" INTPTR_FORMAT ": %s)",
-                                 p2i(iter.obj()), iter.obj()->klass()->internal_name());
+    iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */));
+    if (iter.referent() == NULL) {
+      // Reference has been cleared since discovery; only possible if
+      // discovery is not atomic (checked by load_ptrs).  Remove
+      // reference from list.
+      log_dropped_ref(iter, "cleared");
+      iter.remove();
+      iter.move_to_next();
+    } else if (iter.is_referent_alive()) {
       // The referent is reachable after all.
-      // Remove Reference object from list.
+      // Remove reference from list.
+      log_dropped_ref(iter, "reachable");
       iter.remove();
-      // Update the referent pointer as necessary: Note that this
+      // Update the referent pointer as necessary.  Note that this
       // should not entail any recursive marking because the
       // referent must already have been traversed.
       iter.make_referent_alive();
@@ -413,45 +407,6 @@
   )
 }
 
-void
-ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList&    refs_list,
-                                                  BoolObjectClosure* is_alive,
-                                                  OopClosure*        keep_alive,
-                                                  VoidClosure*       complete_gc) {
-  assert(!discovery_is_atomic(), "Error");
-  DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
-  while (iter.has_next()) {
-    iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
-    HeapWord* next_addr = java_lang_ref_Reference::next_addr_raw(iter.obj());
-    oop next = java_lang_ref_Reference::next(iter.obj());
-    if ((iter.referent() == NULL || iter.is_referent_alive() ||
-         next != NULL)) {
-      assert(oopDesc::is_oop_or_null(next), "Expected an oop or NULL for next field at " PTR_FORMAT, p2i(next));
-      // Remove Reference object from list
-      iter.remove();
-      // Trace the cohorts
-      iter.make_referent_alive();
-      if (UseCompressedOops) {
-        keep_alive->do_oop((narrowOop*)next_addr);
-      } else {
-        keep_alive->do_oop((oop*)next_addr);
-      }
-      iter.move_to_next();
-    } else {
-      iter.next();
-    }
-  }
-  // Now close the newly reachable set
-  complete_gc->do_void();
-  NOT_PRODUCT(
-    if (iter.processed() > 0) {
-      log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " active Refs out of " SIZE_FORMAT
-        " Refs in discovered list " INTPTR_FORMAT,
-        iter.removed(), iter.processed(), p2i(&refs_list));
-    }
-  )
-}
-
 void ReferenceProcessor::process_phase3(DiscoveredList&    refs_list,
                                         bool               clear_referent,
                                         BoolObjectClosure* is_alive,
@@ -465,8 +420,12 @@
       // NULL out referent pointer
       iter.clear_referent();
     } else {
-      // keep the referent around
+      // Current reference is a FinalReference; that's the only kind we
+      // don't clear the referent, instead keeping it for calling finalize.
       iter.make_referent_alive();
+      // Self-loop next, to mark it not active.
+      assert(java_lang_ref_Reference::next(iter.obj()) == NULL, "enqueued FinalReference");
+      java_lang_ref_Reference::set_next_raw(iter.obj(), iter.obj());
     }
     iter.enqueue();
     log_develop_trace(gc, ref)("Adding %sreference (" INTPTR_FORMAT ": %s) as pending",
@@ -913,9 +872,9 @@
   if (!_discovering_refs || !RegisterReferences) {
     return false;
   }
-  // We only discover active references.
-  oop next = java_lang_ref_Reference::next(obj);
-  if (next != NULL) {   // Ref is no longer active
+
+  if ((rt == REF_FINAL) && (java_lang_ref_Reference::next(obj) != NULL)) {
+    // Don't rediscover non-active FinalReferences.
     return false;
   }
 
@@ -1121,24 +1080,15 @@
       return true;
     }
     iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
-    oop obj = iter.obj();
-    oop next = java_lang_ref_Reference::next(obj);
-    if (iter.referent() == NULL || iter.is_referent_alive() || next != NULL) {
-      // The referent has been cleared, or is alive, or the Reference is not
-      // active; we need to trace and mark its cohort.
+    if (iter.referent() == NULL || iter.is_referent_alive()) {
+      // The referent has been cleared, or is alive; we need to trace
+      // and mark its cohort.
       log_develop_trace(gc, ref)("Precleaning Reference (" INTPTR_FORMAT ": %s)",
                                  p2i(iter.obj()), iter.obj()->klass()->internal_name());
       // Remove Reference object from list
       iter.remove();
       // Keep alive its cohort.
       iter.make_referent_alive();
-      if (UseCompressedOops) {
-        narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr_raw(obj);
-        keep_alive->do_oop(next_addr);
-      } else {
-        oop* next_addr = (oop*)java_lang_ref_Reference::next_addr_raw(obj);
-        keep_alive->do_oop(next_addr);
-      }
       iter.move_to_next();
     } else {
       iter.next();