hotspot/src/share/vm/runtime/sweeper.cpp
changeset 27917 c5937f7b4e8b
parent 27420 04e6f914cce1
child 28163 322d55d167be
--- a/hotspot/src/share/vm/runtime/sweeper.cpp	Mon Dec 01 22:41:16 2014 +0300
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp	Tue Dec 02 12:36:03 2014 +0300
@@ -142,9 +142,6 @@
 long     NMethodSweeper::_time_counter                 = 0;    // Virtual time used to periodically invoke sweeper
 long     NMethodSweeper::_last_sweep                   = 0;    // Value of _time_counter when the last sweep happened
 int      NMethodSweeper::_seen                         = 0;    // Nof. nmethod we have currently processed in current pass of CodeCache
-int      NMethodSweeper::_flushed_count                = 0;    // Nof. nmethods flushed in current sweep
-int      NMethodSweeper::_zombified_count              = 0;    // Nof. nmethods made zombie in current sweep
-int      NMethodSweeper::_marked_for_reclamation_count = 0;    // Nof. nmethods marked for reclaim in current sweep
 
 volatile bool NMethodSweeper::_should_sweep            = true; // Indicates if we should invoke the sweeper
 volatile int  NMethodSweeper::_bytes_changed           = 0;    // Counts the total nmethod size if the nmethod changed from:
@@ -161,6 +158,7 @@
 Tickspan NMethodSweeper::_peak_sweep_time;                     // Peak time for a full sweep
 Tickspan NMethodSweeper::_peak_sweep_fraction_time;            // Peak time sweeping one fraction
 
+Monitor* NMethodSweeper::_stat_lock = new Monitor(Mutex::special, "Sweeper::Statistics", true);
 
 class MarkActivationClosure: public CodeBlobClosure {
 public:
@@ -370,9 +368,10 @@
   ResourceMark rm;
   Ticks sweep_start_counter = Ticks::now();
 
-  _flushed_count                = 0;
-  _zombified_count              = 0;
-  _marked_for_reclamation_count = 0;
+  int flushed_count                = 0;
+  int zombified_count              = 0;
+  int marked_for_reclamation_count = 0;
+  int flushed_c2_count     = 0;
 
   if (PrintMethodFlushing && Verbose) {
     tty->print_cr("### Sweep at %d out of %d", _seen, CodeCache::nof_nmethods());
@@ -386,10 +385,8 @@
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
-    // The last invocation iterates until there are no more nmethods
     while (!_current.end()) {
       swept_count++;
-      handle_safepoint_request();
       // Since we will give up the CodeCache_lock, always skip ahead
       // to the next nmethod.  Other blobs can be deleted by other
       // threads but nmethods are only reclaimed by the sweeper.
@@ -399,9 +396,32 @@
       // Now ready to process nmethod and give up CodeCache_lock
       {
         MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-        freed_memory += process_nmethod(nm);
+        int size = nm->total_size();
+        bool is_c2_method = nm->is_compiled_by_c2();
+
+        MethodStateChange type = process_nmethod(nm);
+        switch (type) {
+          case Flushed:
+            freed_memory += size;
+            ++flushed_count;
+            if (is_c2_method) {
+              ++flushed_c2_count;
+            }
+            break;
+          case MarkedForReclamation:
+            ++marked_for_reclamation_count;
+            break;
+          case MadeZombie:
+            ++zombified_count;
+            break;
+          case None:
+            break;
+          default:
+           ShouldNotReachHere();
+        }
       }
       _seen++;
+      handle_safepoint_request();
     }
   }
 
@@ -409,21 +429,25 @@
 
   const Ticks sweep_end_counter = Ticks::now();
   const Tickspan sweep_time = sweep_end_counter - sweep_start_counter;
-  _total_time_sweeping  += sweep_time;
-  _total_time_this_sweep += sweep_time;
-  _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time);
-  _total_flushed_size += freed_memory;
-  _total_nof_methods_reclaimed += _flushed_count;
-
+  {
+    MutexLockerEx mu(_stat_lock, Mutex::_no_safepoint_check_flag);
+    _total_time_sweeping  += sweep_time;
+    _total_time_this_sweep += sweep_time;
+    _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time);
+    _total_flushed_size += freed_memory;
+    _total_nof_methods_reclaimed += flushed_count;
+    _total_nof_c2_methods_reclaimed += flushed_c2_count;
+    _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep);
+  }
   EventSweepCodeCache event(UNTIMED);
   if (event.should_commit()) {
     event.set_starttime(sweep_start_counter);
     event.set_endtime(sweep_end_counter);
     event.set_sweepIndex(_traversals);
     event.set_sweptCount(swept_count);
-    event.set_flushedCount(_flushed_count);
-    event.set_markedCount(_marked_for_reclamation_count);
-    event.set_zombifiedCount(_zombified_count);
+    event.set_flushedCount(flushed_count);
+    event.set_markedCount(marked_for_reclamation_count);
+    event.set_zombifiedCount(zombified_count);
     event.commit();
   }
 
