Print this page


Split Close
Expand all
Collapse all
          --- old/src/share/vm/runtime/sweeper.cpp
          +++ new/src/share/vm/runtime/sweeper.cpp
↓ open down ↓ 118 lines elided ↑ open up ↑
 119  119  
 120  120      _sweep_index = (_sweep_index + 1) % SweeperLogEntries;
 121  121    }
 122  122  }
 123  123  #else
 124  124  #define SWEEP(nm)
 125  125  #endif
 126  126  
 127  127  
 128  128  long      NMethodSweeper::_traversals = 0;   // No. of stack traversals performed
 129      -nmethod*  NMethodSweeper::_current = NULL;   // Current nmethod
 130  129  int       NMethodSweeper::_seen = 0 ;        // No. of nmethods we have currently processed in current pass of CodeCache
      130 +int       NMethodSweeper::_invocations = 0;  // No. of invocations of the sweeper
 131  131  
 132      -volatile int NMethodSweeper::_invocations = 0;   // No. of invocations left until we are completed with this pass
 133      -volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress.
      132 +volatile int       NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress.
      133 +volatile nmethod*  NMethodSweeper::_current = NULL;    // Current nmethod
 134  134  
 135  135  jint      NMethodSweeper::_locked_seen = 0;
 136  136  jint      NMethodSweeper::_not_entrant_seen_on_stack = 0;
 137  137  bool      NMethodSweeper::_rescan = false;
 138  138  bool      NMethodSweeper::_do_sweep = false;
 139  139  bool      NMethodSweeper::_was_full = false;
 140  140  jint      NMethodSweeper::_advise_to_sweep = 0;
 141  141  jlong     NMethodSweeper::_last_was_full = 0;
 142  142  uint      NMethodSweeper::_highest_marked = 0;
 143  143  long      NMethodSweeper::_was_full_traversal = 0;
