< prev index next >

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

Print this page
rev 13070 : [mq]: webrev.0a

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -125,10 +125,12 @@
   for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
     _discovered_refs[i].set_head(NULL);
     _discovered_refs[i].set_length(0);
   }
 
+  _phase_times = new ReferenceProcessorPhaseTimes(_num_q, _processing_is_mt);
+
   setup_policy(false /* default soft ref policy */);
 }
 
 #ifndef PRODUCT
 void ReferenceProcessor::verify_no_references_recorded() {

@@ -206,44 +208,43 @@
   // here so that we use the new value during processing of the
   // discovered soft refs.
 
   _soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock();
 
-  ReferenceProcessorStats stats(
-      total_count(_discoveredSoftRefs),
+  ReferenceProcessorStats stats(total_count(_discoveredSoftRefs),
       total_count(_discoveredWeakRefs),
       total_count(_discoveredFinalRefs),
       total_count(_discoveredPhantomRefs));
 
   // Soft references
   {
-    GCTraceTime(Debug, gc, ref) tt("SoftReference", gc_timer);
+    RefProcPhaseTimesLogger tt("SoftReference", phase_times(), _discoveredSoftRefs, gc_timer);
     process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
-                               is_alive, keep_alive, complete_gc, task_executor);
+                               is_alive, keep_alive, complete_gc, task_executor, gc_timer);
   }
 
   update_soft_ref_master_clock();
 
   // Weak references
   {
-    GCTraceTime(Debug, gc, ref) tt("WeakReference", gc_timer);
+    RefProcPhaseTimesLogger tt("WeakReference", phase_times(), _discoveredWeakRefs, gc_timer);
     process_discovered_reflist(_discoveredWeakRefs, NULL, true,
-                               is_alive, keep_alive, complete_gc, task_executor);
+                               is_alive, keep_alive, complete_gc, task_executor, gc_timer);
   }
 
   // Final references
   {
-    GCTraceTime(Debug, gc, ref) tt("FinalReference", gc_timer);
+    RefProcPhaseTimesLogger tt("FinalReference", phase_times(), _discoveredFinalRefs, gc_timer);
     process_discovered_reflist(_discoveredFinalRefs, NULL, false,
-                               is_alive, keep_alive, complete_gc, task_executor);
+                               is_alive, keep_alive, complete_gc, task_executor, gc_timer);
   }
 
   // Phantom references
   {
-    GCTraceTime(Debug, gc, ref) tt("PhantomReference", gc_timer);
+    RefProcPhaseTimesLogger tt("PhantomReference", phase_times(), _discoveredPhantomRefs, gc_timer);
     process_discovered_reflist(_discoveredPhantomRefs, NULL, true,
-                               is_alive, keep_alive, complete_gc, task_executor);
+                               is_alive, keep_alive, complete_gc, task_executor, gc_timer);
   }
 
   // Weak global JNI references. It would make more sense (semantically) to
   // traverse these simultaneously with the regular weak references above, but
   // that is not how the JDK1.2 specification is. See #4126360. Native code can

@@ -255,12 +256,10 @@
       task_executor->set_single_threaded_mode();
     }
     process_phaseJNI(is_alive, keep_alive, complete_gc);
   }
 
-  log_debug(gc, ref)("Ref Counts: Soft: " SIZE_FORMAT " Weak: " SIZE_FORMAT " Final: " SIZE_FORMAT " Phantom: " SIZE_FORMAT,
-                     stats.soft_count(), stats.weak_count(), stats.final_count(), stats.phantom_count());
   log_develop_trace(gc, ref)("JNI Weak Reference count: " SIZE_FORMAT, count_jni_refs());
 
   return stats;
 }
 

@@ -287,14 +286,14 @@
                                           VoidClosure*       complete_gc) {
   JNIHandles::weak_oops_do(is_alive, keep_alive);
   complete_gc->do_void();
 }
 
-void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) {
+void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor, GCTimer* gc_timer) {
   // Enqueue references that are not made active again, and
   // clear the decks for the next collection (cycle).
-  enqueue_discovered_reflists(task_executor);
+  enqueue_discovered_reflists(task_executor, gc_timer);
 
   // Stop treating discovered references specially.
   disable_discovery();
 }
 

@@ -348,10 +347,12 @@
                      int                 n_queues)
     : EnqueueTask(ref_processor, discovered_refs, n_queues)
   { }
 
   virtual void work(unsigned int work_id) {
+    RefProcWorkerTimeTracker tt(_ref_processor.phase_times()->worker_time_sec(ReferenceProcessorPhaseTimes::RefEnqueue), work_id);
+
     assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds");
     // Simplest first cut: static partitioning.
     int index = work_id;
     // The increment on "index" must correspond to the maximum number of queues
     // (n_queues) with which that ReferenceProcessor was created.  That

@@ -367,11 +368,19 @@
     }
   }
 };
 
 // Enqueue references that are not made active again
