118 // and instead do that in concurrent phase under the relevant lock. This saves init mark |
118 // and instead do that in concurrent phase under the relevant lock. This saves init mark |
119 // pause time. |
119 // pause time. |
120 |
120 |
121 CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong); |
121 CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong); |
122 MarkingCodeBlobClosure blobs_cl(oops, ! CodeBlobToOopClosure::FixRelocations); |
122 MarkingCodeBlobClosure blobs_cl(oops, ! CodeBlobToOopClosure::FixRelocations); |
123 OopClosure* weak_oops = _process_refs ? NULL : oops; |
|
124 |
123 |
125 ResourceMark m; |
124 ResourceMark m; |
126 if (heap->unload_classes()) { |
125 if (heap->unload_classes()) { |
127 _rp->process_strong_roots(oops, weak_oops, &clds_cl, NULL, &blobs_cl, NULL, worker_id); |
126 _rp->process_strong_roots(oops, &clds_cl, NULL, &blobs_cl, NULL, worker_id); |
128 } else { |
127 } else { |
129 if (ShenandoahConcurrentScanCodeRoots) { |
128 if (ShenandoahConcurrentScanCodeRoots) { |
130 CodeBlobClosure* code_blobs = NULL; |
129 CodeBlobClosure* code_blobs = NULL; |
131 #ifdef ASSERT |
130 #ifdef ASSERT |
132 ShenandoahAssertToSpaceClosure assert_to_space_oops; |
131 ShenandoahAssertToSpaceClosure assert_to_space_oops; |
135 // Otherwise, it should have to-space ptrs only if mark does not update refs. |
134 // Otherwise, it should have to-space ptrs only if mark does not update refs. |
136 if (!heap->has_forwarded_objects()) { |
135 if (!heap->has_forwarded_objects()) { |
137 code_blobs = &assert_to_space; |
136 code_blobs = &assert_to_space; |
138 } |
137 } |
139 #endif |
138 #endif |
140 _rp->process_all_roots(oops, weak_oops, &clds_cl, code_blobs, NULL, worker_id); |
139 _rp->process_all_roots(oops, &clds_cl, code_blobs, NULL, worker_id); |
141 } else { |
140 } else { |
142 _rp->process_all_roots(oops, weak_oops, &clds_cl, &blobs_cl, NULL, worker_id); |
141 _rp->process_all_roots(oops, &clds_cl, &blobs_cl, NULL, worker_id); |
143 } |
142 } |
144 } |
143 } |
145 } |
144 } |
146 }; |
145 }; |
147 |
146 |
175 } else { |
174 } else { |
176 code_blobs = |
175 code_blobs = |
177 DEBUG_ONLY(&assert_to_space) |
176 DEBUG_ONLY(&assert_to_space) |
178 NOT_DEBUG(NULL); |
177 NOT_DEBUG(NULL); |
179 } |
178 } |
180 _rp->process_all_roots(&cl, &cl, &cldCl, code_blobs, NULL, worker_id); |
179 _rp->update_all_roots(&cl, &cldCl, code_blobs, NULL, worker_id); |
181 } |
180 } |
182 }; |
181 }; |
183 |
182 |
184 class ShenandoahConcurrentMarkingTask : public AbstractGangTask { |
183 class ShenandoahConcurrentMarkingTask : public AbstractGangTask { |
185 private: |
184 private: |
444 // When we're done marking everything, we process weak references. |
443 // When we're done marking everything, we process weak references. |
445 if (_heap->process_references()) { |
444 if (_heap->process_references()) { |
446 weak_refs_work(full_gc); |
445 weak_refs_work(full_gc); |
447 } |
446 } |
448 |
447 |
|
448 weak_roots_work(); |
|
449 |
449 // And finally finish class unloading |
450 // And finally finish class unloading |
450 if (_heap->unload_classes()) { |
451 if (_heap->unload_classes()) { |
451 _heap->unload_classes_and_cleanup_tables(full_gc); |
452 _heap->unload_classes_and_cleanup_tables(full_gc); |
452 } |
453 } else if (ShenandoahStringDedup::is_enabled()) { |
453 |
454 ShenandoahIsAliveSelector alive; |
|
455 BoolObjectClosure* is_alive = alive.is_alive_closure(); |
|
456 ShenandoahStringDedup::unlink_or_oops_do(is_alive, NULL, false); |
|
457 } |
454 assert(task_queues()->is_empty(), "Should be empty"); |
458 assert(task_queues()->is_empty(), "Should be empty"); |
455 TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats()); |
459 TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats()); |
456 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats()); |
460 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats()); |
457 |
461 |
458 // Resize Metaspace |
462 // Resize Metaspace |
553 |
557 |
554 class ShenandoahWeakAssertNotForwardedClosure : public OopClosure { |
558 class ShenandoahWeakAssertNotForwardedClosure : public OopClosure { |
555 private: |
559 private: |
556 template <class T> |
560 template <class T> |
557 inline void do_oop_work(T* p) { |
561 inline void do_oop_work(T* p) { |
|
562 #ifdef ASSERT |
558 T o = RawAccess<>::oop_load(p); |
563 T o = RawAccess<>::oop_load(p); |
559 if (!CompressedOops::is_null(o)) { |
564 if (!CompressedOops::is_null(o)) { |
560 oop obj = CompressedOops::decode_not_null(o); |
565 oop obj = CompressedOops::decode_not_null(o); |
561 shenandoah_assert_not_forwarded(p, obj); |
566 shenandoah_assert_not_forwarded(p, obj); |
562 } |
567 } |
|
568 #endif |
563 } |
569 } |
564 |
570 |
565 public: |
571 public: |
566 ShenandoahWeakAssertNotForwardedClosure() {} |
572 ShenandoahWeakAssertNotForwardedClosure() {} |
567 |
573 |
646 rp->verify_no_references_recorded(); |
652 rp->verify_no_references_recorded(); |
647 assert(!rp->discovery_enabled(), "Post condition"); |
653 assert(!rp->discovery_enabled(), "Post condition"); |
648 |
654 |
649 } |
655 } |
650 |
656 |
|
657 // Process leftover weak oops: update them, if needed or assert they do not |
|
658 // need updating otherwise. |
|
659 // Weak processor API requires us to visit the oops, even if we are not doing |
|
660 // anything to them. |
|
661 void ShenandoahConcurrentMark::weak_roots_work() { |
|
662 WorkGang* workers = _heap->workers(); |
|
663 ShenandoahIsAliveSelector is_alive; |
|
664 |
|
665 if (_heap->has_forwarded_objects()) { |
|
666 ShenandoahWeakUpdateClosure cl; |
|
667 WeakProcessor::weak_oops_do(workers, is_alive.is_alive_closure(), &cl, 1); |
|
668 } else { |
|
669 ShenandoahWeakAssertNotForwardedClosure cl; |
|
670 WeakProcessor::weak_oops_do(workers, is_alive.is_alive_closure(), &cl, 1); |
|
671 } |
|
672 } |
|
673 |
651 void ShenandoahConcurrentMark::weak_refs_work_doit(bool full_gc) { |
674 void ShenandoahConcurrentMark::weak_refs_work_doit(bool full_gc) { |
652 ReferenceProcessor* rp = _heap->ref_processor(); |
675 ReferenceProcessor* rp = _heap->ref_processor(); |
653 |
676 |
654 ShenandoahPhaseTimings::Phase phase_process = |
677 ShenandoahPhaseTimings::Phase phase_process = |
655 full_gc ? |
678 full_gc ? |
687 |
710 |
688 { |
711 { |
689 ShenandoahGCPhase phase(phase_process); |
712 ShenandoahGCPhase phase(phase_process); |
690 ShenandoahTerminationTracker phase_term(phase_process_termination); |
713 ShenandoahTerminationTracker phase_term(phase_process_termination); |
691 |
714 |
692 // Process leftover weak oops: update them, if needed (using parallel version), |
|
693 // or assert they do not need updating (using serial version) otherwise. |
|
694 // Weak processor API requires us to visit the oops, even if we are not doing |
|
695 // anything to them. |
|
696 if (_heap->has_forwarded_objects()) { |
715 if (_heap->has_forwarded_objects()) { |
697 ShenandoahCMKeepAliveUpdateClosure keep_alive(get_queue(serial_worker_id)); |
716 ShenandoahCMKeepAliveUpdateClosure keep_alive(get_queue(serial_worker_id)); |
698 rp->process_discovered_references(is_alive.is_alive_closure(), &keep_alive, |
717 rp->process_discovered_references(is_alive.is_alive_closure(), &keep_alive, |
699 &complete_gc, &executor, |
718 &complete_gc, &executor, |
700 &pt); |
719 &pt); |
701 |
720 |
702 ShenandoahWeakUpdateClosure cl; |
|
703 WeakProcessor::weak_oops_do(workers, is_alive.is_alive_closure(), &cl, 1); |
|
704 } else { |
721 } else { |
705 ShenandoahCMKeepAliveClosure keep_alive(get_queue(serial_worker_id)); |
722 ShenandoahCMKeepAliveClosure keep_alive(get_queue(serial_worker_id)); |
706 rp->process_discovered_references(is_alive.is_alive_closure(), &keep_alive, |
723 rp->process_discovered_references(is_alive.is_alive_closure(), &keep_alive, |
707 &complete_gc, &executor, |
724 &complete_gc, &executor, |
708 &pt); |
725 &pt); |
709 |
726 |
710 ShenandoahWeakAssertNotForwardedClosure cl; |
|
711 WeakProcessor::weak_oops_do(is_alive.is_alive_closure(), &cl); |
|
712 } |
727 } |
713 |
728 |
714 pt.print_all_references(); |
729 pt.print_all_references(); |
715 |
730 |
716 assert(task_queues()->is_empty(), "Should be empty"); |
731 assert(task_queues()->is_empty(), "Should be empty"); |