comparison src/share/vm/runtime/sweeper.cpp @ 14518:d8041d695d19

Merged with jdk9/dev/hotspot changeset 3812c088b945
author twisti
date Tue, 11 Mar 2014 18:45:59 -0700
parents 2d4a8d3d286b abec000618bf
children 4ca6dc0799b6
comparison
equal deleted inserted replaced
14141:f97c5ec83832 14518:d8041d695d19
127 #define SWEEP(nm) 127 #define SWEEP(nm)
128 #endif 128 #endif
129 129
130 nmethod* NMethodSweeper::_current = NULL; // Current nmethod 130 nmethod* NMethodSweeper::_current = NULL; // Current nmethod
131 long NMethodSweeper::_traversals = 0; // Stack scan count, also sweep ID. 131 long NMethodSweeper::_traversals = 0; // Stack scan count, also sweep ID.
132 long NMethodSweeper::_total_nof_code_cache_sweeps = 0; // Total number of full sweeps of the code cache
132 long NMethodSweeper::_time_counter = 0; // Virtual time used to periodically invoke sweeper 133 long NMethodSweeper::_time_counter = 0; // Virtual time used to periodically invoke sweeper
133 long NMethodSweeper::_last_sweep = 0; // Value of _time_counter when the last sweep happened 134 long NMethodSweeper::_last_sweep = 0; // Value of _time_counter when the last sweep happened
134 int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache 135 int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache
135 int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep 136 int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep
136 int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep 137 int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep
141 volatile int NMethodSweeper::_sweep_started = 0; // Flag to control conc sweeper 142 volatile int NMethodSweeper::_sweep_started = 0; // Flag to control conc sweeper
142 volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from: 143 volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from:
143 // 1) alive -> not_entrant 144 // 1) alive -> not_entrant
144 // 2) not_entrant -> zombie 145 // 2) not_entrant -> zombie
145 // 3) zombie -> marked_for_reclamation 146 // 3) zombie -> marked_for_reclamation
146 147 int NMethodSweeper::_hotness_counter_reset_val = 0;
147 int NMethodSweeper::_total_nof_methods_reclaimed = 0; // Accumulated nof methods flushed 148
148 Tickspan NMethodSweeper::_total_time_sweeping; // Accumulated time sweeping 149 long NMethodSweeper::_total_nof_methods_reclaimed = 0; // Accumulated nof methods flushed
149 Tickspan NMethodSweeper::_total_time_this_sweep; // Total time this sweep 150 long NMethodSweeper::_total_nof_c2_methods_reclaimed = 0; // Accumulated nof methods flushed
150 Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep 151 size_t NMethodSweeper::_total_flushed_size = 0; // Total number of bytes flushed from the code cache
151 Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction 152 Tickspan NMethodSweeper::_total_time_sweeping; // Accumulated time sweeping
152 int NMethodSweeper::_hotness_counter_reset_val = 0; 153 Tickspan NMethodSweeper::_total_time_this_sweep; // Total time this sweep
154 Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep
155 Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction
156
153 157
154 158
155 class MarkActivationClosure: public CodeBlobClosure { 159 class MarkActivationClosure: public CodeBlobClosure {
156 public: 160 public:
157 virtual void do_code_blob(CodeBlob* cb) { 161 virtual void do_code_blob(CodeBlob* cb) {
255 // As a result, we invoke the sweeper after 259 // As a result, we invoke the sweeper after
256 // 15 invocations of 'mark_active_nmethods. 260 // 15 invocations of 'mark_active_nmethods.
257 // Large ReservedCodeCacheSize: (e.g., 256M + code Cache is 90% full). The formula 261 // Large ReservedCodeCacheSize: (e.g., 256M + code Cache is 90% full). The formula
258 // computes: (256 / 16) - 10 = 6. 262 // computes: (256 / 16) - 10 = 6.
259 if (!_should_sweep) { 263 if (!_should_sweep) {
260 int time_since_last_sweep = _time_counter - _last_sweep; 264 const int time_since_last_sweep = _time_counter - _last_sweep;
261 double wait_until_next_sweep = (ReservedCodeCacheSize / (16 * M)) - time_since_last_sweep - 265 // ReservedCodeCacheSize has an 'unsigned' type. We need a 'signed' type for max_wait_time,
262 CodeCache::reverse_free_ratio(); 266 // since 'time_since_last_sweep' can be larger than 'max_wait_time'. If that happens using
267 // an unsigned type would cause an underflow (wait_until_next_sweep becomes a large positive
268 // value) that disables the intended periodic sweeps.
269 const int max_wait_time = ReservedCodeCacheSize / (16 * M);
270 double wait_until_next_sweep = max_wait_time - time_since_last_sweep - CodeCache::reverse_free_ratio();
271 assert(wait_until_next_sweep <= (double)max_wait_time, "Calculation of code cache sweeper interval is incorrect");
263 272
264 if ((wait_until_next_sweep <= 0.0) || !CompileBroker::should_compile_new_jobs()) { 273 if ((wait_until_next_sweep <= 0.0) || !CompileBroker::should_compile_new_jobs()) {
265 _should_sweep = true; 274 _should_sweep = true;
266 } 275 }
267 } 276 }
285 _sweep_fractions_left--; 294 _sweep_fractions_left--;
286 } 295 }
287 296
288 // We are done with sweeping the code cache once. 297 // We are done with sweeping the code cache once.
289 if (_sweep_fractions_left == 0) { 298 if (_sweep_fractions_left == 0) {
299 _total_nof_code_cache_sweeps++;
290 _last_sweep = _time_counter; 300 _last_sweep = _time_counter;
291 // Reset flag; temporarily disables sweeper 301 // Reset flag; temporarily disables sweeper
292 _should_sweep = false; 302 _should_sweep = false;
293 // If there was enough state change, 'possibly_enable_sweeper()' 303 // If there was enough state change, 'possibly_enable_sweeper()'
294 // sets '_should_sweep' to true 304 // sets '_should_sweep' to true
297 // can further increase by calls to 'report_state_change'. 307 // can further increase by calls to 'report_state_change'.
298 if (_should_sweep) { 308 if (_should_sweep) {
299 _bytes_changed = 0; 309 _bytes_changed = 0;
300 } 310 }
301 } 311 }
302 _sweep_started = 0; 312 // Release work, because another compiler thread could continue.
313 OrderAccess::release_store((int*)&_sweep_started, 0);
303 } 314 }
304 } 315 }
305 316
306 void NMethodSweeper::sweep_code_cache() { 317 void NMethodSweeper::sweep_code_cache() {
307 Ticks sweep_start_counter = Ticks::now(); 318 Ticks sweep_start_counter = Ticks::now();
371 const Ticks sweep_end_counter = Ticks::now(); 382 const Ticks sweep_end_counter = Ticks::now();
372 const Tickspan sweep_time = sweep_end_counter - sweep_start_counter; 383 const Tickspan sweep_time = sweep_end_counter - sweep_start_counter;
373 _total_time_sweeping += sweep_time; 384 _total_time_sweeping += sweep_time;
374 _total_time_this_sweep += sweep_time; 385 _total_time_this_sweep += sweep_time;
375 _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); 386 _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time);
387 _total_flushed_size += freed_memory;
376 _total_nof_methods_reclaimed += _flushed_count; 388 _total_nof_methods_reclaimed += _flushed_count;
377 389
378 EventSweepCodeCache event(UNTIMED); 390 EventSweepCodeCache event(UNTIMED);
379 if (event.should_commit()) { 391 if (event.should_commit()) {
380 event.set_starttime(sweep_start_counter); 392 event.set_starttime(sweep_start_counter);
510 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); 522 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods");
511 if (PrintMethodFlushing && Verbose) { 523 if (PrintMethodFlushing && Verbose) {
512 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); 524 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm);
513 } 525 }
514 freed_memory = nm->total_size(); 526 freed_memory = nm->total_size();
527 if (nm->is_compiled_by_c2()) {
528 _total_nof_c2_methods_reclaimed++;
529 }
515 release_nmethod(nm); 530 release_nmethod(nm);
516 _flushed_count++; 531 _flushed_count++;
517 } else { 532 } else {
518 if (PrintMethodFlushing && Verbose) { 533 if (PrintMethodFlushing && Verbose) {
519 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); 534 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm);
548 } 563 }
549 if (nm->is_osr_method()) { 564 if (nm->is_osr_method()) {
550 SWEEP(nm); 565 SWEEP(nm);
551 // No inline caches will ever point to osr methods, so we can just remove it 566 // No inline caches will ever point to osr methods, so we can just remove it
552 freed_memory = nm->total_size(); 567 freed_memory = nm->total_size();
568 if (nm->is_compiled_by_c2()) {
569 _total_nof_c2_methods_reclaimed++;
570 }
553 release_nmethod(nm); 571 release_nmethod(nm);
554 _flushed_count++; 572 _flushed_count++;
555 } else { 573 } else {
556 // Code cache state change is tracked in make_zombie() 574 // Code cache state change is tracked in make_zombie()
557 nm->make_zombie(); 575 nm->make_zombie();
635 xtty->print(s.as_string()); 653 xtty->print(s.as_string());
636 xtty->stamp(); 654 xtty->stamp();
637 xtty->end_elem(); 655 xtty->end_elem();
638 } 656 }
639 } 657 }
658
659 void NMethodSweeper::print() {
660 ttyLocker ttyl;
661 tty->print_cr("Code cache sweeper statistics:");
662 tty->print_cr(" Total sweep time: %1.0lfms", (double)_total_time_sweeping.value()/1000000);
663 tty->print_cr(" Total number of full sweeps: %ld", _total_nof_code_cache_sweeps);
664 tty->print_cr(" Total number of flushed methods: %ld(%ld C2 methods)", _total_nof_methods_reclaimed,
665 _total_nof_c2_methods_reclaimed);
666 tty->print_cr(" Total size of flushed methods: " SIZE_FORMAT "kB", _total_flushed_size/K);
667 }