@@ -433,7 +457,6 @@
   }
 #endif
 
-  _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep);
   log_sweep("finished");
 
   // Sweeper is the only case where memory is released, check here if it
@@ -511,10 +534,11 @@
   nm->flush();
 }
 
-int NMethodSweeper::process_nmethod(nmethod* nm) {
+NMethodSweeper::MethodStateChange NMethodSweeper::process_nmethod(nmethod* nm) {
+  assert(nm != NULL, "sanity");
   assert(!CodeCache_lock->owned_by_self(), "just checking");
 
-  int freed_memory = 0;
+  MethodStateChange result = None;
   // Make sure this nmethod doesn't get unloaded during the scan,
   // since safepoints may happen during acquired below locks.
   NMethodMarker nmm(nm);
@@ -529,7 +553,7 @@
       nm->cleanup_inline_caches();
       SWEEP(nm);
     }
-    return freed_memory;
+    return result;
   }
 
   if (nm->is_zombie()) {
@@ -541,12 +565,9 @@
       if (PrintMethodFlushing && Verbose) {
         tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm);
       }
-      freed_memory = nm->total_size();
-      if (nm->is_compiled_by_c2()) {
-        _total_nof_c2_methods_reclaimed++;
-      }
       release_nmethod(nm);
-      _flushed_count++;
+      assert(result == None, "sanity");
+      result = Flushed;
     } else {
       if (PrintMethodFlushing && Verbose) {
         tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm);
@@ -554,8 +575,9 @@
       nm->mark_for_reclamation();
       // Keep track of code cache state change
       _bytes_changed += nm->total_size();
-      _marked_for_reclamation_count++;
       SWEEP(nm);
+      assert(result == None, "sanity");
+      result = MarkedForReclamation;
     }
   } else if (nm->is_not_entrant()) {
     // If there are no current activations of this method on the
@@ -576,8 +598,9 @@
         }
         // Code cache state change is tracked in make_zombie()
         nm->make_zombie();
-        _zombified_count++;
         SWEEP(nm);
+        assert(result == None, "sanity");
+        result = MadeZombie;
       }
       assert(nm->is_zombie(), "nmethod must be zombie");
     } else {
@@ -594,17 +617,15 @@
     if (nm->is_osr_method()) {
       SWEEP(nm);
       // No inline caches will ever point to osr methods, so we can just remove it
-      freed_memory = nm->total_size();
-      if (nm->is_compiled_by_c2()) {
-        _total_nof_c2_methods_reclaimed++;
-      }
       release_nmethod(nm);
-      _flushed_count++;
+      assert(result == None, "sanity");
+      result = Flushed;
     } else {
       // Code cache state change is tracked in make_zombie()
       nm->make_zombie();
-      _zombified_count++;
       SWEEP(nm);
+      assert(result == None, "sanity");
+      result = MadeZombie;
     }
   } else {
     possibly_flush(nm);
@@ -613,7 +634,7 @@
     nm->cleanup_inline_caches();
     SWEEP(nm);
   }
-  return freed_memory;
+  return result;
 }