-void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor) {
+void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor, GCTimer* gc_timer) {
+
+  ReferenceProcessorStats stats(total_count(_discoveredSoftRefs),
+                                total_count(_discoveredWeakRefs),
+                                total_count(_discoveredFinalRefs),
+                                total_count(_discoveredPhantomRefs));
+
+  RefProcEnqueueTimeLogger tt(phase_times(), stats, gc_timer);
+
   if (_processing_is_mt && task_executor != NULL) {
     // Parallel code
     RefProcEnqueueTask tsk(*this, _discovered_refs, _max_num_q);
     task_executor->execute(tsk);
   } else {

@@ -467,11 +476,11 @@
   }
   // Close the reachable set
   complete_gc->do_void();
   log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " dead Refs out of " SIZE_FORMAT " discovered Refs by policy, from list " INTPTR_FORMAT,
                              iter.removed(), iter.processed(), p2i(&refs_list));
-    }
+}
 
 // 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,

@@ -609,10 +618,12 @@
   { }
   virtual void work(unsigned int i, BoolObjectClosure& is_alive,
                     OopClosure& keep_alive,
                     VoidClosure& complete_gc)
   {
+    RefProcWorkerTimeTracker tt(_ref_processor.phase_times()->worker_time_sec(ReferenceProcessorPhaseTimes::RefPhase1), i);
+
     _ref_processor.process_phase1(_refs_lists[i], _policy,
                                   &is_alive, &keep_alive, &complete_gc);
   }
 private:
   ReferencePolicy* _policy;

@@ -627,10 +638,12 @@
   { }
   virtual void work(unsigned int i, BoolObjectClosure& is_alive,
                     OopClosure& keep_alive,
                     VoidClosure& complete_gc)
   {
+    RefProcWorkerTimeTracker tt(_ref_processor.phase_times()->worker_time_sec(ReferenceProcessorPhaseTimes::RefPhase2), i);
+
     _ref_processor.process_phase2(_refs_lists[i],
                                   &is_alive, &keep_alive, &complete_gc);
   }
 };
 

@@ -645,10 +658,12 @@
   { }
   virtual void work(unsigned int i, BoolObjectClosure& is_alive,
                     OopClosure& keep_alive,
                     VoidClosure& complete_gc)
   {
+    RefProcWorkerTimeTracker tt(_ref_processor.phase_times()->worker_time_sec(ReferenceProcessorPhaseTimes::RefPhase3), i);
+
     _ref_processor.process_phase3(_refs_lists[i], _clear_referent,
                                   &is_alive, &keep_alive, &complete_gc);
   }
 private:
   bool _clear_referent;

@@ -774,32 +789,39 @@
   ReferencePolicy*             policy,
   bool                         clear_referent,
   BoolObjectClosure*           is_alive,
   OopClosure*                  keep_alive,
   VoidClosure*                 complete_gc,
-  AbstractRefProcTaskExecutor* task_executor)
+  AbstractRefProcTaskExecutor* task_executor,
+  GCTimer*                     gc_timer)
 {
   bool mt_processing = task_executor != NULL && _processing_is_mt;
+
+  phase_times()->set_processing_is_mt(mt_processing);
+
   // If discovery used MT and a dynamic number of GC threads, then
   // the queues must be balanced for correctness if fewer than the
   // maximum number of queues were used.  The number of queue used
   // during discovery may be different than the number to be used
   // for processing so don't depend of _num_q < _max_num_q as part
   // of the test.
   bool must_balance = _discovery_is_mt;
 
   if ((mt_processing && ParallelRefProcBalancingEnabled) ||
       must_balance) {
+    RefProcBalanceQueuesTimeTracker tt(phase_times(), gc_timer);
     balance_queues(refs_lists);
   }
 
   // Phase 1 (soft refs only):
   // . Traverse the list and remove any SoftReferences whose
   //   referents are not alive, but that should be kept alive for
   //   policy reasons. Keep alive the transitive closure of all
   //   such referents.
   if (policy != NULL) {
+    RefProcPhaseTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase1, phase_times(), gc_timer);
+
     if (mt_processing) {
       RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);
       task_executor->execute(phase1);
     } else {
       for (uint i = 0; i < _max_num_q; i++) {

@@ -812,30 +834,38 @@
            "Policy must be specified for soft references.");
   }
 
   // Phase 2:
   // . Traverse the list and remove any refs whose referents are alive.
+  {
+    RefProcPhaseTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase2, phase_times(), gc_timer);
+
   if (mt_processing) {
     RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);
     task_executor->execute(phase2);
   } else {
     for (uint i = 0; i < _max_num_q; i++) {
       process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
     }
   }
+  }
 
   // Phase 3:
   // . Traverse the list and process referents as appropriate.
+  {
+    RefProcPhaseTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase3, phase_times(), gc_timer);
+
   if (mt_processing) {
     RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);
     task_executor->execute(phase3);
   } else {
     for (uint i = 0; i < _max_num_q; i++) {
       process_phase3(refs_lists[i], clear_referent,
                      is_alive, keep_alive, complete_gc);
     }
   }
+  }
 }
 
 inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) {
   uint id = 0;
   // Determine the queue index to use for this object.

@@ -1194,6 +1224,5 @@
      case 3: return "PhantomRef";
    }
    ShouldNotReachHere();
    return NULL;
 }
-
< prev index next >