< prev index next >

src/hotspot/share/gc/shared/referenceProcessor.cpp

Print this page
rev 49944 : imported patch 8201492-properly-implement-non-contiguous-reference-processing
rev 49945 : imported patch 8201492-stefanj-review
rev 49949 : imported patch 8202021-cleanup-referenceprocessor
rev 49950 : imported patch 8202021-stefanj-review
rev 49951 : imported patch 8202017-reference-processor-remove-enqueue
rev 49952 : imported patch 8202017-kim-review
rev 49953 : imported patch 8201491-precleaning

@@ -592,23 +592,37 @@
   }
 private:
   bool _clear_referent;
 };
 
+void ReferenceProcessor::log_reflist(const char* prefix, DiscoveredList list[], uint num_active_queues) {
+  LogTarget(Trace, gc, ref) lt;
+
+  if (!lt.is_enabled()) {
+    return;
+  }
+
+  size_t total = 0;
+
+  LogStream ls(lt);
+  ls.print("%s", prefix);
+  for (uint i = 0; i < num_active_queues; i++) {
+    ls.print(SIZE_FORMAT " ", list[i].length());
+    total += list[i].length();
+  }
+  ls.print_cr("(" SIZE_FORMAT ")", total);
+}
+
 #ifndef PRODUCT
-void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], uint active_length, size_t total_refs) {
+void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], uint num_active_queues) {
   if (!log_is_enabled(Trace, gc, ref)) {
     return;
   }
 
-  stringStream st;
-  for (uint i = 0; i < active_length; ++i) {
-    st.print(SIZE_FORMAT " ", ref_lists[i].length());
-  }
-  log_develop_trace(gc, ref)("%s= " SIZE_FORMAT, st.as_string(), total_refs);
+  log_reflist("", ref_lists, num_active_queues);
 #ifdef ASSERT
-  for (uint i = active_length; i < _max_num_queues; i++) {
+  for (uint i = num_active_queues; i < _max_num_queues; i++) {
     assert(ref_lists[i].length() == 0, SIZE_FORMAT " unexpected References in %u",
            ref_lists[i].length(), i);
   }
 #endif
 }

@@ -627,14 +641,15 @@
 {
   // calculate total length
   size_t total_refs = 0;
   log_develop_trace(gc, ref)("Balance ref_lists ");
 
+  log_reflist_counts(ref_lists, _max_num_queues);
+
   for (uint i = 0; i < _max_num_queues; ++i) {
     total_refs += ref_lists[i].length();
   }
-  log_reflist_counts(ref_lists, _max_num_queues, total_refs);
   size_t avg_refs = total_refs / _num_queues + 1;
   uint to_idx = 0;
   for (uint from_idx = 0; from_idx < _max_num_queues; from_idx++) {
     bool move_all = false;
     if (from_idx >= _num_queues) {

@@ -691,15 +706,15 @@
         to_idx = (to_idx + 1) % _num_queues;
       }
     }
   }
 #ifdef ASSERT
+  log_reflist_counts(ref_lists, _num_queues);
   size_t balanced_total_refs = 0;
   for (uint i = 0; i < _num_queues; ++i) {
     balanced_total_refs += ref_lists[i].length();
   }
-  log_reflist_counts(ref_lists, _num_queues, balanced_total_refs);
   assert(total_refs == balanced_total_refs, "Balancing was incomplete");
 #endif
 }
 
 void ReferenceProcessor::process_discovered_reflist(

@@ -1009,67 +1024,83 @@
     }
   }
   return false;
 }
 
