src/share/vm/runtime/sweeper.cpp

changeset 1637
5f24d0319e54
parent 1435
a1423fe86a18
child 1893
bfe29ec02863
     1.1 --- a/src/share/vm/runtime/sweeper.cpp	Fri Jan 29 08:33:24 2010 -0800
     1.2 +++ b/src/share/vm/runtime/sweeper.cpp	Fri Jan 29 09:27:22 2010 -0800
     1.3 @@ -33,6 +33,11 @@
     1.4  jint      NMethodSweeper::_locked_seen = 0;
     1.5  jint      NMethodSweeper::_not_entrant_seen_on_stack = 0;
     1.6  bool      NMethodSweeper::_rescan = false;
     1.7 +bool      NMethodSweeper::_was_full = false;
     1.8 +jint      NMethodSweeper::_advise_to_sweep = 0;
     1.9 +jlong     NMethodSweeper::_last_was_full = 0;
    1.10 +uint      NMethodSweeper::_highest_marked = 0;
    1.11 +long      NMethodSweeper::_was_full_traversal = 0;
    1.12  
    1.13  class MarkActivationClosure: public CodeBlobClosure {
    1.14  public:
    1.15 @@ -114,6 +119,40 @@
    1.16        tty->print_cr("### Couldn't make progress on some nmethods so stopping sweep");
    1.17      }
    1.18    }
    1.19 +
    1.20 +  if (UseCodeCacheFlushing) {
    1.21 +    if (!CodeCache::needs_flushing()) {
    1.22 +      // In a safepoint, no race with setters
    1.23 +      _advise_to_sweep = 0;
    1.24 +    }
    1.25 +
    1.26 +    if (was_full()) {
    1.27 +      // There was some progress so attempt to restart the compiler
    1.28 +      jlong now           = os::javaTimeMillis();
    1.29 +      jlong max_interval  = (jlong)MinCodeCacheFlushingInterval * (jlong)1000;
    1.30 +      jlong curr_interval = now - _last_was_full;
    1.31 +      if ((!CodeCache::needs_flushing()) && (curr_interval > max_interval)) {
    1.32 +        CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation);
    1.33 +        set_was_full(false);
    1.34 +
    1.35 +        // Update the _last_was_full time so we can tell how fast the
    1.36 +        // code cache is filling up
    1.37 +        _last_was_full = os::javaTimeMillis();
    1.38 +
    1.39 +        if (PrintMethodFlushing) {
    1.40 +          tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
    1.41 +            CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
    1.42 +        }
    1.43 +        if (LogCompilation && (xtty != NULL)) {
    1.44 +          ttyLocker ttyl;
    1.45 +          xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
    1.46 +                           CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
    1.47 +          xtty->stamp();
    1.48 +          xtty->end_elem();
    1.49 +        }
    1.50 +      }
    1.51 +    }
    1.52 +  }
    1.53  }
    1.54  
    1.55  
    1.56 @@ -137,12 +176,12 @@
    1.57      if (nm->is_marked_for_reclamation()) {
    1.58        assert(!nm->is_locked_by_vm(), "must not flush locked nmethods");
    1.59        if (PrintMethodFlushing && Verbose) {
    1.60 -        tty->print_cr("### Nmethod 0x%x (marked for reclamation) being flushed", nm);
    1.61 +        tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm);
    1.62        }
    1.63        nm->flush();
    1.64      } else {
    1.65        if (PrintMethodFlushing && Verbose) {
    1.66 -        tty->print_cr("### Nmethod 0x%x (zombie) being marked for reclamation", nm);
    1.67 +        tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm);
    1.68        }
    1.69        nm->mark_for_reclamation();
    1.70        _rescan = true;
    1.71 @@ -152,7 +191,7 @@
    1.72      // stack we can safely convert it to a zombie method
    1.73      if (nm->can_not_entrant_be_converted()) {
    1.74        if (PrintMethodFlushing && Verbose) {
    1.75 -        tty->print_cr("### Nmethod 0x%x (not entrant) being made zombie", nm);
    1.76 +        tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm);
    1.77        }
    1.78        nm->make_zombie();
    1.79        _rescan = true;
    1.80 @@ -167,7 +206,7 @@
    1.81    } else if (nm->is_unloaded()) {
    1.82      // Unloaded code, just make it a zombie
    1.83      if (PrintMethodFlushing && Verbose)
    1.84 -      tty->print_cr("### Nmethod 0x%x (unloaded) being made zombie", nm);
    1.85 +      tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm);
    1.86      if (nm->is_osr_method()) {
    1.87        // No inline caches will ever point to osr methods, so we can just remove it
    1.88        nm->flush();
    1.89 @@ -177,7 +216,167 @@
    1.90      }
    1.91    } else {
    1.92      assert(nm->is_alive(), "should be alive");
    1.93 +
    1.94 +    if (UseCodeCacheFlushing) {
    1.95 +      if ((nm->method()->code() != nm) && !(nm->is_locked_by_vm()) && !(nm->is_osr_method()) &&
    1.96 +          (_traversals > _was_full_traversal+2) && (((uint)nm->compile_id()) < _highest_marked) &&
    1.97 +          CodeCache::needs_flushing()) {
    1.98 +        // This method has not been called since the forced cleanup happened
    1.99 +        nm->make_not_entrant();
   1.100 +      }
   1.101 +    }
   1.102 +
   1.103      // Clean-up all inline caches that points to zombie/non-reentrant methods
   1.104      nm->cleanup_inline_caches();
   1.105    }
   1.106  }
   1.107 +
   1.108 +// Code cache unloading: when compilers notice the code cache is getting full,
   1.109 +// they will call a vm op that comes here. This code attempts to speculatively
   1.110 +// unload the oldest half of the nmethods (based on the compile job id) by
   1.111 +// saving the old code in a list in the CodeCache. Then
   1.112 +// execution resumes. If a method so marked is not called by the second
   1.113 +// safepoint from the current one, the nmethod will be marked non-entrant and
   1.114 +// got rid of by normal sweeping. If the method is called, the methodOop's
   1.115 +// _code field is restored and the methodOop/nmethod
   1.116 +// go back to their normal state.
   1.117 +void NMethodSweeper::handle_full_code_cache(bool is_full) {
   1.118 +  // Only the first one to notice can advise us to start early cleaning
   1.119 +  if (!is_full){
   1.120 +    jint old = Atomic::cmpxchg( 1, &_advise_to_sweep, 0 );
   1.121 +    if (old != 0) {
   1.122 +      return;
   1.123 +    }
   1.124 +  }
   1.125 +
   1.126 +  if (is_full) {
   1.127 +    // Since code cache is full, immediately stop new compiles
   1.128 +    bool did_set = CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation);
   1.129 +    if (!did_set) {
   1.130 +      // only the first to notice can start the cleaning,
   1.131 +      // others will go back and block
   1.132 +      return;
   1.133 +    }
   1.134 +    set_was_full(true);
   1.135 +
   1.136 +    // If we run out within MinCodeCacheFlushingInterval of the last unload time, give up
   1.137 +    jlong now = os::javaTimeMillis();
   1.138 +    jlong max_interval = (jlong)MinCodeCacheFlushingInterval * (jlong)1000;
   1.139 +    jlong curr_interval = now - _last_was_full;
   1.140 +    if (curr_interval < max_interval) {
   1.141 +      _rescan = true;
   1.142 +      if (PrintMethodFlushing) {
   1.143 +        tty->print_cr("### handle full too often, turning off compiler");
   1.144 +      }
   1.145 +      if (LogCompilation && (xtty != NULL)) {
   1.146 +        ttyLocker ttyl;
   1.147 +        xtty->begin_elem("disable_compiler flushing_interval='" UINT64_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
   1.148 +                         curr_interval/1000, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
   1.149 +        xtty->stamp();
   1.150 +        xtty->end_elem();
   1.151 +      }
   1.152 +      return;
   1.153 +    }
   1.154 +  }
   1.155 +
   1.156 +  VM_HandleFullCodeCache op(is_full);
   1.157 +  VMThread::execute(&op);
   1.158 +
   1.159 +  // rescan again as soon as possible
   1.160 +  _rescan = true;
   1.161 +}
   1.162 +
   1.163 +void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
   1.164 +  // If there was a race in detecting full code cache, only run
   1.165 +  // one vm op for it or keep the compiler shut off
   1.166 +
   1.167 +  debug_only(jlong start = os::javaTimeMillis();)
   1.168 +
   1.169 +  if ((!was_full()) && (is_full)) {
   1.170 +    if (!CodeCache::needs_flushing()) {
   1.171 +      if (PrintMethodFlushing) {
   1.172 +        tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
   1.173 +          CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
   1.174 +      }
   1.175 +      if (LogCompilation && (xtty != NULL)) {
   1.176 +        ttyLocker ttyl;
   1.177 +        xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
   1.178 +                         CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
   1.179 +        xtty->stamp();
   1.180 +        xtty->end_elem();
   1.181 +      }
   1.182 +      CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation);
   1.183 +      return;
   1.184 +    }
   1.185 +  }
   1.186 +
   1.187 +  // Traverse the code cache trying to dump the oldest nmethods
   1.188 +  uint curr_max_comp_id = CompileBroker::get_compilation_id();
   1.189 +  uint flush_target = ((curr_max_comp_id - _highest_marked) >> 1) + _highest_marked;
   1.190 +  if (PrintMethodFlushing && Verbose) {
   1.191 +    tty->print_cr("### Cleaning code cache: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes",
   1.192 +        CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
   1.193 +  }
   1.194 +  if (LogCompilation && (xtty != NULL)) {
   1.195 +    ttyLocker ttyl;
   1.196 +    xtty->begin_elem("start_cleaning_code_cache live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
   1.197 +                      CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
   1.198 +    xtty->stamp();
   1.199 +    xtty->end_elem();
   1.200 +  }
   1.201 +
   1.202 +  nmethod* nm = CodeCache::alive_nmethod(CodeCache::first());
   1.203 +  jint disconnected = 0;
   1.204 +  jint made_not_entrant  = 0;
   1.205 +  while ((nm != NULL)){
   1.206 +    uint curr_comp_id = nm->compile_id();
   1.207 +
   1.208 +    // OSR methods cannot be flushed like this. Also, don't flush native methods
   1.209 +    // since they are part of the JDK in most cases
   1.210 +    if (nm->is_in_use() && (!nm->is_osr_method()) && (!nm->is_locked_by_vm()) &&
   1.211 +        (!nm->is_native_method()) && ((curr_comp_id < flush_target))) {
   1.212 +
   1.213 +      if ((nm->method()->code() == nm)) {
   1.214 +        // This method has not been previously considered for
   1.215 +        // unloading or it was restored already
   1.216 +        CodeCache::speculatively_disconnect(nm);
   1.217 +        disconnected++;
   1.218 +      } else if (nm->is_speculatively_disconnected()) {
   1.219 +        // This method was previously considered for preemptive unloading and was not called since then
   1.220 +        nm->method()->invocation_counter()->decay();
   1.221 +        nm->method()->backedge_counter()->decay();
   1.222 +        nm->make_not_entrant();
   1.223 +        made_not_entrant++;
   1.224 +      }
   1.225 +
   1.226 +      if (curr_comp_id > _highest_marked) {
   1.227 +        _highest_marked = curr_comp_id;
   1.228 +      }
   1.229 +    }
   1.230 +    nm = CodeCache::alive_nmethod(CodeCache::next(nm));
   1.231 +  }
   1.232 +
   1.233 +  if (LogCompilation && (xtty != NULL)) {
   1.234 +    ttyLocker ttyl;
   1.235 +    xtty->begin_elem("stop_cleaning_code_cache disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
   1.236 +                      disconnected, made_not_entrant, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
   1.237 +    xtty->stamp();
   1.238 +    xtty->end_elem();
   1.239 +  }
   1.240 +
   1.241 +  // Shut off compiler. Sweeper will run exiting from this safepoint
   1.242 +  // and turn it back on if it clears enough space
   1.243 +  if (was_full()) {
   1.244 +    _last_was_full = os::javaTimeMillis();
   1.245 +    CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation);
   1.246 +  }
   1.247 +
   1.248 +  // After two more traversals the sweeper will get rid of unrestored nmethods
   1.249 +  _was_full_traversal = _traversals;
   1.250 +#ifdef ASSERT
   1.251 +  jlong end = os::javaTimeMillis();
   1.252 +  if(PrintMethodFlushing && Verbose) {
   1.253 +    tty->print_cr("### sweeper: unload time: " INT64_FORMAT, end-start);
   1.254 +  }
   1.255 +#endif
   1.256 +}

mercurial