413 while (!_current.end()) { |
420 while (!_current.end()) { |
414 swept_count++; |
421 swept_count++; |
415 // Since we will give up the CodeCache_lock, always skip ahead |
422 // Since we will give up the CodeCache_lock, always skip ahead |
416 // to the next nmethod. Other blobs can be deleted by other |
423 // to the next nmethod. Other blobs can be deleted by other |
417 // threads but nmethods are only reclaimed by the sweeper. |
424 // threads but nmethods are only reclaimed by the sweeper. |
418 nmethod* nm = _current.method(); |
425 CompiledMethod* nm = _current.method(); |
419 _current.next(); |
426 _current.next(); |
420 |
427 |
421 // Now ready to process nmethod and give up CodeCache_lock |
428 // Now ready to process nmethod and give up CodeCache_lock |
422 { |
429 { |
423 MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
430 MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
424 // Save information before potentially flushing the nmethod |
431 // Save information before potentially flushing the nmethod |
425 int size = nm->total_size(); |
432 // Only flushing nmethods so size only matters for them. |
|
433 int size = nm->is_nmethod() ? ((nmethod*)nm)->total_size() : 0; |
426 bool is_c2_method = nm->is_compiled_by_c2(); |
434 bool is_c2_method = nm->is_compiled_by_c2(); |
427 bool is_osr = nm->is_osr_method(); |
435 bool is_osr = nm->is_osr_method(); |
428 int compile_id = nm->compile_id(); |
436 int compile_id = nm->compile_id(); |
429 intptr_t address = p2i(nm); |
437 intptr_t address = p2i(nm); |
430 const char* state_before = nm->state(); |
438 const char* state_before = nm->state(); |
431 const char* state_after = ""; |
439 const char* state_after = ""; |
432 |
440 |
433 MethodStateChange type = process_nmethod(nm); |
441 MethodStateChange type = process_compiled_method(nm); |
434 switch (type) { |
442 switch (type) { |
435 case Flushed: |
443 case Flushed: |
436 state_after = "flushed"; |
444 state_after = "flushed"; |
437 freed_memory += size; |
445 freed_memory += size; |
438 ++flushed_count; |
446 ++flushed_count; |
530 if (percent_changed > 1.0) { |
538 if (percent_changed > 1.0) { |
531 _should_sweep = true; |
539 _should_sweep = true; |
532 } |
540 } |
533 } |
541 } |
534 |
542 |
535 class NMethodMarker: public StackObj { |
543 class CompiledMethodMarker: public StackObj { |
536 private: |
544 private: |
537 CodeCacheSweeperThread* _thread; |
545 CodeCacheSweeperThread* _thread; |
538 public: |
546 public: |
539 NMethodMarker(nmethod* nm) { |
547 CompiledMethodMarker(CompiledMethod* cm) { |
540 JavaThread* current = JavaThread::current(); |
548 JavaThread* current = JavaThread::current(); |
541 assert (current->is_Code_cache_sweeper_thread(), "Must be"); |
549 assert (current->is_Code_cache_sweeper_thread(), "Must be"); |
542 _thread = (CodeCacheSweeperThread*)current; |
550 _thread = (CodeCacheSweeperThread*)current; |
543 if (!nm->is_zombie() && !nm->is_unloaded()) { |
551 if (!cm->is_zombie() && !cm->is_unloaded()) { |
544 // Only expose live nmethods for scanning |
552 // Only expose live nmethods for scanning |
545 _thread->set_scanned_nmethod(nm); |
553 _thread->set_scanned_compiled_method(cm); |
546 } |
554 } |
547 } |
555 } |
548 ~NMethodMarker() { |
556 ~CompiledMethodMarker() { |
549 _thread->set_scanned_nmethod(NULL); |
557 _thread->set_scanned_compiled_method(NULL); |
550 } |
558 } |
551 }; |
559 }; |
552 |
560 |
553 void NMethodSweeper::release_nmethod(nmethod* nm) { |
561 void NMethodSweeper::release_compiled_method(CompiledMethod* nm) { |
554 // Make sure the released nmethod is no longer referenced by the sweeper thread |
562 // Make sure the released nmethod is no longer referenced by the sweeper thread |
555 CodeCacheSweeperThread* thread = (CodeCacheSweeperThread*)JavaThread::current(); |
563 CodeCacheSweeperThread* thread = (CodeCacheSweeperThread*)JavaThread::current(); |
556 thread->set_scanned_nmethod(NULL); |
564 thread->set_scanned_compiled_method(NULL); |
557 |
565 |
558 // Clean up any CompiledICHolders |
566 // Clean up any CompiledICHolders |
559 { |
567 { |
560 ResourceMark rm; |
568 ResourceMark rm; |
561 MutexLocker ml_patch(CompiledIC_lock); |
569 MutexLocker ml_patch(CompiledIC_lock); |
569 |
577 |
570 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
578 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
571 nm->flush(); |
579 nm->flush(); |
572 } |
580 } |
573 |
581 |
574 NMethodSweeper::MethodStateChange NMethodSweeper::process_nmethod(nmethod* nm) { |
582 NMethodSweeper::MethodStateChange NMethodSweeper::process_compiled_method(CompiledMethod* cm) { |
575 assert(nm != NULL, "sanity"); |
583 assert(cm != NULL, "sanity"); |
576 assert(!CodeCache_lock->owned_by_self(), "just checking"); |
584 assert(!CodeCache_lock->owned_by_self(), "just checking"); |
577 |
585 |
578 MethodStateChange result = None; |
586 MethodStateChange result = None; |
579 // Make sure this nmethod doesn't get unloaded during the scan, |
587 // Make sure this nmethod doesn't get unloaded during the scan, |
580 // since safepoints may happen during acquired below locks. |
588 // since safepoints may happen during acquired below locks. |
581 NMethodMarker nmm(nm); |
589 CompiledMethodMarker nmm(cm); |
582 SWEEP(nm); |
590 SWEEP(cm); |
583 |
591 |
584 // Skip methods that are currently referenced by the VM |
592 // Skip methods that are currently referenced by the VM |
585 if (nm->is_locked_by_vm()) { |
593 if (cm->is_locked_by_vm()) { |
586 // But still remember to clean-up inline caches for alive nmethods |
594 // But still remember to clean-up inline caches for alive nmethods |
587 if (nm->is_alive()) { |
595 if (cm->is_alive()) { |
588 // Clean inline caches that point to zombie/non-entrant/unloaded nmethods |
596 // Clean inline caches that point to zombie/non-entrant/unloaded nmethods |
589 MutexLocker cl(CompiledIC_lock); |
597 MutexLocker cl(CompiledIC_lock); |
590 nm->cleanup_inline_caches(); |
598 cm->cleanup_inline_caches(); |
591 SWEEP(nm); |
599 SWEEP(cm); |
592 } |
600 } |
593 return result; |
601 return result; |
594 } |
602 } |
595 |
603 |
596 if (nm->is_zombie()) { |
604 if (cm->is_zombie()) { |
597 // All inline caches that referred to this nmethod were cleaned in the |
605 // All inline caches that referred to this nmethod were cleaned in the |
598 // previous sweeper cycle. Now flush the nmethod from the code cache. |
606 // previous sweeper cycle. Now flush the nmethod from the code cache. |
599 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); |
607 assert(!cm->is_locked_by_vm(), "must not flush locked Compiled Methods"); |
600 release_nmethod(nm); |
608 release_compiled_method(cm); |
601 assert(result == None, "sanity"); |
609 assert(result == None, "sanity"); |
602 result = Flushed; |
610 result = Flushed; |
603 } else if (nm->is_not_entrant()) { |
611 } else if (cm->is_not_entrant()) { |
604 // If there are no current activations of this method on the |
612 // If there are no current activations of this method on the |
605 // stack we can safely convert it to a zombie method |
613 // stack we can safely convert it to a zombie method |
606 if (nm->can_convert_to_zombie()) { |
614 if (cm->can_convert_to_zombie()) { |
607 // Clear ICStubs to prevent back patching stubs of zombie or flushed |
615 // Clear ICStubs to prevent back patching stubs of zombie or flushed |
608 // nmethods during the next safepoint (see ICStub::finalize). |
616 // nmethods during the next safepoint (see ICStub::finalize). |
609 { |
617 { |
610 MutexLocker cl(CompiledIC_lock); |
618 MutexLocker cl(CompiledIC_lock); |
611 nm->clear_ic_stubs(); |
619 cm->clear_ic_stubs(); |
612 } |
620 } |
613 // Code cache state change is tracked in make_zombie() |
621 // Code cache state change is tracked in make_zombie() |
614 nm->make_zombie(); |
622 cm->make_zombie(); |
615 SWEEP(nm); |
623 SWEEP(cm); |
616 // The nmethod may have been locked by JVMTI after being made zombie (see |
624 // The nmethod may have been locked by JVMTI after being made zombie (see |
617 // JvmtiDeferredEvent::compiled_method_unload_event()). If so, we cannot |
625 // JvmtiDeferredEvent::compiled_method_unload_event()). If so, we cannot |
618 // flush the osr nmethod directly but have to wait for a later sweeper cycle. |
626 // flush the osr nmethod directly but have to wait for a later sweeper cycle. |
619 if (nm->is_osr_method() && !nm->is_locked_by_vm()) { |
627 if (cm->is_osr_method() && !cm->is_locked_by_vm()) { |
620 // No inline caches will ever point to osr methods, so we can just remove it. |
628 // No inline caches will ever point to osr methods, so we can just remove it. |
621 // Make sure that we unregistered the nmethod with the heap and flushed all |
629 // Make sure that we unregistered the nmethod with the heap and flushed all |
622 // dependencies before removing the nmethod (done in make_zombie()). |
630 // dependencies before removing the nmethod (done in make_zombie()). |
623 assert(nm->is_zombie(), "nmethod must be unregistered"); |
631 assert(cm->is_zombie(), "nmethod must be unregistered"); |
624 release_nmethod(nm); |
632 release_compiled_method(cm); |
625 assert(result == None, "sanity"); |
633 assert(result == None, "sanity"); |
626 result = Flushed; |
634 result = Flushed; |
627 } else { |
635 } else { |
628 assert(result == None, "sanity"); |
636 assert(result == None, "sanity"); |
629 result = MadeZombie; |
637 result = MadeZombie; |
630 assert(nm->is_zombie(), "nmethod must be zombie"); |
638 assert(cm->is_zombie(), "nmethod must be zombie"); |
631 } |
639 } |
632 } else { |
640 } else { |
633 // Still alive, clean up its inline caches |
641 // Still alive, clean up its inline caches |
634 MutexLocker cl(CompiledIC_lock); |
642 MutexLocker cl(CompiledIC_lock); |
635 nm->cleanup_inline_caches(); |
643 cm->cleanup_inline_caches(); |
636 SWEEP(nm); |
644 SWEEP(cm); |
637 } |
645 } |
638 } else if (nm->is_unloaded()) { |
646 } else if (cm->is_unloaded()) { |
639 // Code is unloaded, so there are no activations on the stack. |
647 // Code is unloaded, so there are no activations on the stack. |
640 // Convert the nmethod to zombie or flush it directly in the OSR case. |
648 // Convert the nmethod to zombie or flush it directly in the OSR case. |
641 { |
649 { |
642 // Clean ICs of unloaded nmethods as well because they may reference other |
650 // Clean ICs of unloaded nmethods as well because they may reference other |
643 // unloaded nmethods that may be flushed earlier in the sweeper cycle. |
651 // unloaded nmethods that may be flushed earlier in the sweeper cycle. |
644 MutexLocker cl(CompiledIC_lock); |
652 MutexLocker cl(CompiledIC_lock); |
645 nm->cleanup_inline_caches(); |
653 cm->cleanup_inline_caches(); |
646 } |
654 } |
647 if (nm->is_osr_method()) { |
655 if (cm->is_osr_method()) { |
648 SWEEP(nm); |
656 SWEEP(cm); |
649 // No inline caches will ever point to osr methods, so we can just remove it |
657 // No inline caches will ever point to osr methods, so we can just remove it |
650 release_nmethod(nm); |
658 release_compiled_method(cm); |
651 assert(result == None, "sanity"); |
659 assert(result == None, "sanity"); |
652 result = Flushed; |
660 result = Flushed; |
653 } else { |
661 } else { |
654 // Code cache state change is tracked in make_zombie() |
662 // Code cache state change is tracked in make_zombie() |
655 nm->make_zombie(); |
663 cm->make_zombie(); |
656 SWEEP(nm); |
664 SWEEP(cm); |
657 assert(result == None, "sanity"); |
665 assert(result == None, "sanity"); |
658 result = MadeZombie; |
666 result = MadeZombie; |
659 } |
667 } |
660 } else { |
668 } else { |
661 possibly_flush(nm); |
669 if (cm->is_nmethod()) { |
|
670 possibly_flush((nmethod*)cm); |
|
671 } |
662 // Clean inline caches that point to zombie/non-entrant/unloaded nmethods |
672 // Clean inline caches that point to zombie/non-entrant/unloaded nmethods |
663 MutexLocker cl(CompiledIC_lock); |
673 MutexLocker cl(CompiledIC_lock); |
664 nm->cleanup_inline_caches(); |
674 cm->cleanup_inline_caches(); |
665 SWEEP(nm); |
675 SWEEP(cm); |
666 } |
676 } |
667 return result; |
677 return result; |
668 } |
678 } |
669 |
679 |
670 |
680 |