140 long NMethodSweeper::_traversals = 0; // Stack scan count, also sweep ID. |
140 long NMethodSweeper::_traversals = 0; // Stack scan count, also sweep ID. |
141 long NMethodSweeper::_total_nof_code_cache_sweeps = 0; // Total number of full sweeps of the code cache |
141 long NMethodSweeper::_total_nof_code_cache_sweeps = 0; // Total number of full sweeps of the code cache |
142 long NMethodSweeper::_time_counter = 0; // Virtual time used to periodically invoke sweeper |
142 long NMethodSweeper::_time_counter = 0; // Virtual time used to periodically invoke sweeper |
143 long NMethodSweeper::_last_sweep = 0; // Value of _time_counter when the last sweep happened |
143 long NMethodSweeper::_last_sweep = 0; // Value of _time_counter when the last sweep happened |
144 int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache |
144 int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache |
145 int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep |
|
146 int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep |
|
147 int NMethodSweeper::_marked_for_reclamation_count = 0; // Nof. nmethods marked for reclaim in current sweep |
|
148 |
145 |
149 volatile bool NMethodSweeper::_should_sweep = true; // Indicates if we should invoke the sweeper |
146 volatile bool NMethodSweeper::_should_sweep = true; // Indicates if we should invoke the sweeper |
150 volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from: |
147 volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from: |
151 // 1) alive -> not_entrant |
148 // 1) alive -> not_entrant |
152 // 2) not_entrant -> zombie |
149 // 2) not_entrant -> zombie |
159 Tickspan NMethodSweeper::_total_time_sweeping; // Accumulated time sweeping |
156 Tickspan NMethodSweeper::_total_time_sweeping; // Accumulated time sweeping |
160 Tickspan NMethodSweeper::_total_time_this_sweep; // Total time this sweep |
157 Tickspan NMethodSweeper::_total_time_this_sweep; // Total time this sweep |
161 Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep |
158 Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep |
162 Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction |
159 Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction |
163 |
160 |
|
161 Monitor* NMethodSweeper::_stat_lock = new Monitor(Mutex::special, "Sweeper::Statistics", true); |
164 |
162 |
165 class MarkActivationClosure: public CodeBlobClosure { |
163 class MarkActivationClosure: public CodeBlobClosure { |
166 public: |
164 public: |
167 virtual void do_code_blob(CodeBlob* cb) { |
165 virtual void do_code_blob(CodeBlob* cb) { |
168 assert(cb->is_nmethod(), "CodeBlob should be nmethod"); |
166 assert(cb->is_nmethod(), "CodeBlob should be nmethod"); |
384 |
383 |
385 int freed_memory = 0; |
384 int freed_memory = 0; |
386 { |
385 { |
387 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
386 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
388 |
387 |
389 // The last invocation iterates until there are no more nmethods |
|
390 while (!_current.end()) { |
388 while (!_current.end()) { |
391 swept_count++; |
389 swept_count++; |
392 handle_safepoint_request(); |
|
393 // Since we will give up the CodeCache_lock, always skip ahead |
390 // Since we will give up the CodeCache_lock, always skip ahead |
394 // to the next nmethod. Other blobs can be deleted by other |
391 // to the next nmethod. Other blobs can be deleted by other |
395 // threads but nmethods are only reclaimed by the sweeper. |
392 // threads but nmethods are only reclaimed by the sweeper. |
396 nmethod* nm = _current.method(); |
393 nmethod* nm = _current.method(); |
397 _current.next(); |
394 _current.next(); |
398 |
395 |
399 // Now ready to process nmethod and give up CodeCache_lock |
396 // Now ready to process nmethod and give up CodeCache_lock |
400 { |
397 { |
401 MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
398 MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
402 freed_memory += process_nmethod(nm); |
399 int size = nm->total_size(); |
|
400 bool is_c2_method = nm->is_compiled_by_c2(); |
|
401 |
|
402 MethodStateChange type = process_nmethod(nm); |
|
403 switch (type) { |
|
404 case Flushed: |
|
405 freed_memory += size; |
|
406 ++flushed_count; |
|
407 if (is_c2_method) { |
|
408 ++flushed_c2_count; |
|
409 } |
|
410 break; |
|
411 case MarkedForReclamation: |
|
412 ++marked_for_reclamation_count; |
|
413 break; |
|
414 case MadeZombie: |
|
415 ++zombified_count; |
|
416 break; |
|
417 case None: |
|
418 break; |
|
419 default: |
|
420 ShouldNotReachHere(); |
|
421 } |
403 } |
422 } |
404 _seen++; |
423 _seen++; |
|
424 handle_safepoint_request(); |
405 } |
425 } |
406 } |
426 } |
407 |
427 |
408 assert(_current.end(), "must have scanned the whole cache"); |
428 assert(_current.end(), "must have scanned the whole cache"); |
409 |
429 |
410 const Ticks sweep_end_counter = Ticks::now(); |
430 const Ticks sweep_end_counter = Ticks::now(); |
411 const Tickspan sweep_time = sweep_end_counter - sweep_start_counter; |
431 const Tickspan sweep_time = sweep_end_counter - sweep_start_counter; |
412 _total_time_sweeping += sweep_time; |
432 { |
413 _total_time_this_sweep += sweep_time; |
433 MutexLockerEx mu(_stat_lock, Mutex::_no_safepoint_check_flag); |
414 _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); |
434 _total_time_sweeping += sweep_time; |
415 _total_flushed_size += freed_memory; |
435 _total_time_this_sweep += sweep_time; |
416 _total_nof_methods_reclaimed += _flushed_count; |
436 _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); |
417 |
437 _total_flushed_size += freed_memory; |
|
438 _total_nof_methods_reclaimed += flushed_count; |
|
439 _total_nof_c2_methods_reclaimed += flushed_c2_count; |
|
440 _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep); |
|
441 } |
418 EventSweepCodeCache event(UNTIMED); |
442 EventSweepCodeCache event(UNTIMED); |
419 if (event.should_commit()) { |
443 if (event.should_commit()) { |
420 event.set_starttime(sweep_start_counter); |
444 event.set_starttime(sweep_start_counter); |
421 event.set_endtime(sweep_end_counter); |
445 event.set_endtime(sweep_end_counter); |
422 event.set_sweepIndex(_traversals); |
446 event.set_sweepIndex(_traversals); |
423 event.set_sweptCount(swept_count); |
447 event.set_sweptCount(swept_count); |
424 event.set_flushedCount(_flushed_count); |
448 event.set_flushedCount(flushed_count); |
425 event.set_markedCount(_marked_for_reclamation_count); |
449 event.set_markedCount(marked_for_reclamation_count); |
426 event.set_zombifiedCount(_zombified_count); |
450 event.set_zombifiedCount(zombified_count); |
427 event.commit(); |
451 event.commit(); |
428 } |
452 } |
429 |
453 |
430 #ifdef ASSERT |
454 #ifdef ASSERT |
431 if(PrintMethodFlushing) { |
455 if(PrintMethodFlushing) { |
432 tty->print_cr("### sweeper: sweep time(%d): ", (jlong)sweep_time.value()); |
456 tty->print_cr("### sweeper: sweep time(%d): ", (jlong)sweep_time.value()); |
433 } |
457 } |
434 #endif |
458 #endif |
435 |
459 |
436 _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep); |
|
437 log_sweep("finished"); |
460 log_sweep("finished"); |
438 |
461 |
439 // Sweeper is the only case where memory is released, check here if it |
462 // Sweeper is the only case where memory is released, check here if it |
440 // is time to restart the compiler. Only checking if there is a certain |
463 // is time to restart the compiler. Only checking if there is a certain |
441 // amount of free memory in the code cache might lead to re-enabling |
464 // amount of free memory in the code cache might lead to re-enabling |
509 |
532 |
510 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
533 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
511 nm->flush(); |
534 nm->flush(); |
512 } |
535 } |
513 |
536 |
514 int NMethodSweeper::process_nmethod(nmethod* nm) { |
537 NMethodSweeper::MethodStateChange NMethodSweeper::process_nmethod(nmethod* nm) { |
|
538 assert(nm != NULL, "sanity"); |
515 assert(!CodeCache_lock->owned_by_self(), "just checking"); |
539 assert(!CodeCache_lock->owned_by_self(), "just checking"); |
516 |
540 |
517 int freed_memory = 0; |
541 MethodStateChange result = None; |
518 // Make sure this nmethod doesn't get unloaded during the scan, |
542 // Make sure this nmethod doesn't get unloaded during the scan, |
519 // since safepoints may happen during acquired below locks. |
543 // since safepoints may happen during acquired below locks. |
520 NMethodMarker nmm(nm); |
544 NMethodMarker nmm(nm); |
521 SWEEP(nm); |
545 SWEEP(nm); |
522 |
546 |
539 if (nm->is_marked_for_reclamation()) { |
563 if (nm->is_marked_for_reclamation()) { |
540 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); |
564 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); |
541 if (PrintMethodFlushing && Verbose) { |
565 if (PrintMethodFlushing && Verbose) { |
542 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); |
566 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); |
543 } |
567 } |
544 freed_memory = nm->total_size(); |
|
545 if (nm->is_compiled_by_c2()) { |
|
546 _total_nof_c2_methods_reclaimed++; |
|
547 } |
|
548 release_nmethod(nm); |
568 release_nmethod(nm); |
549 _flushed_count++; |
569 assert(result == None, "sanity"); |
|
570 result = Flushed; |
550 } else { |
571 } else { |
551 if (PrintMethodFlushing && Verbose) { |
572 if (PrintMethodFlushing && Verbose) { |
552 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); |
573 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); |
553 } |
574 } |
554 nm->mark_for_reclamation(); |
575 nm->mark_for_reclamation(); |
555 // Keep track of code cache state change |
576 // Keep track of code cache state change |
556 _bytes_changed += nm->total_size(); |
577 _bytes_changed += nm->total_size(); |
557 _marked_for_reclamation_count++; |
|
558 SWEEP(nm); |
578 SWEEP(nm); |
|
579 assert(result == None, "sanity"); |
|
580 result = MarkedForReclamation; |
559 } |
581 } |
560 } else if (nm->is_not_entrant()) { |
582 } else if (nm->is_not_entrant()) { |
561 // If there are no current activations of this method on the |
583 // If there are no current activations of this method on the |
562 // stack we can safely convert it to a zombie method |
584 // stack we can safely convert it to a zombie method |
563 if (nm->can_not_entrant_be_converted()) { |
585 if (nm->can_not_entrant_be_converted()) { |
592 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm); |
615 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm); |
593 } |
616 } |
594 if (nm->is_osr_method()) { |
617 if (nm->is_osr_method()) { |
595 SWEEP(nm); |
618 SWEEP(nm); |
596 // No inline caches will ever point to osr methods, so we can just remove it |
619 // No inline caches will ever point to osr methods, so we can just remove it |
597 freed_memory = nm->total_size(); |
|
598 if (nm->is_compiled_by_c2()) { |
|
599 _total_nof_c2_methods_reclaimed++; |
|
600 } |
|
601 release_nmethod(nm); |
620 release_nmethod(nm); |
602 _flushed_count++; |
621 assert(result == None, "sanity"); |
|
622 result = Flushed; |
603 } else { |
623 } else { |
604 // Code cache state change is tracked in make_zombie() |
624 // Code cache state change is tracked in make_zombie() |
605 nm->make_zombie(); |
625 nm->make_zombie(); |
606 _zombified_count++; |
|
607 SWEEP(nm); |
626 SWEEP(nm); |
|
627 assert(result == None, "sanity"); |
|
628 result = MadeZombie; |
608 } |
629 } |
609 } else { |
630 } else { |
610 possibly_flush(nm); |
631 possibly_flush(nm); |
611 // Clean-up all inline caches that point to zombie/non-reentrant methods |
632 // Clean-up all inline caches that point to zombie/non-reentrant methods |
612 MutexLocker cl(CompiledIC_lock); |
633 MutexLocker cl(CompiledIC_lock); |
613 nm->cleanup_inline_caches(); |
634 nm->cleanup_inline_caches(); |
614 SWEEP(nm); |
635 SWEEP(nm); |
615 } |
636 } |
616 return freed_memory; |
637 return result; |
617 } |
638 } |
618 |
639 |
619 |
640 |
620 void NMethodSweeper::possibly_flush(nmethod* nm) { |
641 void NMethodSweeper::possibly_flush(nmethod* nm) { |
621 if (UseCodeCacheFlushing) { |
642 if (UseCodeCacheFlushing) { |