↓ open down ↓ 25 lines elided ↑ open up ↑
 169  169    }
 170  170  
 171  171    // Make sure CompiledIC_lock in unlocked, since we might update some
 172  172    // inline caches. If it is, we just bail-out and try later.
 173  173    if (CompiledIC_lock->is_locked() || Patching_lock->is_locked()) return;
 174  174  
 175  175    // Check for restart
 176  176    assert(CodeCache::find_blob_unsafe(_current) == _current, "Sweeper nmethod cached state invalid");
 177  177    if (_current == NULL) {
 178  178      _seen        = 0;
 179      -    _invocations = NmethodSweepFraction;
      179 +    _invocations = 0;
 180  180      _current     = CodeCache::first_nmethod();
 181  181      _traversals  += 1;
 182  182      if (PrintMethodFlushing) {
 183  183        tty->print_cr("### Sweep: stack traversal %d", _traversals);
 184  184      }
 185  185      Threads::nmethods_do(&mark_activation_closure);
 186  186  
 187  187      // reset the flags since we started a scan from the beginning.
 188  188      _rescan = false;
 189  189      _locked_seen = 0;
↓ open down ↓ 22 lines elided ↑ open up ↑
 212  212          log_sweep("restart_compiler");
 213  213        }
 214  214      }
 215  215    }
 216  216  }
 217  217  
 218  218  void NMethodSweeper::possibly_sweep() {
 219  219    assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
 220  220    if ((!MethodFlushing) || (!_do_sweep)) return;
 221  221  
 222      -  if (_invocations > 0) {
      222 +  if (_current != NULL) {
 223  223      // Only one thread at a time will sweep
 224  224      jint old = Atomic::cmpxchg( 1, &_sweep_started, 0 );
 225  225      if (old != 0) {
 226  226        return;
 227  227      }
 228  228  #ifdef ASSERT
 229  229      if (LogSweeper && _records == NULL) {
 230  230        // Create the ring buffer for the logging code
 231  231        _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries);
 232  232        memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries);
 233  233      }
 234  234  #endif
 235      -    if (_invocations > 0) {
      235 +    if (_current != NULL) {
 236  236        sweep_code_cache();
 237      -      _invocations--;
 238  237      }
      238 +    _invocations++;
 239  239      _sweep_started = 0;
 240  240    }
 241  241  }
 242  242  
 243      -void NMethodSweeper::sweep_code_cache() {
      243 +void NMethodSweeper::sweep_code_cache(void) {
 244  244  #ifdef ASSERT
 245  245    jlong sweep_start;
 246  246    if (PrintMethodFlushing) {
 247  247      sweep_start = os::javaTimeMillis();
 248  248    }
 249  249  #endif
 250  250    if (PrintMethodFlushing && Verbose) {
 251      -    tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations);
      251 +    tty->print_cr("### Sweep at %d out of %d, invocations %d", _seen, CodeCache::nof_nmethods(), _invocations);
 252  252    }
 253  253  
 254      -  // We want to visit all nmethods after NmethodSweepFraction
 255      -  // invocations so divide the remaining number of nmethods by the
 256      -  // remaining number of invocations.  This is only an estimate since
 257      -  // the number of nmethods changes during the sweep so the final
 258      -  // stage must iterate until it there are no more nmethods.
 259      -  int todo = (CodeCache::nof_nmethods() - _seen) / _invocations;
 260      -
 261  254    assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here");
 262  255    assert(!CodeCache_lock->owned_by_self(), "just checking");
 263  256  
 264  257    {
 265  258      MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 266  259  
 267  260      // The last invocation iterates until there are no more nmethods
 268      -    for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) {
      261 +    for (int i = 0; (i < NMethodSweepLimit || CompileTheWorld) && _current != NULL; i++) {
      262 +      if (!CompileTheWorld && SafepointSynchronize::is_synchronizing()) { // Safepoint request
      263 +        if (PrintMethodFlushing && Verbose) {
      264 +          tty->print_cr("### Sweep at %d out of %d, safepoint", _seen, CodeCache::nof_nmethods());
      265 +        }
      266 +        MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 269  267  
      268 +        assert(Thread::current()->is_Java_thread(), "should be java thread");
      269 +        JavaThread* thread = (JavaThread*)Thread::current();
      270 +        ThreadBlockInVM tbivm(thread);
      271 +        thread->java_suspend_self();
      272 +      }
 270  273        // Since we will give up the CodeCache_lock, always skip ahead
 271  274        // to the next nmethod.  Other blobs can be deleted by other
 272  275        // threads but nmethods are only reclaimed by the sweeper.
 273  276        nmethod* next = CodeCache::next_nmethod(_current);
 274  277  
 275  278        // Now ready to process nmethod and give up CodeCache_lock
 276  279        {
 277  280          MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 278  281          process_nmethod(_current);
 279  282        }
 280  283        _seen++;
 281  284        _current = next;
 282  285      }
 283  286    }
 284  287  
 285      -  assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache");
 286      -
 287  288    if (_current == NULL && !_rescan && (_locked_seen || _not_entrant_seen_on_stack)) {
 288  289      // we've completed a scan without making progress but there were
 289  290      // nmethods we were unable to process either because they were
 290  291      // locked or were still on stack.  We don't have to aggresively
 291  292      // clean them up so just stop scanning.  We could scan once more
 292  293      // but that complicates the control logic and it's unlikely to
 293  294      // matter much.
 294  295      if (PrintMethodFlushing) {
 295  296        tty->print_cr("### Couldn't make progress on some nmethods so stopping sweep");
 296  297      }
 297  298    }
 298  299  
 299  300  #ifdef ASSERT
 300  301    if(PrintMethodFlushing) {
 301  302      jlong sweep_end             = os::javaTimeMillis();
 302  303      tty->print_cr("### sweeper:      sweep time(%d): " INT64_FORMAT, _invocations, sweep_end - sweep_start);
 303  304    }
 304  305  #endif
 305  306  
 306      -  if (_invocations == 1) {
      307 +  if (_current == NULL) {
 307  308      log_sweep("finished");
 308  309    }
 309  310  }
 310  311  
 311  312  class NMethodMarker: public StackObj {
 312  313   private:
 313  314    CompilerThread* _thread;
 314  315   public:
 315  316    NMethodMarker(nmethod* nm) {
 316  317      _thread = CompilerThread::current();
↓ open down ↓ 261 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX