src/share/vm/runtime/sweeper.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/runtime/sweeper.cpp	Wed Oct  9 15:17:18 2013
--- new/src/share/vm/runtime/sweeper.cpp	Wed Oct  9 15:17:17 2013

*** 125,135 **** --- 125,136 ---- } #else #define SWEEP(nm) #endif ! nmethod* NMethodSweeper::_current = NULL; // Current nmethod ! nmethod* NMethodSweeper::_current_nmethod = NULL; // Current nmethod + int NMethodSweeper::_current_type = 0; // Current CodeBlobType long NMethodSweeper::_traversals = 0; // Nof. stack traversals performed int NMethodSweeper::_seen = 0; // Nof. nmethods 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_count = 0; // Nof. nmethods marked for reclaim in current sweep
*** 181,191 **** --- 182,192 ---- _hotness_counter_reset_val = (ReservedCodeCacheSize < M) ? 1 : (ReservedCodeCacheSize / M) * 2; } return _hotness_counter_reset_val; } bool NMethodSweeper::sweep_in_progress() { ! return (_current_nmethod != NULL); } // Scans the stacks of all Java threads and marks activations of not-entrant methods. // No need to synchronize access, since 'mark_active_nmethods' is always executed at a // safepoint.
*** 196,210 **** --- 197,212 ---- if (!MethodFlushing) { return; } // Check for restart ! assert(CodeCache::find_blob_unsafe(_current_nmethod) == _current_nmethod, "Sweeper nmethod cached state invalid"); if (!sweep_in_progress() && need_marking_phase()) { _seen = 0; _invocations = NmethodSweepFraction; ! _current = CodeCache::first_nmethod(); ! _current_nmethod = (nmethod*)CodeCache::first_blob(CodeBlobType::MethodNoProfile); + _current_type = CodeBlobType::MethodNoProfile; _traversals += 1; _total_time_this_sweep = 0; if (PrintMethodFlushing) { tty->print_cr("### Sweep: stack traversal %d", _traversals);
*** 249,259 **** --- 251,260 ---- _sweep_started = 0; } } void NMethodSweeper::sweep_code_cache() { jlong sweep_start_counter = os::elapsed_counter(); _flushed_count = 0; _zombified_count = 0; _marked_count = 0;
*** 283,294 **** --- 284,298 ---- int freed_memory = 0; { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + // Sweep non-profiled and profiled nmethods + while (_current_type <= CodeBlobType::MethodProfile) { + // The last invocation iterates until there are no more nmethods ! for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) { ! while ((swept_count < todo || _invocations == 1) && _current_nmethod != NULL) { swept_count++; if (SafepointSynchronize::is_synchronizing()) { // Safepoint request if (PrintMethodFlushing && Verbose) { tty->print_cr("### Sweep at %d out of %d, invocation: %d, yielding to safepoint", _seen, CodeCache::nof_nmethods(), _invocations); }
*** 300,322 **** --- 304,339 ---- thread->java_suspend_self(); } // 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. ! nmethod* next = CodeCache::next_nmethod(_current); ! nmethod* next = (nmethod*)CodeCache::next_blob(_current_nmethod, _current_type); // Now ready to process nmethod and give up CodeCache_lock { MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); ! freed_memory += process_nmethod(_current); ! process_nmethod(_current_nmethod, _current_type); } _seen++; ! _current_nmethod = next; } + + while (_current_nmethod == NULL && _current_type < CodeBlobType::MethodProfile) { + // We reached the last method of the type + // Go to next type that has methods available + _current_type++; + _current_nmethod = (nmethod*)CodeCache::first_blob(_current_type); } assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache"); + if ((swept_count >= todo && _invocations > 1) || _current_nmethod == NULL) { + // We processed enough methods for this invocation + break; + } + } + } + + assert(_invocations > 1 || _current_nmethod == NULL, "must have scanned the whole cache"); if (!sweep_in_progress() && !need_marking_phase() && (_locked_seen || _not_entrant_seen_on_stack)) { // we've completed a scan without making progress but there were // nmethods we were unable to process either because they were // locked or were still on stack. We don't have to aggressively
*** 356,379 **** --- 373,382 ---- if (_invocations == 1) { _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 // is time to restart the compiler. Only checking if there is a certain // amount of free memory in the code cache might lead to re-enabling // compilation although no memory has been released. For example, there are // cases when compilation was disabled although there is 4MB (or more) free // memory in the code cache. The reason is code cache fragmentation. Therefore, // it only makes sense to re-enable compilation if we have actually freed memory. // Note that typically several kB are released for sweeping 16MB of the code // cache. As a result, 'freed_memory' > 0 to restart the compiler. if (UseCodeCacheFlushing && (!CompileBroker::should_compile_new_jobs() && (freed_memory > 0))) { CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation); log_sweep("restart_compiler"); } } class NMethodMarker: public StackObj { private: CompilerThread* _thread;
*** 405,415 **** --- 408,418 ---- MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); nm->flush(); } ! int NMethodSweeper::process_nmethod(nmethod *nm, int code_blob_type) { assert(!CodeCache_lock->owned_by_self(), "just checking"); int freed_memory = 0; // Make sure this nmethod doesn't get unloaded during the scan, // since safepoints may happen during acquired below locks.
*** 497,507 **** --- 500,510 ---- nm->dec_hotness_counter(); // Get the initial value of the hotness counter. This value depends on the // ReservedCodeCacheSize int reset_val = hotness_counter_reset_val(); int time_since_reset = reset_val - nm->hotness_counter(); ! double threshold = -reset_val + (CodeCache::reverse_free_ratio(code_blob_type) * NmethodSweepActivity); // The less free space in the code cache we have - the bigger reverse_free_ratio() is. // I.e., 'threshold' increases with lower available space in the code cache and a higher // NmethodSweepActivity. If the current hotness counter - which decreases from its initial // value until it is reset by stack walking - is smaller than the computed threshold, the // corresponding nmethod is considered for removal.

src/share/vm/runtime/sweeper.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File