--- old/src/share/vm/runtime/sweeper.cpp 2014-04-14 10:01:27.199015916 +0200 +++ new/src/share/vm/runtime/sweeper.cpp 2014-04-14 10:01:26.243015881 +0200 @@ -127,7 +127,8 @@ #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; // Stack scan count, also sweep ID. long NMethodSweeper::_total_nof_code_cache_sweeps = 0; // Total number of full sweeps of the code cache long NMethodSweeper::_time_counter = 0; // Virtual time used to periodically invoke sweeper @@ -146,26 +147,24 @@ // 3) zombie -> marked_for_reclamation int NMethodSweeper::_hotness_counter_reset_val = 0; -long NMethodSweeper::_total_nof_methods_reclaimed = 0; // Accumulated nof methods flushed -long NMethodSweeper::_total_nof_c2_methods_reclaimed = 0; // Accumulated nof methods flushed -size_t NMethodSweeper::_total_flushed_size = 0; // Total number of bytes flushed from the code cache -Tickspan NMethodSweeper::_total_time_sweeping; // Accumulated time sweeping -Tickspan NMethodSweeper::_total_time_this_sweep; // Total time this sweep -Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep -Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction - +long NMethodSweeper::_total_nof_methods_reclaimed = 0; // Accumulated nof methods flushed +long NMethodSweeper::_total_nof_c2_methods_reclaimed = 0; // Accumulated nof methods flushed +size_t NMethodSweeper::_total_flushed_size = 0; // Total number of bytes flushed from the code cache +Tickspan NMethodSweeper::_total_time_sweeping; // Accumulated time sweeping +Tickspan NMethodSweeper::_total_time_this_sweep; // Total time this sweep +Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep +Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction class MarkActivationClosure: public CodeBlobClosure { public: virtual void do_code_blob(CodeBlob* cb) { - if (cb->is_nmethod()) { - nmethod* nm = (nmethod*)cb; - nm->set_hotness_counter(NMethodSweeper::hotness_counter_reset_val()); - // If we see an activation belonging to a non_entrant nmethod, we mark it. - if (nm->is_not_entrant()) { - nm->mark_as_seen_on_stack(); - } + assert(cb->is_nmethod(), "CodeBlob should be nmethod"); + nmethod* nm = (nmethod*)cb; + nm->set_hotness_counter(NMethodSweeper::hotness_counter_reset_val()); + // If we see an activation belonging to a non_entrant nmethod, we mark it. + if (nm->is_not_entrant()) { + nm->mark_as_seen_on_stack(); } } }; @@ -174,10 +173,9 @@ class SetHotnessClosure: public CodeBlobClosure { public: virtual void do_code_blob(CodeBlob* cb) { - if (cb->is_nmethod()) { - nmethod* nm = (nmethod*)cb; - nm->set_hotness_counter(NMethodSweeper::hotness_counter_reset_val()); - } + assert(cb->is_nmethod(), "CodeBlob should be nmethod"); + nmethod* nm = (nmethod*)cb; + nm->set_hotness_counter(NMethodSweeper::hotness_counter_reset_val()); } }; static SetHotnessClosure set_hotness_closure; @@ -190,7 +188,7 @@ return _hotness_counter_reset_val; } bool NMethodSweeper::sweep_in_progress() { - return (_current != NULL); + return (_current_nmethod != NULL); } // Scans the stacks of all Java threads and marks activations of not-entrant methods. @@ -208,11 +206,12 @@ _time_counter++; // Check for restart - assert(CodeCache::find_blob_unsafe(_current) == _current, "Sweeper nmethod cached state invalid"); + assert(CodeCache::find_blob_unsafe(_current_nmethod) == _current_nmethod, "Sweeper nmethod cached state invalid"); if (!sweep_in_progress()) { _seen = 0; _sweep_fractions_left = NmethodSweepFraction; - _current = CodeCache::first_nmethod(); + _current_nmethod = (nmethod*)CodeCache::first_blob(CodeBlobType::MethodNonProfiled); + _current_type = CodeBlobType::MethodNonProfiled; _traversals += 1; _total_time_this_sweep = Tickspan(); @@ -267,7 +266,10 @@ // an unsigned type would cause an underflow (wait_until_next_sweep becomes a large positive // value) that disables the intended periodic sweeps. const int max_wait_time = ReservedCodeCacheSize / (16 * M); - double wait_until_next_sweep = max_wait_time - time_since_last_sweep - CodeCache::reverse_free_ratio(); + // Use only signed types + double wait_until_next_sweep = max_wait_time - time_since_last_sweep - + MAX2(CodeCache::reverse_free_ratio(CodeBlobType::MethodProfiled), + CodeCache::reverse_free_ratio(CodeBlobType::MethodNonProfiled)); assert(wait_until_next_sweep <= (double)max_wait_time, "Calculation of code cache sweeper interval is incorrect"); if ((wait_until_next_sweep <= 0.0) || !CompileBroker::should_compile_new_jobs()) { @@ -349,7 +351,7 @@ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); // The last invocation iterates until there are no more nmethods - for (int i = 0; (i < todo || _sweep_fractions_left == 1) && _current != NULL; i++) { + while ((swept_count < todo || _sweep_fractions_left == 1) && _current_nmethod != NULL) { swept_count++; if (SafepointSynchronize::is_synchronizing()) { // Safepoint request if (PrintMethodFlushing && Verbose) { @@ -365,19 +367,26 @@ // 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); + freed_memory += process_nmethod(_current_nmethod, _current_type); } _seen++; - _current = next; + + while (next == NULL && _current_type < CodeBlobType::MethodProfiled) { + // We reached the last method of the type + // Go to next type that has methods available + _current_type++; + next = (nmethod*)CodeCache::first_blob(_current_type); + } + _current_nmethod = next; } } - assert(_sweep_fractions_left > 1 || _current == NULL, "must have scanned the whole cache"); + assert(_sweep_fractions_left > 1 || _current_nmethod == NULL, "must have scanned the whole cache"); const Ticks sweep_end_counter = Ticks::now(); const Tickspan sweep_time = sweep_end_counter - sweep_start_counter; @@ -485,7 +494,7 @@ nm->flush(); } -int NMethodSweeper::process_nmethod(nmethod *nm) { +int NMethodSweeper::process_nmethod(nmethod *nm, int code_blob_type) { assert(!CodeCache_lock->owned_by_self(), "just checking"); int freed_memory = 0; @@ -577,7 +586,7 @@ // 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() * NmethodSweepActivity); + 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