1006 } |
1006 } |
1007 |
1007 |
1008 verifier->check_bitmaps(caller); |
1008 verifier->check_bitmaps(caller); |
1009 } |
1009 } |
1010 |
1010 |
1011 class G1UpdateRemSetTrackingBeforeRebuild : public HeapRegionClosure { |
1011 class G1UpdateRemSetTrackingBeforeRebuildTask : public AbstractGangTask { |
1012 G1CollectedHeap* _g1h; |
1012 G1CollectedHeap* _g1h; |
1013 G1ConcurrentMark* _cm; |
1013 G1ConcurrentMark* _cm; |
|
1014 HeapRegionClaimer _hrclaimer; |
|
1015 uint volatile _total_selected_for_rebuild; |
1014 |
1016 |
1015 G1PrintRegionLivenessInfoClosure _cl; |
1017 G1PrintRegionLivenessInfoClosure _cl; |
1016 |
1018 |
1017 uint _num_regions_selected_for_rebuild; // The number of regions actually selected for rebuild. |
1019 class G1UpdateRemSetTrackingBeforeRebuild : public HeapRegionClosure { |
1018 |
1020 G1CollectedHeap* _g1h; |
1019 void update_remset_before_rebuild(HeapRegion * hr) { |
1021 G1ConcurrentMark* _cm; |
1020 G1RemSetTrackingPolicy* tracking_policy = _g1h->g1_policy()->remset_tracker(); |
1022 |
1021 |
1023 G1PrintRegionLivenessInfoClosure* _cl; |
1022 size_t live_bytes = _cm->liveness(hr->hrm_index()) * HeapWordSize; |
1024 |
1023 bool selected_for_rebuild = tracking_policy->update_before_rebuild(hr, live_bytes); |
1025 uint _num_regions_selected_for_rebuild; // The number of regions actually selected for rebuild. |
1024 if (selected_for_rebuild) { |
1026 |
1025 _num_regions_selected_for_rebuild++; |
1027 void update_remset_before_rebuild(HeapRegion * hr) { |
1026 } |
1028 G1RemSetTrackingPolicy* tracking_policy = _g1h->g1_policy()->remset_tracker(); |
1027 _cm->update_top_at_rebuild_start(hr); |
1029 |
1028 } |
1030 size_t const live_bytes = _cm->liveness(hr->hrm_index()) * HeapWordSize; |
1029 |
1031 bool selected_for_rebuild = tracking_policy->update_before_rebuild(hr, live_bytes); |
1030 void distribute_marked_bytes(HeapRegion* hr, size_t marked_words) { |
1032 if (selected_for_rebuild) { |
1031 uint const region_idx = hr->hrm_index(); |
1033 _num_regions_selected_for_rebuild++; |
1032 uint num_regions_in_humongous = (uint)G1CollectedHeap::humongous_obj_size_in_regions(marked_words); |
|
1033 |
|
1034 for (uint i = region_idx; i < (region_idx + num_regions_in_humongous); i++) { |
|
1035 HeapRegion* const r = _g1h->region_at(i); |
|
1036 size_t const words_to_add = MIN2(HeapRegion::GrainWords, marked_words); |
|
1037 assert(words_to_add > 0, "Out of space to distribute before end of humongous object in region %u (starts %u)", i, region_idx); |
|
1038 |
|
1039 log_trace(gc, marking)("Adding " SIZE_FORMAT " words to humongous region %u (%s)", |
|
1040 words_to_add, i, r->get_type_str()); |
|
1041 r->add_to_marked_bytes(words_to_add * HeapWordSize); |
|
1042 marked_words -= words_to_add; |
|
1043 } |
|
1044 assert(marked_words == 0, |
|
1045 SIZE_FORMAT " words left after distributing space across %u regions", |
|
1046 marked_words, num_regions_in_humongous); |
|
1047 } |
|
1048 |
|
1049 void update_marked_bytes(HeapRegion* hr) { |
|
1050 uint const region_idx = hr->hrm_index(); |
|
1051 size_t marked_words = _cm->liveness(region_idx); |
|
1052 // The marking attributes the object's size completely to the humongous starts |
|
1053 // region. We need to distribute this value across the entire set of regions a |
|
1054 // humongous object spans. |
|
1055 if (hr->is_humongous()) { |
|
1056 assert(hr->is_starts_humongous() || marked_words == 0, |
|
1057 "Should not have marked words " SIZE_FORMAT " in non-starts humongous region %u (%s)", |
|
1058 marked_words, region_idx, hr->get_type_str()); |
|
1059 |
|
1060 if (marked_words > 0) { |
|
1061 distribute_marked_bytes(hr, marked_words); |
|
1062 } |
1034 } |
1063 } else { |
1035 _cm->update_top_at_rebuild_start(hr); |
1064 log_trace(gc, marking)("Adding " SIZE_FORMAT " words to region %u (%s)", marked_words, region_idx, hr->get_type_str()); |
1036 } |
1065 hr->add_to_marked_bytes(marked_words * HeapWordSize); |
1037 |
1066 } |
1038 // Distribute the given words across the humongous object starting with hr and |
1067 } |
1039 // note end of marking. |
|
1040 void distribute_marked_bytes(HeapRegion* hr, size_t marked_words) { |
|
1041 uint const region_idx = hr->hrm_index(); |
|
1042 size_t const obj_size_in_words = (size_t)oop(hr->bottom())->size(); |
|
1043 uint const num_regions_in_humongous = (uint)G1CollectedHeap::humongous_obj_size_in_regions(obj_size_in_words); |
|
1044 |
|
1045 // "Distributing" zero words means that we only note end of marking for these |
|
1046 // regions. |
|
1047 assert(marked_words == 0 || obj_size_in_words == marked_words, |
|
1048 "Marked words should either be 0 or the same as humongous object (" SIZE_FORMAT ") but is " SIZE_FORMAT, |
|
1049 obj_size_in_words, marked_words); |
|
1050 |
|
1051 for (uint i = region_idx; i < (region_idx + num_regions_in_humongous); i++) { |
|
1052 HeapRegion* const r = _g1h->region_at(i); |
|
1053 size_t const words_to_add = MIN2(HeapRegion::GrainWords, marked_words); |
|
1054 |
|
1055 log_trace(gc, marking)("Adding " SIZE_FORMAT " words to humongous region %u (%s)", |
|
1056 words_to_add, i, r->get_type_str()); |
|
1057 add_marked_bytes_and_note_end(r, words_to_add * HeapWordSize); |
|
1058 marked_words -= words_to_add; |
|
1059 } |
|
1060 assert(marked_words == 0, |
|
1061 SIZE_FORMAT " words left after distributing space across %u regions", |
|
1062 marked_words, num_regions_in_humongous); |
|
1063 } |
|
1064 |
|
1065 void update_marked_bytes(HeapRegion* hr) { |
|
1066 uint const region_idx = hr->hrm_index(); |
|
1067 size_t const marked_words = _cm->liveness(region_idx); |
|
1068 // The marking attributes the object's size completely to the humongous starts |
|
1069 // region. We need to distribute this value across the entire set of regions a |
|
1070 // humongous object spans. |
|
1071 if (hr->is_humongous()) { |
|
1072 assert(hr->is_starts_humongous() || marked_words == 0, |
|
1073 "Should not have marked words " SIZE_FORMAT " in non-starts humongous region %u (%s)", |
|
1074 marked_words, region_idx, hr->get_type_str()); |
|
1075 if (hr->is_starts_humongous()) { |
|
1076 distribute_marked_bytes(hr, marked_words); |
|
1077 } |
|
1078 } else { |
|
1079 log_trace(gc, marking)("Adding " SIZE_FORMAT " words to region %u (%s)", marked_words, region_idx, hr->get_type_str()); |
|
1080 add_marked_bytes_and_note_end(hr, marked_words * HeapWordSize); |
|
1081 } |
|
1082 } |
|
1083 |
|
1084 void add_marked_bytes_and_note_end(HeapRegion* hr, size_t marked_bytes) { |
|
1085 hr->add_to_marked_bytes(marked_bytes); |
|
1086 _cl->do_heap_region(hr); |
|
1087 hr->note_end_of_marking(); |
|
1088 } |
|
1089 |
|
1090 public: |
|
1091 G1UpdateRemSetTrackingBeforeRebuild(G1CollectedHeap* g1h, G1ConcurrentMark* cm, G1PrintRegionLivenessInfoClosure* cl) : |
|
1092 _g1h(g1h), _cm(cm), _num_regions_selected_for_rebuild(0), _cl(cl) { } |
|
1093 |
|
1094 virtual bool do_heap_region(HeapRegion* r) { |
|
1095 update_remset_before_rebuild(r); |
|
1096 update_marked_bytes(r); |
|
1097 |
|
1098 return false; |
|
1099 } |
|
1100 |
|
1101 uint num_selected_for_rebuild() const { return _num_regions_selected_for_rebuild; } |
|
1102 }; |
1068 |
1103 |
1069 public: |
1104 public: |
1070 G1UpdateRemSetTrackingBeforeRebuild(G1CollectedHeap* g1h, G1ConcurrentMark* cm) : |
1105 G1UpdateRemSetTrackingBeforeRebuildTask(G1CollectedHeap* g1h, G1ConcurrentMark* cm, uint num_workers) : |
1071 _g1h(g1h), _cm(cm), _cl("Post-Marking"), _num_regions_selected_for_rebuild(0) { } |
1106 AbstractGangTask("G1 Update RemSet Tracking Before Rebuild"), |
1072 |
1107 _g1h(g1h), _cm(cm), _hrclaimer(num_workers), _total_selected_for_rebuild(0), _cl("Post-Marking") { } |
1073 virtual bool do_heap_region(HeapRegion* r) { |
1108 |
1074 update_remset_before_rebuild(r); |
1109 virtual void work(uint worker_id) { |
1075 update_marked_bytes(r); |
1110 G1UpdateRemSetTrackingBeforeRebuild update_cl(_g1h, _cm, &_cl); |
1076 if (log_is_enabled(Trace, gc, liveness)) { |
1111 _g1h->heap_region_par_iterate_from_worker_offset(&update_cl, &_hrclaimer, worker_id); |
1077 _cl.do_heap_region(r); |
1112 Atomic::add(update_cl.num_selected_for_rebuild(), &_total_selected_for_rebuild); |
1078 } |
1113 } |
1079 r->note_end_of_marking(); |
1114 |
1080 return false; |
1115 uint total_selected_for_rebuild() const { return _total_selected_for_rebuild; } |
1081 } |
1116 |
1082 |
1117 // Number of regions for which roughly one thread should be spawned for this work. |
1083 uint num_selected_for_rebuild() const { return _num_regions_selected_for_rebuild; } |
1118 static const uint RegionsPerThread = 384; |
1084 }; |
1119 }; |
1085 |
1120 |
1086 class G1UpdateRemSetTrackingAfterRebuild : public HeapRegionClosure { |
1121 class G1UpdateRemSetTrackingAfterRebuild : public HeapRegionClosure { |
1087 G1CollectedHeap* _g1h; |
1122 G1CollectedHeap* _g1h; |
1088 public: |
1123 public: |
1135 |
1170 |
1136 // Install newly created mark bitmap as "prev". |
1171 // Install newly created mark bitmap as "prev". |
1137 swap_mark_bitmaps(); |
1172 swap_mark_bitmaps(); |
1138 { |
1173 { |
1139 GCTraceTime(Debug, gc, phases) debug("Update Remembered Set Tracking Before Rebuild", _gc_timer_cm); |
1174 GCTraceTime(Debug, gc, phases) debug("Update Remembered Set Tracking Before Rebuild", _gc_timer_cm); |
1140 G1UpdateRemSetTrackingBeforeRebuild cl(_g1h, this); |
1175 |
1141 _g1h->heap_region_iterate(&cl); |
1176 uint const workers_by_capacity = (_g1h->num_regions() + G1UpdateRemSetTrackingBeforeRebuildTask::RegionsPerThread - 1) / |
|
1177 G1UpdateRemSetTrackingBeforeRebuildTask::RegionsPerThread; |
|
1178 uint const num_workers = MIN2(_g1h->workers()->active_workers(), workers_by_capacity); |
|
1179 |
|
1180 G1UpdateRemSetTrackingBeforeRebuildTask cl(_g1h, this, num_workers); |
|
1181 log_debug(gc,ergo)("Running %s using %u workers for %u regions in heap", cl.name(), num_workers, _g1h->num_regions()); |
|
1182 _g1h->workers()->run_task(&cl, num_workers); |
|
1183 |
1142 log_debug(gc, remset, tracking)("Remembered Set Tracking update regions total %u, selected %u", |
1184 log_debug(gc, remset, tracking)("Remembered Set Tracking update regions total %u, selected %u", |
1143 _g1h->num_regions(), cl.num_selected_for_rebuild()); |
1185 _g1h->num_regions(), cl.total_selected_for_rebuild()); |
1144 } |
1186 } |
1145 { |
1187 { |
1146 GCTraceTime(Debug, gc, phases) debug("Reclaim Empty Regions", _gc_timer_cm); |
1188 GCTraceTime(Debug, gc, phases) debug("Reclaim Empty Regions", _gc_timer_cm); |
1147 reclaim_empty_regions(); |
1189 reclaim_empty_regions(); |
1148 } |
1190 } |