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) { |
290 _sweep_fractions_left--; |
294 _sweep_fractions_left--; |
291 } |
295 } |
292 |
296 |
293 // We are done with sweeping the code cache once. |
297 // We are done with sweeping the code cache once. |
294 if (_sweep_fractions_left == 0) { |
298 if (_sweep_fractions_left == 0) { |
|
299 _total_nof_code_cache_sweeps++; |
295 _last_sweep = _time_counter; |
300 _last_sweep = _time_counter; |
296 // Reset flag; temporarily disables sweeper |
301 // Reset flag; temporarily disables sweeper |
297 _should_sweep = false; |
302 _should_sweep = false; |
298 // If there was enough state change, 'possibly_enable_sweeper()' |
303 // If there was enough state change, 'possibly_enable_sweeper()' |
299 // sets '_should_sweep' to true |
304 // sets '_should_sweep' to true |
376 const Ticks sweep_end_counter = Ticks::now(); |
381 const Ticks sweep_end_counter = Ticks::now(); |
377 const Tickspan sweep_time = sweep_end_counter - sweep_start_counter; |
382 const Tickspan sweep_time = sweep_end_counter - sweep_start_counter; |
378 _total_time_sweeping += sweep_time; |
383 _total_time_sweeping += sweep_time; |
379 _total_time_this_sweep += sweep_time; |
384 _total_time_this_sweep += sweep_time; |
380 _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); |
385 _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); |
|
386 _total_flushed_size += freed_memory; |
381 _total_nof_methods_reclaimed += _flushed_count; |
387 _total_nof_methods_reclaimed += _flushed_count; |
382 |
388 |
383 EventSweepCodeCache event(UNTIMED); |
389 EventSweepCodeCache event(UNTIMED); |
384 if (event.should_commit()) { |
390 if (event.should_commit()) { |
385 event.set_starttime(sweep_start_counter); |
391 event.set_starttime(sweep_start_counter); |
507 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); |
513 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); |
508 if (PrintMethodFlushing && Verbose) { |
514 if (PrintMethodFlushing && Verbose) { |
509 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); |
515 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); |
510 } |
516 } |
511 freed_memory = nm->total_size(); |
517 freed_memory = nm->total_size(); |
|
518 if (nm->is_compiled_by_c2()) { |
|
519 _total_nof_c2_methods_reclaimed++; |
|
520 } |
512 release_nmethod(nm); |
521 release_nmethod(nm); |
513 _flushed_count++; |
522 _flushed_count++; |
514 } else { |
523 } else { |
515 if (PrintMethodFlushing && Verbose) { |
524 if (PrintMethodFlushing && Verbose) { |
516 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); |
525 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); |
545 } |
554 } |
546 if (nm->is_osr_method()) { |
555 if (nm->is_osr_method()) { |
547 SWEEP(nm); |
556 SWEEP(nm); |
548 // No inline caches will ever point to osr methods, so we can just remove it |
557 // No inline caches will ever point to osr methods, so we can just remove it |
549 freed_memory = nm->total_size(); |
558 freed_memory = nm->total_size(); |
|
559 if (nm->is_compiled_by_c2()) { |
|
560 _total_nof_c2_methods_reclaimed++; |
|
561 } |
550 release_nmethod(nm); |
562 release_nmethod(nm); |
551 _flushed_count++; |
563 _flushed_count++; |
552 } else { |
564 } else { |
553 // Code cache state change is tracked in make_zombie() |
565 // Code cache state change is tracked in make_zombie() |
554 nm->make_zombie(); |
566 nm->make_zombie(); |
632 xtty->print(s.as_string()); |
644 xtty->print(s.as_string()); |
633 xtty->stamp(); |
645 xtty->stamp(); |
634 xtty->end_elem(); |
646 xtty->end_elem(); |
635 } |
647 } |
636 } |
648 } |
|
649 |
|
650 void NMethodSweeper::print() { |
|
651 ttyLocker ttyl; |
|
652 tty->print_cr("Code cache sweeper statistics:"); |
|
653 tty->print_cr(" Total sweep time: %1.0lfms", (double)_total_time_sweeping.value()/1000000); |
|
654 tty->print_cr(" Total number of full sweeps: %ld", _total_nof_code_cache_sweeps); |
|
655 tty->print_cr(" Total number of flushed methods: %ld(%ld C2 methods)", _total_nof_methods_reclaimed, |
|
656 _total_nof_c2_methods_reclaimed); |
|
657 tty->print_cr(" Total size of flushed methods: " SIZE_FORMAT "kB", _total_flushed_size/K); |
|
658 } |