-// Preclean the discovered references by removing those
-// whose referents are alive, and by marking from those that
-// are not active. These lists can be handled here
-// in any order and, indeed, concurrently.
-void ReferenceProcessor::preclean_discovered_references(
-  BoolObjectClosure* is_alive,
+void ReferenceProcessor::preclean_discovered_references(BoolObjectClosure* is_alive,
   OopClosure* keep_alive,
   VoidClosure* complete_gc,
   YieldClosure* yield,
   GCTimer* gc_timer) {
+  // These lists can be handled here in any order and, indeed, concurrently.
 
   // Soft references
   {
     GCTraceTime(Debug, gc, ref) tm("Preclean SoftReferences", gc_timer);
+    log_reflist("SoftRef before: ", _discoveredSoftRefs, _max_num_queues);
     for (uint i = 0; i < _max_num_queues; i++) {
       if (yield->should_return()) {
         return;
       }
-      preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
-                                  keep_alive, complete_gc, yield);
+      if (preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
+                                      keep_alive, complete_gc, yield)) {
+        log_reflist("SoftRef abort: ", _discoveredSoftRefs, _max_num_queues);
+        return;
+      }
     }
+    log_reflist("SoftRef after: ", _discoveredSoftRefs, _max_num_queues);
   }
 
   // Weak references
   {
     GCTraceTime(Debug, gc, ref) tm("Preclean WeakReferences", gc_timer);
+    log_reflist("WeakRef before: ", _discoveredWeakRefs, _max_num_queues);
     for (uint i = 0; i < _max_num_queues; i++) {
       if (yield->should_return()) {
         return;
       }
-      preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
-                                  keep_alive, complete_gc, yield);
+      if (preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
+                                      keep_alive, complete_gc, yield)) {
+        log_reflist("WeakRef abort: ", _discoveredWeakRefs, _max_num_queues);
+        return;
+      }
     }
+    log_reflist("WeakRef after: ", _discoveredWeakRefs, _max_num_queues);
   }
 
   // Final references
   {
     GCTraceTime(Debug, gc, ref) tm("Preclean FinalReferences", gc_timer);
+    log_reflist("FinalRef before: ", _discoveredFinalRefs, _max_num_queues);
     for (uint i = 0; i < _max_num_queues; i++) {
       if (yield->should_return()) {
         return;
       }
-      preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
-                                  keep_alive, complete_gc, yield);
+      if (preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
+                                      keep_alive, complete_gc, yield)) {
+        log_reflist("FinalRef abort: ", _discoveredFinalRefs, _max_num_queues);
+        return;
+      }
     }
+    log_reflist("FinalRef after: ", _discoveredFinalRefs, _max_num_queues);
   }
 
   // Phantom references
   {
     GCTraceTime(Debug, gc, ref) tm("Preclean PhantomReferences", gc_timer);
+    log_reflist("PhantomRef before: ", _discoveredPhantomRefs, _max_num_queues);
     for (uint i = 0; i < _max_num_queues; i++) {
       if (yield->should_return()) {
         return;
       }
-      preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
-                                  keep_alive, complete_gc, yield);
+      if (preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
+                                      keep_alive, complete_gc, yield)) {
+        log_reflist("PhantomRef abort: ", _discoveredPhantomRefs, _max_num_queues);
+        return;
+      }
     }
+    log_reflist("PhantomRef after: ", _discoveredPhantomRefs, _max_num_queues);
   }
 }
 
 // Walk the given discovered ref list, and remove all reference objects
 // whose referents are still alive, whose referents are NULL or which

@@ -1077,23 +1108,24 @@
 // thus precleaning the ref lists (which happens single-threaded today),
 // we do not disable refs discovery to honor the correct semantics of
 // java.lang.Reference. As a result, we need to be careful below
 // that ref removal steps interleave safely with ref discovery steps
 // (in this thread).
-void
-ReferenceProcessor::preclean_discovered_reflist(DiscoveredList&    refs_list,
+bool ReferenceProcessor::preclean_discovered_reflist(DiscoveredList&    refs_list,
                                                 BoolObjectClosure* is_alive,
                                                 OopClosure*        keep_alive,
                                                 VoidClosure*       complete_gc,
                                                 YieldClosure*      yield) {
   DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
   while (iter.has_next()) {
+    if (yield->should_return_fine_grain()) {
+      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) {
+    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.
       log_develop_trace(gc, ref)("Precleaning Reference (" INTPTR_FORMAT ": %s)",
                                  p2i(iter.obj()), iter.obj()->klass()->internal_name());
       // Remove Reference object from list

@@ -1119,10 +1151,11 @@
     if (iter.processed() > 0) {
       log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT,
         iter.removed(), iter.processed(), p2i(&refs_list));
     }
   )
+  return false;
 }
 
 const char* ReferenceProcessor::list_name(uint i) {
    assert(i <= _max_num_queues * number_of_subclasses_of_ref(),
           "Out of bounds index");
< prev index next >