26 #include "classfile/classLoaderData.hpp" |
26 #include "classfile/classLoaderData.hpp" |
27 #include "classfile/classLoaderDataGraph.hpp" |
27 #include "classfile/classLoaderDataGraph.hpp" |
28 #include "gc/shared/referenceProcessor.hpp" |
28 #include "gc/shared/referenceProcessor.hpp" |
29 #include "gc/shared/referenceProcessorPhaseTimes.hpp" |
29 #include "gc/shared/referenceProcessorPhaseTimes.hpp" |
30 #include "gc/shared/workgroup.hpp" |
30 #include "gc/shared/workgroup.hpp" |
31 #include "gc/shared/weakProcessor.inline.hpp" |
|
32 #include "gc/shenandoah/shenandoahBarrierSet.hpp" |
31 #include "gc/shenandoah/shenandoahBarrierSet.hpp" |
33 #include "gc/shenandoah/shenandoahClosures.inline.hpp" |
32 #include "gc/shenandoah/shenandoahClosures.inline.hpp" |
34 #include "gc/shenandoah/shenandoahCodeRoots.hpp" |
33 #include "gc/shenandoah/shenandoahCodeRoots.hpp" |
35 #include "gc/shenandoah/shenandoahCollectionSet.hpp" |
34 #include "gc/shenandoah/shenandoahCollectionSet.hpp" |
36 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" |
35 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" |
365 prepare_regions(); |
364 prepare_regions(); |
366 |
365 |
367 // Rebuild free set |
366 // Rebuild free set |
368 free_set->rebuild(); |
367 free_set->rebuild(); |
369 |
368 |
370 log_info(gc, ergo)("Collectable Garbage: " SIZE_FORMAT "M, " SIZE_FORMAT "M CSet, " SIZE_FORMAT " CSet regions", |
369 log_info(gc, ergo)("Collectable Garbage: " SIZE_FORMAT "%s, " SIZE_FORMAT "%s CSet, " SIZE_FORMAT " CSet regions", |
371 collection_set->garbage() / M, collection_set->live_data() / M, collection_set->count()); |
370 byte_size_in_proper_unit(collection_set->garbage()), proper_unit_for_byte_size(collection_set->garbage()), |
|
371 byte_size_in_proper_unit(collection_set->live_data()), proper_unit_for_byte_size(collection_set->live_data()), |
|
372 collection_set->count()); |
372 } |
373 } |
373 |
374 |
374 void ShenandoahTraversalGC::init_traversal_collection() { |
375 void ShenandoahTraversalGC::init_traversal_collection() { |
375 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "STW traversal GC"); |
376 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "STW traversal GC"); |
376 |
377 |
387 ShenandoahHeapLocker lock(_heap->lock()); |
388 ShenandoahHeapLocker lock(_heap->lock()); |
388 prepare(); |
389 prepare(); |
389 } |
390 } |
390 |
391 |
391 _heap->set_concurrent_traversal_in_progress(true); |
392 _heap->set_concurrent_traversal_in_progress(true); |
|
393 _heap->set_has_forwarded_objects(true); |
392 |
394 |
393 bool process_refs = _heap->process_references(); |
395 bool process_refs = _heap->process_references(); |
394 if (process_refs) { |
396 if (process_refs) { |
395 ReferenceProcessor* rp = _heap->ref_processor(); |
397 ReferenceProcessor* rp = _heap->ref_processor(); |
396 rp->enable_discovery(true /*verify_no_refs*/); |
398 rp->enable_discovery(true /*verify_no_refs*/); |
400 { |
402 { |
401 ShenandoahGCPhase phase_work(ShenandoahPhaseTimings::init_traversal_gc_work); |
403 ShenandoahGCPhase phase_work(ShenandoahPhaseTimings::init_traversal_gc_work); |
402 assert(_task_queues->is_empty(), "queues must be empty before traversal GC"); |
404 assert(_task_queues->is_empty(), "queues must be empty before traversal GC"); |
403 TASKQUEUE_STATS_ONLY(_task_queues->reset_taskqueue_stats()); |
405 TASKQUEUE_STATS_ONLY(_task_queues->reset_taskqueue_stats()); |
404 |
406 |
405 #if defined(COMPILER2) || INCLUDE_JVMCI |
407 #if COMPILER2_OR_JVMCI |
406 DerivedPointerTable::clear(); |
408 DerivedPointerTable::clear(); |
407 #endif |
409 #endif |
408 |
410 |
409 { |
411 { |
410 uint nworkers = _heap->workers()->active_workers(); |
412 uint nworkers = _heap->workers()->active_workers(); |
412 ShenandoahCSetRootScanner rp(nworkers, ShenandoahPhaseTimings::init_traversal_gc_work); |
414 ShenandoahCSetRootScanner rp(nworkers, ShenandoahPhaseTimings::init_traversal_gc_work); |
413 ShenandoahInitTraversalCollectionTask traversal_task(&rp); |
415 ShenandoahInitTraversalCollectionTask traversal_task(&rp); |
414 _heap->workers()->run_task(&traversal_task); |
416 _heap->workers()->run_task(&traversal_task); |
415 } |
417 } |
416 |
418 |
417 #if defined(COMPILER2) || INCLUDE_JVMCI |
419 #if COMPILER2_OR_JVMCI |
418 DerivedPointerTable::update_pointers(); |
420 DerivedPointerTable::update_pointers(); |
419 #endif |
421 #endif |
420 } |
422 } |
421 |
423 |
422 if (ShenandoahPacing) { |
424 if (ShenandoahPacing) { |
569 |
571 |
570 void ShenandoahTraversalGC::final_traversal_collection() { |
572 void ShenandoahTraversalGC::final_traversal_collection() { |
571 _heap->make_parsable(true); |
573 _heap->make_parsable(true); |
572 |
574 |
573 if (!_heap->cancelled_gc()) { |
575 if (!_heap->cancelled_gc()) { |
574 #if defined(COMPILER2) || INCLUDE_JVMCI |
576 #if COMPILER2_OR_JVMCI |
575 DerivedPointerTable::clear(); |
577 DerivedPointerTable::clear(); |
576 #endif |
578 #endif |
577 ShenandoahGCPhase phase_work(ShenandoahPhaseTimings::final_traversal_gc_work); |
579 ShenandoahGCPhase phase_work(ShenandoahPhaseTimings::final_traversal_gc_work); |
578 uint nworkers = _heap->workers()->active_workers(); |
580 uint nworkers = _heap->workers()->active_workers(); |
579 task_queues()->reserve(nworkers); |
581 task_queues()->reserve(nworkers); |
583 ShenandoahTerminationTracker term(ShenandoahPhaseTimings::final_traversal_gc_termination); |
585 ShenandoahTerminationTracker term(ShenandoahPhaseTimings::final_traversal_gc_termination); |
584 |
586 |
585 ShenandoahTaskTerminator terminator(nworkers, task_queues()); |
587 ShenandoahTaskTerminator terminator(nworkers, task_queues()); |
586 ShenandoahFinalTraversalCollectionTask task(&rp, &terminator); |
588 ShenandoahFinalTraversalCollectionTask task(&rp, &terminator); |
587 _heap->workers()->run_task(&task); |
589 _heap->workers()->run_task(&task); |
588 #if defined(COMPILER2) || INCLUDE_JVMCI |
590 #if COMPILER2_OR_JVMCI |
589 DerivedPointerTable::update_pointers(); |
591 DerivedPointerTable::update_pointers(); |
590 #endif |
592 #endif |
591 } |
593 } |
592 |
594 |
593 if (!_heap->cancelled_gc() && _heap->process_references()) { |
595 if (!_heap->cancelled_gc() && _heap->process_references()) { |
594 weak_refs_work(); |
596 weak_refs_work(); |
595 } |
|
596 |
|
597 if (!_heap->cancelled_gc()) { |
|
598 fixup_roots(); |
|
599 if (_heap->unload_classes()) { |
|
600 _heap->unload_classes_and_cleanup_tables(false); |
|
601 } |
|
602 } |
597 } |
603 |
598 |
604 if (!_heap->cancelled_gc()) { |
599 if (!_heap->cancelled_gc()) { |
605 assert(_task_queues->is_empty(), "queues must be empty after traversal GC"); |
600 assert(_task_queues->is_empty(), "queues must be empty after traversal GC"); |
606 TASKQUEUE_STATS_ONLY(_task_queues->print_taskqueue_stats()); |
601 TASKQUEUE_STATS_ONLY(_task_queues->print_taskqueue_stats()); |
607 TASKQUEUE_STATS_ONLY(_task_queues->reset_taskqueue_stats()); |
602 TASKQUEUE_STATS_ONLY(_task_queues->reset_taskqueue_stats()); |
608 |
603 |
609 // No more marking expected |
604 // No more marking expected |
|
605 _heap->set_concurrent_traversal_in_progress(false); |
610 _heap->mark_complete_marking_context(); |
606 _heap->mark_complete_marking_context(); |
|
607 |
|
608 fixup_roots(); |
|
609 _heap->parallel_cleaning(false); |
|
610 |
|
611 _heap->set_has_forwarded_objects(false); |
611 |
612 |
612 // Resize metaspace |
613 // Resize metaspace |
613 MetaspaceGC::compute_new_size(); |
614 MetaspaceGC::compute_new_size(); |
614 |
615 |
615 // Still good? We can now trash the cset, and make final verification |
616 // Still good? We can now trash the cset, and make final verification |
652 _heap->free_set()->rebuild(); |
653 _heap->free_set()->rebuild(); |
653 reset(); |
654 reset(); |
654 } |
655 } |
655 |
656 |
656 assert(_task_queues->is_empty(), "queues must be empty after traversal GC"); |
657 assert(_task_queues->is_empty(), "queues must be empty after traversal GC"); |
657 _heap->set_concurrent_traversal_in_progress(false); |
|
658 assert(!_heap->cancelled_gc(), "must not be cancelled when getting out here"); |
658 assert(!_heap->cancelled_gc(), "must not be cancelled when getting out here"); |
659 |
659 |
660 if (ShenandoahVerify) { |
660 if (ShenandoahVerify) { |
661 _heap->verifier()->verify_after_traversal(); |
661 _heap->verifier()->verify_after_traversal(); |
662 } |
662 } |
673 inline void do_oop_work(T* p) { |
673 inline void do_oop_work(T* p) { |
674 T o = RawAccess<>::oop_load(p); |
674 T o = RawAccess<>::oop_load(p); |
675 if (!CompressedOops::is_null(o)) { |
675 if (!CompressedOops::is_null(o)) { |
676 oop obj = CompressedOops::decode_not_null(o); |
676 oop obj = CompressedOops::decode_not_null(o); |
677 oop forw = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); |
677 oop forw = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); |
678 if (!oopDesc::equals_raw(obj, forw)) { |
678 if (obj != forw) { |
679 RawAccess<IS_NOT_NULL>::oop_store(p, forw); |
679 RawAccess<IS_NOT_NULL>::oop_store(p, forw); |
680 } |
680 } |
681 } |
681 } |
682 } |
682 } |
683 |
683 |
704 _rp->roots_do<ShenandoahForwardedIsAliveClosure, ShenandoahTraversalFixRootsClosure>(worker_id, &is_alive, &cl); |
704 _rp->roots_do<ShenandoahForwardedIsAliveClosure, ShenandoahTraversalFixRootsClosure>(worker_id, &is_alive, &cl); |
705 } |
705 } |
706 }; |
706 }; |
707 |
707 |
708 void ShenandoahTraversalGC::fixup_roots() { |
708 void ShenandoahTraversalGC::fixup_roots() { |
709 #if defined(COMPILER2) || INCLUDE_JVMCI |
709 #if COMPILER2_OR_JVMCI |
710 DerivedPointerTable::clear(); |
710 DerivedPointerTable::clear(); |
711 #endif |
711 #endif |
712 ShenandoahRootUpdater rp(_heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots, true /* update code cache */); |
712 ShenandoahRootUpdater rp(_heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots); |
713 ShenandoahTraversalFixRootsTask update_roots_task(&rp); |
713 ShenandoahTraversalFixRootsTask update_roots_task(&rp); |
714 _heap->workers()->run_task(&update_roots_task); |
714 _heap->workers()->run_task(&update_roots_task); |
715 #if defined(COMPILER2) || INCLUDE_JVMCI |
715 #if COMPILER2_OR_JVMCI |
716 DerivedPointerTable::update_pointers(); |
716 DerivedPointerTable::update_pointers(); |
717 #endif |
717 #endif |
718 } |
718 } |
719 |
719 |
720 void ShenandoahTraversalGC::reset() { |
720 void ShenandoahTraversalGC::reset() { |