hotspot/src/share/vm/runtime/sweeper.cpp
changeset 9942 2e86734ba620
parent 9138 35e4b04eadf4
child 11789 2ff80dcfc1cf
equal deleted inserted replaced
9941:f2365fbd62f4 9942:2e86734ba620
    35 #include "runtime/sweeper.hpp"
    35 #include "runtime/sweeper.hpp"
    36 #include "runtime/vm_operations.hpp"
    36 #include "runtime/vm_operations.hpp"
    37 #include "utilities/events.hpp"
    37 #include "utilities/events.hpp"
    38 #include "utilities/xmlstream.hpp"
    38 #include "utilities/xmlstream.hpp"
    39 
    39 
       
    40 #ifdef ASSERT
       
    41 
       
    42 #define SWEEP(nm) record_sweep(nm, __LINE__)
       
    43 // Sweeper logging code
       
    44 class SweeperRecord {
       
    45  public:
       
    46   int traversal;
       
    47   int invocation;
       
    48   int compile_id;
       
    49   long traversal_mark;
       
    50   int state;
       
    51   const char* kind;
       
    52   address vep;
       
    53   address uep;
       
    54   int line;
       
    55 
       
    56   void print() {
       
    57       tty->print_cr("traversal = %d invocation = %d compile_id = %d %s uep = " PTR_FORMAT " vep = "
       
    58                     PTR_FORMAT " state = %d traversal_mark %d line = %d",
       
    59                     traversal,
       
    60                     invocation,
       
    61                     compile_id,
       
    62                     kind == NULL ? "" : kind,
       
    63                     uep,
       
    64                     vep,
       
    65                     state,
       
    66                     traversal_mark,
       
    67                     line);
       
    68   }
       
    69 };
       
    70 
       
    71 static int _sweep_index = 0;
       
    72 static SweeperRecord* _records = NULL;
       
    73 
       
    74 void NMethodSweeper::report_events(int id, address entry) {
       
    75   if (_records != NULL) {
       
    76     for (int i = _sweep_index; i < SweeperLogEntries; i++) {
       
    77       if (_records[i].uep == entry ||
       
    78           _records[i].vep == entry ||
       
    79           _records[i].compile_id == id) {
       
    80         _records[i].print();
       
    81       }
       
    82     }
       
    83     for (int i = 0; i < _sweep_index; i++) {
       
    84       if (_records[i].uep == entry ||
       
    85           _records[i].vep == entry ||
       
    86           _records[i].compile_id == id) {
       
    87         _records[i].print();
       
    88       }
       
    89     }
       
    90   }
       
    91 }
       
    92 
       
    93 void NMethodSweeper::report_events() {
       
    94   if (_records != NULL) {
       
    95     for (int i = _sweep_index; i < SweeperLogEntries; i++) {
       
    96       // skip empty records
       
    97       if (_records[i].vep == NULL) continue;
       
    98       _records[i].print();
       
    99     }
       
   100     for (int i = 0; i < _sweep_index; i++) {
       
   101       // skip empty records
       
   102       if (_records[i].vep == NULL) continue;
       
   103       _records[i].print();
       
   104     }
       
   105   }
       
   106 }
       
   107 
       
   108 void NMethodSweeper::record_sweep(nmethod* nm, int line) {
       
   109   if (_records != NULL) {
       
   110     _records[_sweep_index].traversal = _traversals;
       
   111     _records[_sweep_index].traversal_mark = nm->_stack_traversal_mark;
       
   112     _records[_sweep_index].invocation = _invocations;
       
   113     _records[_sweep_index].compile_id = nm->compile_id();
       
   114     _records[_sweep_index].kind = nm->compile_kind();
       
   115     _records[_sweep_index].state = nm->_state;
       
   116     _records[_sweep_index].vep = nm->verified_entry_point();
       
   117     _records[_sweep_index].uep = nm->entry_point();
       
   118     _records[_sweep_index].line = line;
       
   119 
       
   120     _sweep_index = (_sweep_index + 1) % SweeperLogEntries;
       
   121   }
       
   122 }
       
   123 #else
       
   124 #define SWEEP(nm)
       
   125 #endif
       
   126 
       
   127 
    40 long      NMethodSweeper::_traversals = 0;   // No. of stack traversals performed
   128 long      NMethodSweeper::_traversals = 0;   // No. of stack traversals performed
    41 nmethod*  NMethodSweeper::_current = NULL;   // Current nmethod
   129 nmethod*  NMethodSweeper::_current = NULL;   // Current nmethod
    42 int       NMethodSweeper::_seen = 0 ;        // No. of nmethods we have currently processed in current pass of CodeCache
   130 int       NMethodSweeper::_seen = 0 ;        // No. of nmethods we have currently processed in current pass of CodeCache
    43 
   131 
    44 volatile int NMethodSweeper::_invocations = 0;   // No. of invocations left until we are completed with this pass
   132 volatile int NMethodSweeper::_invocations = 0;   // No. of invocations left until we are completed with this pass
   135     // Only one thread at a time will sweep
   223     // Only one thread at a time will sweep
   136     jint old = Atomic::cmpxchg( 1, &_sweep_started, 0 );
   224     jint old = Atomic::cmpxchg( 1, &_sweep_started, 0 );
   137     if (old != 0) {
   225     if (old != 0) {
   138       return;
   226       return;
   139     }
   227     }
       
   228 #ifdef ASSERT
       
   229     if (LogSweeper && _records == NULL) {
       
   230       // Create the ring buffer for the logging code
       
   231       _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries);
       
   232       memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries);
       
   233     }
       
   234 #endif
   140     if (_invocations > 0) {
   235     if (_invocations > 0) {
   141       sweep_code_cache();
   236       sweep_code_cache();
   142       _invocations--;
   237       _invocations--;
   143     }
   238     }
   144     _sweep_started = 0;
   239     _sweep_started = 0;
   211   if (_invocations == 1) {
   306   if (_invocations == 1) {
   212     log_sweep("finished");
   307     log_sweep("finished");
   213   }
   308   }
   214 }
   309 }
   215 
   310 
       
   311 class NMethodMarker: public StackObj {
       
   312  private:
       
   313   CompilerThread* _thread;
       
   314  public:
       
   315   NMethodMarker(nmethod* nm) {
       
   316     _thread = CompilerThread::current();
       
   317     _thread->set_scanned_nmethod(nm);
       
   318   }
       
   319   ~NMethodMarker() {
       
   320     _thread->set_scanned_nmethod(NULL);
       
   321   }
       
   322 };
       
   323 
   216 
   324 
   217 void NMethodSweeper::process_nmethod(nmethod *nm) {
   325 void NMethodSweeper::process_nmethod(nmethod *nm) {
   218   assert(!CodeCache_lock->owned_by_self(), "just checking");
   326   assert(!CodeCache_lock->owned_by_self(), "just checking");
       
   327 
       
   328   // Make sure this nmethod doesn't get unloaded during the scan,
       
   329   // since the locks acquired below might safepoint.
       
   330   NMethodMarker nmm(nm);
       
   331 
       
   332   SWEEP(nm);
   219 
   333 
   220   // Skip methods that are currently referenced by the VM
   334   // Skip methods that are currently referenced by the VM
   221   if (nm->is_locked_by_vm()) {
   335   if (nm->is_locked_by_vm()) {
   222     // But still remember to clean-up inline caches for alive nmethods
   336     // But still remember to clean-up inline caches for alive nmethods
   223     if (nm->is_alive()) {
   337     if (nm->is_alive()) {
   224       // Clean-up all inline caches that points to zombie/non-reentrant methods
   338       // Clean-up all inline caches that points to zombie/non-reentrant methods
   225       MutexLocker cl(CompiledIC_lock);
   339       MutexLocker cl(CompiledIC_lock);
   226       nm->cleanup_inline_caches();
   340       nm->cleanup_inline_caches();
       
   341       SWEEP(nm);
   227     } else {
   342     } else {
   228       _locked_seen++;
   343       _locked_seen++;
       
   344       SWEEP(nm);
   229     }
   345     }
   230     return;
   346     return;
   231   }
   347   }
   232 
   348 
   233   if (nm->is_zombie()) {
   349   if (nm->is_zombie()) {
   245       if (PrintMethodFlushing && Verbose) {
   361       if (PrintMethodFlushing && Verbose) {
   246         tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm);
   362         tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm);
   247       }
   363       }
   248       nm->mark_for_reclamation();
   364       nm->mark_for_reclamation();
   249       _rescan = true;
   365       _rescan = true;
       
   366       SWEEP(nm);
   250     }
   367     }
   251   } else if (nm->is_not_entrant()) {
   368   } else if (nm->is_not_entrant()) {
   252     // If there is no current activations of this method on the
   369     // If there is no current activations of this method on the
   253     // stack we can safely convert it to a zombie method
   370     // stack we can safely convert it to a zombie method
   254     if (nm->can_not_entrant_be_converted()) {
   371     if (nm->can_not_entrant_be_converted()) {
   255       if (PrintMethodFlushing && Verbose) {
   372       if (PrintMethodFlushing && Verbose) {
   256         tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm);
   373         tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm);
   257       }
   374       }
   258       nm->make_zombie();
   375       nm->make_zombie();
   259       _rescan = true;
   376       _rescan = true;
       
   377       SWEEP(nm);
   260     } else {
   378     } else {
   261       // Still alive, clean up its inline caches
   379       // Still alive, clean up its inline caches
   262       MutexLocker cl(CompiledIC_lock);
   380       MutexLocker cl(CompiledIC_lock);
   263       nm->cleanup_inline_caches();
   381       nm->cleanup_inline_caches();
   264       // we coudn't transition this nmethod so don't immediately
   382       // we coudn't transition this nmethod so don't immediately
   265       // request a rescan.  If this method stays on the stack for a
   383       // request a rescan.  If this method stays on the stack for a
   266       // long time we don't want to keep rescanning the code cache.
   384       // long time we don't want to keep rescanning the code cache.
   267       _not_entrant_seen_on_stack++;
   385       _not_entrant_seen_on_stack++;
       
   386       SWEEP(nm);
   268     }
   387     }
   269   } else if (nm->is_unloaded()) {
   388   } else if (nm->is_unloaded()) {
   270     // Unloaded code, just make it a zombie
   389     // Unloaded code, just make it a zombie
   271     if (PrintMethodFlushing && Verbose)
   390     if (PrintMethodFlushing && Verbose)
   272       tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm);
   391       tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm);
   273     if (nm->is_osr_method()) {
   392     if (nm->is_osr_method()) {
   274       // No inline caches will ever point to osr methods, so we can just remove it
   393       // No inline caches will ever point to osr methods, so we can just remove it
   275       MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   394       MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       
   395       SWEEP(nm);
   276       nm->flush();
   396       nm->flush();
   277     } else {
   397     } else {
   278       nm->make_zombie();
   398       nm->make_zombie();
   279       _rescan = true;
   399       _rescan = true;
       
   400       SWEEP(nm);
   280     }
   401     }
   281   } else {
   402   } else {
   282     assert(nm->is_alive(), "should be alive");
   403     assert(nm->is_alive(), "should be alive");
   283 
   404 
   284     if (UseCodeCacheFlushing) {
   405     if (UseCodeCacheFlushing) {
   291     }
   412     }
   292 
   413 
   293     // Clean-up all inline caches that points to zombie/non-reentrant methods
   414     // Clean-up all inline caches that points to zombie/non-reentrant methods
   294     MutexLocker cl(CompiledIC_lock);
   415     MutexLocker cl(CompiledIC_lock);
   295     nm->cleanup_inline_caches();
   416     nm->cleanup_inline_caches();
       
   417     SWEEP(nm);
   296   }
   418   }
   297 }
   419 }
   298 
   420 
   299 // Code cache unloading: when compilers notice the code cache is getting full,
   421 // Code cache unloading: when compilers notice the code cache is getting full,
   300 // they will call a vm op that comes here. This code attempts to speculatively
   422 // they will call a vm op that comes here. This code attempts to speculatively