125 |
125 |
126 _rem_set = collector_policy()->create_rem_set(reserved_region()); |
126 _rem_set = collector_policy()->create_rem_set(reserved_region()); |
127 set_barrier_set(rem_set()->bs()); |
127 set_barrier_set(rem_set()->bs()); |
128 |
128 |
129 ReservedSpace young_rs = heap_rs.first_part(gen_policy()->young_gen_spec()->max_size(), false, false); |
129 ReservedSpace young_rs = heap_rs.first_part(gen_policy()->young_gen_spec()->max_size(), false, false); |
130 _young_gen = gen_policy()->young_gen_spec()->init(young_rs, 0, rem_set()); |
130 _young_gen = gen_policy()->young_gen_spec()->init(young_rs, rem_set()); |
131 heap_rs = heap_rs.last_part(gen_policy()->young_gen_spec()->max_size()); |
131 heap_rs = heap_rs.last_part(gen_policy()->young_gen_spec()->max_size()); |
132 |
132 |
133 ReservedSpace old_rs = heap_rs.first_part(gen_policy()->old_gen_spec()->max_size(), false, false); |
133 ReservedSpace old_rs = heap_rs.first_part(gen_policy()->old_gen_spec()->max_size(), false, false); |
134 _old_gen = gen_policy()->old_gen_spec()->init(old_rs, 1, rem_set()); |
134 _old_gen = gen_policy()->old_gen_spec()->init(old_rs, rem_set()); |
135 clear_incremental_collection_failed(); |
135 clear_incremental_collection_failed(); |
136 |
136 |
137 #if INCLUDE_ALL_GCS |
137 #if INCLUDE_ALL_GCS |
138 // If we are running CMS, create the collector responsible |
138 // If we are running CMS, create the collector responsible |
139 // for collecting the CMS generations. |
139 // for collecting the CMS generations. |
200 |
200 |
201 size_t GenCollectedHeap::used() const { |
201 size_t GenCollectedHeap::used() const { |
202 return _young_gen->used() + _old_gen->used(); |
202 return _young_gen->used() + _old_gen->used(); |
203 } |
203 } |
204 |
204 |
205 // Save the "used_region" for generations level and lower. |
205 void GenCollectedHeap::save_used_regions() { |
206 void GenCollectedHeap::save_used_regions(int level) { |
206 _old_gen->save_used_region(); |
207 assert(level == 0 || level == 1, "Illegal level parameter"); |
|
208 if (level == 1) { |
|
209 _old_gen->save_used_region(); |
|
210 } |
|
211 _young_gen->save_used_region(); |
207 _young_gen->save_used_region(); |
212 } |
208 } |
213 |
209 |
214 size_t GenCollectedHeap::max_capacity() const { |
210 size_t GenCollectedHeap::max_capacity() const { |
215 return _young_gen->max_capacity() + _old_gen->max_capacity(); |
211 return _young_gen->max_capacity() + _old_gen->max_capacity(); |
335 // a previous collection will do mangling and will |
331 // a previous collection will do mangling and will |
336 // change top of some spaces. |
332 // change top of some spaces. |
337 record_gen_tops_before_GC(); |
333 record_gen_tops_before_GC(); |
338 |
334 |
339 if (PrintGC && Verbose) { |
335 if (PrintGC && Verbose) { |
340 gclog_or_tty->print("level=%d invoke=%d size=" SIZE_FORMAT, |
336 // I didn't want to change the logging when removing the level concept, |
341 gen->level(), |
337 // but I guess this logging could say young/old or something instead of 0/1. |
|
338 uint level; |
|
339 if (heap()->is_young_gen(gen)) { |
|
340 level = 0; |
|
341 } else { |
|
342 level = 1; |
|
343 } |
|
344 gclog_or_tty->print("level=%u invoke=%d size=" SIZE_FORMAT, |
|
345 level, |
342 gen->stat_record()->invocations, |
346 gen->stat_record()->invocations, |
343 size * HeapWordSize); |
347 size * HeapWordSize); |
344 } |
348 } |
345 |
349 |
346 if (run_verification && VerifyBeforeGC) { |
350 if (run_verification && VerifyBeforeGC) { |
410 gclog_or_tty->print(":"); |
414 gclog_or_tty->print(":"); |
411 gen->print_heap_change(prev_used); |
415 gen->print_heap_change(prev_used); |
412 } |
416 } |
413 } |
417 } |
414 |
418 |
415 void GenCollectedHeap::do_collection(bool full, |
419 void GenCollectedHeap::do_collection(bool full, |
416 bool clear_all_soft_refs, |
420 bool clear_all_soft_refs, |
417 size_t size, |
421 size_t size, |
418 bool is_tlab, |
422 bool is_tlab, |
419 int max_level) { |
423 GenerationType max_generation) { |
420 ResourceMark rm; |
424 ResourceMark rm; |
421 DEBUG_ONLY(Thread* my_thread = Thread::current();) |
425 DEBUG_ONLY(Thread* my_thread = Thread::current();) |
422 |
426 |
423 assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); |
427 assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); |
424 assert(my_thread->is_VM_thread() || |
428 assert(my_thread->is_VM_thread() || |
442 print_heap_before_gc(); |
446 print_heap_before_gc(); |
443 |
447 |
444 { |
448 { |
445 FlagSetting fl(_is_gc_active, true); |
449 FlagSetting fl(_is_gc_active, true); |
446 |
450 |
447 bool complete = full && (max_level == 1 /* old */); |
451 bool complete = full && (max_generation == OldGen); |
448 const char* gc_cause_prefix = complete ? "Full GC" : "GC"; |
452 const char* gc_cause_prefix = complete ? "Full GC" : "GC"; |
449 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); |
453 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); |
450 // The PrintGCDetails logging starts before we have incremented the GC id. We will do that later |
454 // The PrintGCDetails logging starts before we have incremented the GC id. We will do that later |
451 // so we can assume here that the next GC id is what we want. |
455 // so we can assume here that the next GC id is what we want. |
452 GCTraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, NULL, GCId::peek()); |
456 GCTraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, NULL, GCId::peek()); |
456 |
460 |
457 size_t gch_prev_used = used(); |
461 size_t gch_prev_used = used(); |
458 bool run_verification = total_collections() >= VerifyGCStartAt; |
462 bool run_verification = total_collections() >= VerifyGCStartAt; |
459 |
463 |
460 bool prepared_for_verification = false; |
464 bool prepared_for_verification = false; |
461 int max_level_collected = 0; |
465 bool collected_old = false; |
462 bool old_collects_young = (max_level == 1) && |
466 bool old_collects_young = complete && |
463 full && |
|
464 _old_gen->full_collects_younger_generations(); |
467 _old_gen->full_collects_younger_generations(); |
465 if (!old_collects_young && |
468 if (!old_collects_young && |
466 _young_gen->should_collect(full, size, is_tlab)) { |
469 _young_gen->should_collect(full, size, is_tlab)) { |
467 if (run_verification && VerifyGCLevel <= 0 && VerifyBeforeGC) { |
470 if (run_verification && VerifyGCLevel <= 0 && VerifyBeforeGC) { |
468 prepare_for_verify(); |
471 prepare_for_verify(); |
508 run_verification && VerifyGCLevel <= 1, |
511 run_verification && VerifyGCLevel <= 1, |
509 do_clear_all_soft_refs, |
512 do_clear_all_soft_refs, |
510 true); |
513 true); |
511 |
514 |
512 must_restore_marks_for_biased_locking = true; |
515 must_restore_marks_for_biased_locking = true; |
513 max_level_collected = 1; |
516 collected_old = true; |
514 } |
517 } |
515 |
518 |
516 // Update "complete" boolean wrt what actually transpired -- |
519 // Update "complete" boolean wrt what actually transpired -- |
517 // for instance, a promotion failure could have led to |
520 // for instance, a promotion failure could have led to |
518 // a whole heap collection. |
521 // a whole heap collection. |
519 complete = complete || (max_level_collected == 1 /* old */); |
522 complete = complete || collected_old; |
520 |
523 |
521 if (complete) { // We did a "major" collection |
524 if (complete) { // We did a "major" collection |
522 // FIXME: See comment at pre_full_gc_dump call |
525 // FIXME: See comment at pre_full_gc_dump call |
523 post_full_gc_dump(NULL); // do any post full gc dumps |
526 post_full_gc_dump(NULL); // do any post full gc dumps |
524 } |
527 } |
659 // Verify that the code cache contents are not subject to |
662 // Verify that the code cache contents are not subject to |
660 // movement by a scavenging collection. |
663 // movement by a scavenging collection. |
661 DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, !CodeBlobToOopClosure::FixRelocations)); |
664 DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, !CodeBlobToOopClosure::FixRelocations)); |
662 DEBUG_ONLY(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable)); |
665 DEBUG_ONLY(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable)); |
663 } |
666 } |
664 |
|
665 } |
667 } |
666 |
668 |
667 void GenCollectedHeap::gen_process_roots(StrongRootsScope* scope, |
669 void GenCollectedHeap::gen_process_roots(StrongRootsScope* scope, |
668 int level, |
670 GenerationType type, |
669 bool younger_gens_as_roots, |
671 bool younger_gens_as_roots, |
670 ScanningOption so, |
672 ScanningOption so, |
671 bool only_strong_roots, |
673 bool only_strong_roots, |
672 OopsInGenClosure* not_older_gens, |
674 OopsInGenClosure* not_older_gens, |
673 OopsInGenClosure* older_gens, |
675 OopsInGenClosure* older_gens, |
674 CLDClosure* cld_closure) { |
676 CLDClosure* cld_closure) { |
675 const bool is_adjust_phase = !only_strong_roots && !younger_gens_as_roots; |
677 const bool is_adjust_phase = !only_strong_roots && !younger_gens_as_roots; |
676 |
678 |
677 bool is_moving_collection = false; |
679 bool is_moving_collection = false; |
678 if (level == 0 || is_adjust_phase) { |
680 if (type == YoungGen || is_adjust_phase) { |
679 // young collections are always moving |
681 // young collections are always moving |
680 is_moving_collection = true; |
682 is_moving_collection = true; |
681 } |
683 } |
682 |
684 |
683 MarkingCodeBlobClosure mark_code_closure(not_older_gens, is_moving_collection); |
685 MarkingCodeBlobClosure mark_code_closure(not_older_gens, is_moving_collection); |
689 cld_closure, weak_cld_closure, |
691 cld_closure, weak_cld_closure, |
690 &mark_code_closure); |
692 &mark_code_closure); |
691 |
693 |
692 if (younger_gens_as_roots) { |
694 if (younger_gens_as_roots) { |
693 if (!_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) { |
695 if (!_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) { |
694 if (level == 1) { |
696 if (type == OldGen) { |
695 not_older_gens->set_generation(_young_gen); |
697 not_older_gens->set_generation(_young_gen); |
696 _young_gen->oop_iterate(not_older_gens); |
698 _young_gen->oop_iterate(not_older_gens); |
697 } |
699 } |
698 not_older_gens->reset_generation(); |
700 not_older_gens->reset_generation(); |
699 } |
701 } |
700 } |
702 } |
701 // When collection is parallel, all threads get to cooperate to do |
703 // When collection is parallel, all threads get to cooperate to do |
702 // older-gen scanning. |
704 // old generation scanning. |
703 if (level == 0) { |
705 if (type == YoungGen) { |
704 older_gens->set_generation(_old_gen); |
706 older_gens->set_generation(_old_gen); |
705 rem_set()->younger_refs_iterate(_old_gen, older_gens, scope->n_threads()); |
707 rem_set()->younger_refs_iterate(_old_gen, older_gens, scope->n_threads()); |
706 older_gens->reset_generation(); |
708 older_gens->reset_generation(); |
707 } |
709 } |
708 |
710 |
722 _old_gen->ref_processor()->weak_oops_do(root_closure); |
724 _old_gen->ref_processor()->weak_oops_do(root_closure); |
723 } |
725 } |
724 |
726 |
725 #define GCH_SINCE_SAVE_MARKS_ITERATE_DEFN(OopClosureType, nv_suffix) \ |
727 #define GCH_SINCE_SAVE_MARKS_ITERATE_DEFN(OopClosureType, nv_suffix) \ |
726 void GenCollectedHeap:: \ |
728 void GenCollectedHeap:: \ |
727 oop_since_save_marks_iterate(int level, \ |
729 oop_since_save_marks_iterate(GenerationType gen, \ |
728 OopClosureType* cur, \ |
730 OopClosureType* cur, \ |
729 OopClosureType* older) { \ |
731 OopClosureType* older) { \ |
730 if (level == 0) { \ |
732 if (gen == YoungGen) { \ |
731 _young_gen->oop_since_save_marks_iterate##nv_suffix(cur); \ |
733 _young_gen->oop_since_save_marks_iterate##nv_suffix(cur); \ |
732 _old_gen->oop_since_save_marks_iterate##nv_suffix(older); \ |
734 _old_gen->oop_since_save_marks_iterate##nv_suffix(older); \ |
733 } else { \ |
735 } else { \ |
734 _old_gen->oop_since_save_marks_iterate##nv_suffix(cur); \ |
736 _old_gen->oop_since_save_marks_iterate##nv_suffix(cur); \ |
735 } \ |
737 } \ |
768 #else // INCLUDE_ALL_GCS |
770 #else // INCLUDE_ALL_GCS |
769 ShouldNotReachHere(); |
771 ShouldNotReachHere(); |
770 #endif // INCLUDE_ALL_GCS |
772 #endif // INCLUDE_ALL_GCS |
771 } else if (cause == GCCause::_wb_young_gc) { |
773 } else if (cause == GCCause::_wb_young_gc) { |
772 // minor collection for WhiteBox API |
774 // minor collection for WhiteBox API |
773 collect(cause, 0 /* young */); |
775 collect(cause, YoungGen); |
774 } else { |
776 } else { |
775 #ifdef ASSERT |
777 #ifdef ASSERT |
776 if (cause == GCCause::_scavenge_alot) { |
778 if (cause == GCCause::_scavenge_alot) { |
777 // minor collection only |
779 // minor collection only |
778 collect(cause, 0 /* young */); |
780 collect(cause, YoungGen); |
779 } else { |
781 } else { |
780 // Stop-the-world full collection |
782 // Stop-the-world full collection |
781 collect(cause, 1 /* old */); |
783 collect(cause, OldGen); |
782 } |
784 } |
783 #else |
785 #else |
784 // Stop-the-world full collection |
786 // Stop-the-world full collection |
785 collect(cause, 1 /* old */); |
787 collect(cause, OldGen); |
786 #endif |
788 #endif |
787 } |
789 } |
788 } |
790 } |
789 |
791 |
790 void GenCollectedHeap::collect(GCCause::Cause cause, int max_level) { |
792 void GenCollectedHeap::collect(GCCause::Cause cause, GenerationType max_generation) { |
791 // The caller doesn't have the Heap_lock |
793 // The caller doesn't have the Heap_lock |
792 assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock"); |
794 assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock"); |
793 MutexLocker ml(Heap_lock); |
795 MutexLocker ml(Heap_lock); |
794 collect_locked(cause, max_level); |
796 collect_locked(cause, max_generation); |
795 } |
797 } |
796 |
798 |
797 void GenCollectedHeap::collect_locked(GCCause::Cause cause) { |
799 void GenCollectedHeap::collect_locked(GCCause::Cause cause) { |
798 // The caller has the Heap_lock |
800 // The caller has the Heap_lock |
799 assert(Heap_lock->owned_by_self(), "this thread should own the Heap_lock"); |
801 assert(Heap_lock->owned_by_self(), "this thread should own the Heap_lock"); |
800 collect_locked(cause, 1 /* old */); |
802 collect_locked(cause, OldGen); |
801 } |
803 } |
802 |
804 |
803 // this is the private collection interface |
805 // this is the private collection interface |
804 // The Heap_lock is expected to be held on entry. |
806 // The Heap_lock is expected to be held on entry. |
805 |
807 |
806 void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) { |
808 void GenCollectedHeap::collect_locked(GCCause::Cause cause, GenerationType max_generation) { |
807 // Read the GC count while holding the Heap_lock |
809 // Read the GC count while holding the Heap_lock |
808 unsigned int gc_count_before = total_collections(); |
810 unsigned int gc_count_before = total_collections(); |
809 unsigned int full_gc_count_before = total_full_collections(); |
811 unsigned int full_gc_count_before = total_full_collections(); |
810 { |
812 { |
811 MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back |
813 MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back |
812 VM_GenCollectFull op(gc_count_before, full_gc_count_before, |
814 VM_GenCollectFull op(gc_count_before, full_gc_count_before, |
813 cause, max_level); |
815 cause, max_generation); |
814 VMThread::execute(&op); |
816 VMThread::execute(&op); |
815 } |
817 } |
816 } |
818 } |
817 |
819 |
818 #if INCLUDE_ALL_GCS |
820 #if INCLUDE_ALL_GCS |
851 } |
853 } |
852 } |
854 } |
853 #endif // INCLUDE_ALL_GCS |
855 #endif // INCLUDE_ALL_GCS |
854 |
856 |
855 void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) { |
857 void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) { |
856 do_full_collection(clear_all_soft_refs, 1 /* old */); |
858 do_full_collection(clear_all_soft_refs, OldGen); |
857 } |
859 } |
858 |
860 |
859 void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs, |
861 void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs, |
860 int max_level) { |
862 GenerationType last_generation) { |
861 int local_max_level; |
863 GenerationType local_last_generation; |
862 if (!incremental_collection_will_fail(false /* don't consult_young */) && |
864 if (!incremental_collection_will_fail(false /* don't consult_young */) && |
863 gc_cause() == GCCause::_gc_locker) { |
865 gc_cause() == GCCause::_gc_locker) { |
864 local_max_level = 0; |
866 local_last_generation = YoungGen; |
865 } else { |
867 } else { |
866 local_max_level = max_level; |
868 local_last_generation = last_generation; |
867 } |
869 } |
868 |
870 |
869 do_collection(true /* full */, |
871 do_collection(true, // full |
870 clear_all_soft_refs /* clear_all_soft_refs */, |
872 clear_all_soft_refs, // clear_all_soft_refs |
871 0 /* size */, |
873 0, // size |
872 false /* is_tlab */, |
874 false, // is_tlab |
873 local_max_level /* max_level */); |
875 local_last_generation); // last_generation |
874 // Hack XXX FIX ME !!! |
876 // Hack XXX FIX ME !!! |
875 // A scavenge may not have been attempted, or may have |
877 // A scavenge may not have been attempted, or may have |
876 // been attempted and failed, because the old gen was too full |
878 // been attempted and failed, because the old gen was too full |
877 if (local_max_level == 0 && gc_cause() == GCCause::_gc_locker && |
879 if (local_last_generation == YoungGen && gc_cause() == GCCause::_gc_locker && |
878 incremental_collection_will_fail(false /* don't consult_young */)) { |
880 incremental_collection_will_fail(false /* don't consult_young */)) { |
879 if (PrintGCDetails) { |
881 if (PrintGCDetails) { |
880 gclog_or_tty->print_cr("GC locker: Trying a full collection " |
882 gclog_or_tty->print_cr("GC locker: Trying a full collection " |
881 "because scavenge failed"); |
883 "because scavenge failed"); |
882 } |
884 } |
883 // This time allow the old gen to be collected as well |
885 // This time allow the old gen to be collected as well |
884 do_collection(true /* full */, |
886 do_collection(true, // full |
885 clear_all_soft_refs /* clear_all_soft_refs */, |
887 clear_all_soft_refs, // clear_all_soft_refs |
886 0 /* size */, |
888 0, // size |
887 false /* is_tlab */, |
889 false, // is_tlab |
888 1 /* old */ /* max_level */); |
890 OldGen); // last_generation |
889 } |
891 } |
890 } |
892 } |
891 |
893 |
892 bool GenCollectedHeap::is_in_young(oop p) { |
894 bool GenCollectedHeap::is_in_young(oop p) { |
893 bool result = ((HeapWord*)p) < _old_gen->reserved().start(); |
895 bool result = ((HeapWord*)p) < _old_gen->reserved().start(); |
1106 CompactPoint cp(_old_gen); |
1108 CompactPoint cp(_old_gen); |
1107 _old_gen->prepare_for_compaction(&cp); |
1109 _old_gen->prepare_for_compaction(&cp); |
1108 _young_gen->prepare_for_compaction(&cp); |
1110 _young_gen->prepare_for_compaction(&cp); |
1109 } |
1111 } |
1110 |
1112 |
1111 GCStats* GenCollectedHeap::gc_stats(int level) const { |
1113 GCStats* GenCollectedHeap::gc_stats(Generation* gen) const { |
1112 if (level == 0) { |
1114 return gen->gc_stats(); |
1113 return _young_gen->gc_stats(); |
|
1114 } else { |
|
1115 return _old_gen->gc_stats(); |
|
1116 } |
|
1117 } |
1115 } |
1118 |
1116 |
1119 void GenCollectedHeap::verify(bool silent, VerifyOption option /* ignored */) { |
1117 void GenCollectedHeap::verify(bool silent, VerifyOption option /* ignored */) { |
1120 if (!silent) { |
1118 if (!silent) { |
1121 gclog_or_tty->print("%s", _old_gen->name()); |
1119 gclog_or_tty->print("%s", _old_gen->name()); |