Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 6254:a2f7274eb6ef
7114678: G1: various small fixes, code cleanup, and refactoring
Summary: Various cleanups as a prelude to introducing iterators for HeapRegions.
Reviewed-by: johnc, brutisso
author | tonyp |
---|---|
date | Thu, 19 Jul 2012 15:15:54 -0700 |
parents | 3a431b605145 |
children | aaf61e68b255 |
comparison
equal
deleted
inserted
replaced
6253:db823a892a55 | 6254:a2f7274eb6ef |
---|---|
1147 | 1147 |
1148 ShouldNotReachHere(); | 1148 ShouldNotReachHere(); |
1149 } | 1149 } |
1150 | 1150 |
1151 class PostMCRemSetClearClosure: public HeapRegionClosure { | 1151 class PostMCRemSetClearClosure: public HeapRegionClosure { |
1152 G1CollectedHeap* _g1h; | |
1152 ModRefBarrierSet* _mr_bs; | 1153 ModRefBarrierSet* _mr_bs; |
1153 public: | 1154 public: |
1154 PostMCRemSetClearClosure(ModRefBarrierSet* mr_bs) : _mr_bs(mr_bs) {} | 1155 PostMCRemSetClearClosure(G1CollectedHeap* g1h, ModRefBarrierSet* mr_bs) : |
1156 _g1h(g1h), _mr_bs(mr_bs) { } | |
1155 bool doHeapRegion(HeapRegion* r) { | 1157 bool doHeapRegion(HeapRegion* r) { |
1156 r->reset_gc_time_stamp(); | 1158 if (r->continuesHumongous()) { |
1157 if (r->continuesHumongous()) | |
1158 return false; | 1159 return false; |
1160 } | |
1161 _g1h->reset_gc_time_stamps(r); | |
1159 HeapRegionRemSet* hrrs = r->rem_set(); | 1162 HeapRegionRemSet* hrrs = r->rem_set(); |
1160 if (hrrs != NULL) hrrs->clear(); | 1163 if (hrrs != NULL) hrrs->clear(); |
1161 // You might think here that we could clear just the cards | 1164 // You might think here that we could clear just the cards |
1162 // corresponding to the used region. But no: if we leave a dirty card | 1165 // corresponding to the used region. But no: if we leave a dirty card |
1163 // in a region we might allocate into, then it would prevent that card | 1166 // in a region we might allocate into, then it would prevent that card |
1166 _mr_bs->clear(MemRegion(r->bottom(), r->end())); | 1169 _mr_bs->clear(MemRegion(r->bottom(), r->end())); |
1167 return false; | 1170 return false; |
1168 } | 1171 } |
1169 }; | 1172 }; |
1170 | 1173 |
1171 | 1174 void G1CollectedHeap::clear_rsets_post_compaction() { |
1172 class PostMCRemSetInvalidateClosure: public HeapRegionClosure { | 1175 PostMCRemSetClearClosure rs_clear(this, mr_bs()); |
1173 ModRefBarrierSet* _mr_bs; | 1176 heap_region_iterate(&rs_clear); |
1174 public: | 1177 } |
1175 PostMCRemSetInvalidateClosure(ModRefBarrierSet* mr_bs) : _mr_bs(mr_bs) {} | |
1176 bool doHeapRegion(HeapRegion* r) { | |
1177 if (r->continuesHumongous()) return false; | |
1178 if (r->used_region().word_size() != 0) { | |
1179 _mr_bs->invalidate(r->used_region(), true /*whole heap*/); | |
1180 } | |
1181 return false; | |
1182 } | |
1183 }; | |
1184 | 1178 |
1185 class RebuildRSOutOfRegionClosure: public HeapRegionClosure { | 1179 class RebuildRSOutOfRegionClosure: public HeapRegionClosure { |
1186 G1CollectedHeap* _g1h; | 1180 G1CollectedHeap* _g1h; |
1187 UpdateRSOopClosure _cl; | 1181 UpdateRSOopClosure _cl; |
1188 int _worker_i; | 1182 int _worker_i; |
1227 // We only generate output for non-empty regions. | 1221 // We only generate output for non-empty regions. |
1228 if (!hr->is_empty()) { | 1222 if (!hr->is_empty()) { |
1229 if (!hr->isHumongous()) { | 1223 if (!hr->isHumongous()) { |
1230 _hr_printer->post_compaction(hr, G1HRPrinter::Old); | 1224 _hr_printer->post_compaction(hr, G1HRPrinter::Old); |
1231 } else if (hr->startsHumongous()) { | 1225 } else if (hr->startsHumongous()) { |
1232 if (hr->capacity() == HeapRegion::GrainBytes) { | 1226 if (hr->region_num() == 1) { |
1233 // single humongous region | 1227 // single humongous region |
1234 _hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous); | 1228 _hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous); |
1235 } else { | 1229 } else { |
1236 _hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous); | 1230 _hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous); |
1237 } | 1231 } |
1244 } | 1238 } |
1245 | 1239 |
1246 PostCompactionPrinterClosure(G1HRPrinter* hr_printer) | 1240 PostCompactionPrinterClosure(G1HRPrinter* hr_printer) |
1247 : _hr_printer(hr_printer) { } | 1241 : _hr_printer(hr_printer) { } |
1248 }; | 1242 }; |
1243 | |
1244 void G1CollectedHeap::print_hrs_post_compaction() { | |
1245 PostCompactionPrinterClosure cl(hr_printer()); | |
1246 heap_region_iterate(&cl); | |
1247 } | |
1249 | 1248 |
1250 bool G1CollectedHeap::do_collection(bool explicit_gc, | 1249 bool G1CollectedHeap::do_collection(bool explicit_gc, |
1251 bool clear_all_soft_refs, | 1250 bool clear_all_soft_refs, |
1252 size_t word_size) { | 1251 size_t word_size) { |
1253 assert_at_safepoint(true /* should_be_vm_thread */); | 1252 assert_at_safepoint(true /* should_be_vm_thread */); |
1400 | 1399 |
1401 reset_gc_time_stamp(); | 1400 reset_gc_time_stamp(); |
1402 // Since everything potentially moved, we will clear all remembered | 1401 // Since everything potentially moved, we will clear all remembered |
1403 // sets, and clear all cards. Later we will rebuild remebered | 1402 // sets, and clear all cards. Later we will rebuild remebered |
1404 // sets. We will also reset the GC time stamps of the regions. | 1403 // sets. We will also reset the GC time stamps of the regions. |
1405 PostMCRemSetClearClosure rs_clear(mr_bs()); | 1404 clear_rsets_post_compaction(); |
1406 heap_region_iterate(&rs_clear); | 1405 check_gc_time_stamps(); |
1407 | 1406 |
1408 // Resize the heap if necessary. | 1407 // Resize the heap if necessary. |
1409 resize_if_necessary_after_full_collection(explicit_gc ? 0 : word_size); | 1408 resize_if_necessary_after_full_collection(explicit_gc ? 0 : word_size); |
1410 | 1409 |
1411 if (_hr_printer.is_active()) { | 1410 if (_hr_printer.is_active()) { |
1412 // We should do this after we potentially resize the heap so | 1411 // We should do this after we potentially resize the heap so |
1413 // that all the COMMIT / UNCOMMIT events are generated before | 1412 // that all the COMMIT / UNCOMMIT events are generated before |
1414 // the end GC event. | 1413 // the end GC event. |
1415 | 1414 |
1416 PostCompactionPrinterClosure cl(hr_printer()); | 1415 print_hrs_post_compaction(); |
1417 heap_region_iterate(&cl); | |
1418 | |
1419 _hr_printer.end_gc(true /* full */, (size_t) total_collections()); | 1416 _hr_printer.end_gc(true /* full */, (size_t) total_collections()); |
1420 } | 1417 } |
1421 | 1418 |
1422 if (_cg1r->use_cache()) { | 1419 if (_cg1r->use_cache()) { |
1423 _cg1r->clear_and_record_card_counts(); | 1420 _cg1r->clear_and_record_card_counts(); |
2261 | 2258 |
2262 size_t G1CollectedHeap::capacity() const { | 2259 size_t G1CollectedHeap::capacity() const { |
2263 return _g1_committed.byte_size(); | 2260 return _g1_committed.byte_size(); |
2264 } | 2261 } |
2265 | 2262 |
2263 void G1CollectedHeap::reset_gc_time_stamps(HeapRegion* hr) { | |
2264 assert(!hr->continuesHumongous(), "pre-condition"); | |
2265 hr->reset_gc_time_stamp(); | |
2266 if (hr->startsHumongous()) { | |
2267 uint first_index = hr->hrs_index() + 1; | |
2268 uint last_index = hr->last_hc_index(); | |
2269 for (uint i = first_index; i < last_index; i += 1) { | |
2270 HeapRegion* chr = region_at(i); | |
2271 assert(chr->continuesHumongous(), "sanity"); | |
2272 chr->reset_gc_time_stamp(); | |
2273 } | |
2274 } | |
2275 } | |
2276 | |
2277 #ifndef PRODUCT | |
2278 class CheckGCTimeStampsHRClosure : public HeapRegionClosure { | |
2279 private: | |
2280 unsigned _gc_time_stamp; | |
2281 bool _failures; | |
2282 | |
2283 public: | |
2284 CheckGCTimeStampsHRClosure(unsigned gc_time_stamp) : | |
2285 _gc_time_stamp(gc_time_stamp), _failures(false) { } | |
2286 | |
2287 virtual bool doHeapRegion(HeapRegion* hr) { | |
2288 unsigned region_gc_time_stamp = hr->get_gc_time_stamp(); | |
2289 if (_gc_time_stamp != region_gc_time_stamp) { | |
2290 gclog_or_tty->print_cr("Region "HR_FORMAT" has GC time stamp = %d, " | |
2291 "expected %d", HR_FORMAT_PARAMS(hr), | |
2292 region_gc_time_stamp, _gc_time_stamp); | |
2293 _failures = true; | |
2294 } | |
2295 return false; | |
2296 } | |
2297 | |
2298 bool failures() { return _failures; } | |
2299 }; | |
2300 | |
2301 void G1CollectedHeap::check_gc_time_stamps() { | |
2302 CheckGCTimeStampsHRClosure cl(_gc_time_stamp); | |
2303 heap_region_iterate(&cl); | |
2304 guarantee(!cl.failures(), "all GC time stamps should have been reset"); | |
2305 } | |
2306 #endif // PRODUCT | |
2307 | |
2266 void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, | 2308 void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, |
2267 DirtyCardQueue* into_cset_dcq, | 2309 DirtyCardQueue* into_cset_dcq, |
2268 bool concurrent, | 2310 bool concurrent, |
2269 int worker_i) { | 2311 int worker_i) { |
2270 // Clean cards in the hot card cache | 2312 // Clean cards in the hot card cache |
2528 OopClosure* _cl; | 2570 OopClosure* _cl; |
2529 public: | 2571 public: |
2530 IterateOopClosureRegionClosure(MemRegion mr, OopClosure* cl) | 2572 IterateOopClosureRegionClosure(MemRegion mr, OopClosure* cl) |
2531 : _mr(mr), _cl(cl) {} | 2573 : _mr(mr), _cl(cl) {} |
2532 bool doHeapRegion(HeapRegion* r) { | 2574 bool doHeapRegion(HeapRegion* r) { |
2533 if (! r->continuesHumongous()) { | 2575 if (!r->continuesHumongous()) { |
2534 r->oop_iterate(_cl); | 2576 r->oop_iterate(_cl); |
2535 } | 2577 } |
2536 return false; | 2578 return false; |
2537 } | 2579 } |
2538 }; | 2580 }; |
2599 | 2641 |
2600 void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { | 2642 void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { |
2601 _hrs.iterate(cl); | 2643 _hrs.iterate(cl); |
2602 } | 2644 } |
2603 | 2645 |
2604 void G1CollectedHeap::heap_region_iterate_from(HeapRegion* r, | |
2605 HeapRegionClosure* cl) const { | |
2606 _hrs.iterate_from(r, cl); | |
2607 } | |
2608 | |
2609 void | 2646 void |
2610 G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl, | 2647 G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl, |
2611 uint worker, | 2648 uint worker_id, |
2612 uint no_of_par_workers, | 2649 uint no_of_par_workers, |
2613 jint claim_value) { | 2650 jint claim_value) { |
2614 const uint regions = n_regions(); | 2651 const uint regions = n_regions(); |
2615 const uint max_workers = (G1CollectedHeap::use_parallel_gc_threads() ? | 2652 const uint max_workers = (G1CollectedHeap::use_parallel_gc_threads() ? |
2616 no_of_par_workers : | 2653 no_of_par_workers : |
2617 1); | 2654 1); |
2618 assert(UseDynamicNumberOfGCThreads || | 2655 assert(UseDynamicNumberOfGCThreads || |
2619 no_of_par_workers == workers()->total_workers(), | 2656 no_of_par_workers == workers()->total_workers(), |
2620 "Non dynamic should use fixed number of workers"); | 2657 "Non dynamic should use fixed number of workers"); |
2621 // try to spread out the starting points of the workers | 2658 // try to spread out the starting points of the workers |
2622 const uint start_index = regions / max_workers * worker; | 2659 const HeapRegion* start_hr = |
2660 start_region_for_worker(worker_id, no_of_par_workers); | |
2661 const uint start_index = start_hr->hrs_index(); | |
2623 | 2662 |
2624 // each worker will actually look at all regions | 2663 // each worker will actually look at all regions |
2625 for (uint count = 0; count < regions; ++count) { | 2664 for (uint count = 0; count < regions; ++count) { |
2626 const uint index = (start_index + count) % regions; | 2665 const uint index = (start_index + count) % regions; |
2627 assert(0 <= index && index < regions, "sanity"); | 2666 assert(0 <= index && index < regions, "sanity"); |
2859 OrderAccess::storestore(); | 2898 OrderAccess::storestore(); |
2860 _worker_cset_start_region_time_stamp[worker_i] = gc_time_stamp; | 2899 _worker_cset_start_region_time_stamp[worker_i] = gc_time_stamp; |
2861 return result; | 2900 return result; |
2862 } | 2901 } |
2863 | 2902 |
2903 HeapRegion* G1CollectedHeap::start_region_for_worker(uint worker_i, | |
2904 uint no_of_par_workers) { | |
2905 uint worker_num = | |
2906 G1CollectedHeap::use_parallel_gc_threads() ? no_of_par_workers : 1U; | |
2907 assert(UseDynamicNumberOfGCThreads || | |
2908 no_of_par_workers == workers()->total_workers(), | |
2909 "Non dynamic should use fixed number of workers"); | |
2910 const uint start_index = n_regions() * worker_i / worker_num; | |
2911 return region_at(start_index); | |
2912 } | |
2913 | |
2864 void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) { | 2914 void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) { |
2865 HeapRegion* r = g1_policy()->collection_set(); | 2915 HeapRegion* r = g1_policy()->collection_set(); |
2866 while (r != NULL) { | 2916 while (r != NULL) { |
2867 HeapRegion* next = r->next_in_collection_set(); | 2917 HeapRegion* next = r->next_in_collection_set(); |
2868 if (cl->doHeapRegion(r)) { | 2918 if (cl->doHeapRegion(r)) { |
2970 void G1CollectedHeap::prepare_for_verify() { | 3020 void G1CollectedHeap::prepare_for_verify() { |
2971 if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { | 3021 if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { |
2972 ensure_parsability(false); | 3022 ensure_parsability(false); |
2973 } | 3023 } |
2974 g1_rem_set()->prepare_for_verify(); | 3024 g1_rem_set()->prepare_for_verify(); |
3025 } | |
3026 | |
3027 bool G1CollectedHeap::allocated_since_marking(oop obj, HeapRegion* hr, | |
3028 VerifyOption vo) { | |
3029 switch (vo) { | |
3030 case VerifyOption_G1UsePrevMarking: | |
3031 return hr->obj_allocated_since_prev_marking(obj); | |
3032 case VerifyOption_G1UseNextMarking: | |
3033 return hr->obj_allocated_since_next_marking(obj); | |
3034 case VerifyOption_G1UseMarkWord: | |
3035 return false; | |
3036 default: | |
3037 ShouldNotReachHere(); | |
3038 } | |
3039 return false; // keep some compilers happy | |
3040 } | |
3041 | |
3042 HeapWord* G1CollectedHeap::top_at_mark_start(HeapRegion* hr, VerifyOption vo) { | |
3043 switch (vo) { | |
3044 case VerifyOption_G1UsePrevMarking: return hr->prev_top_at_mark_start(); | |
3045 case VerifyOption_G1UseNextMarking: return hr->next_top_at_mark_start(); | |
3046 case VerifyOption_G1UseMarkWord: return NULL; | |
3047 default: ShouldNotReachHere(); | |
3048 } | |
3049 return NULL; // keep some compilers happy | |
3050 } | |
3051 | |
3052 bool G1CollectedHeap::is_marked(oop obj, VerifyOption vo) { | |
3053 switch (vo) { | |
3054 case VerifyOption_G1UsePrevMarking: return isMarkedPrev(obj); | |
3055 case VerifyOption_G1UseNextMarking: return isMarkedNext(obj); | |
3056 case VerifyOption_G1UseMarkWord: return obj->is_gc_marked(); | |
3057 default: ShouldNotReachHere(); | |
3058 } | |
3059 return false; // keep some compilers happy | |
3060 } | |
3061 | |
3062 const char* G1CollectedHeap::top_at_mark_start_str(VerifyOption vo) { | |
3063 switch (vo) { | |
3064 case VerifyOption_G1UsePrevMarking: return "PTAMS"; | |
3065 case VerifyOption_G1UseNextMarking: return "NTAMS"; | |
3066 case VerifyOption_G1UseMarkWord: return "NONE"; | |
3067 default: ShouldNotReachHere(); | |
3068 } | |
3069 return NULL; // keep some compilers happy | |
2975 } | 3070 } |
2976 | 3071 |
2977 class VerifyLivenessOopClosure: public OopClosure { | 3072 class VerifyLivenessOopClosure: public OopClosure { |
2978 G1CollectedHeap* _g1h; | 3073 G1CollectedHeap* _g1h; |
2979 VerifyOption _vo; | 3074 VerifyOption _vo; |
3059 } | 3154 } |
3060 }; | 3155 }; |
3061 | 3156 |
3062 class VerifyRegionClosure: public HeapRegionClosure { | 3157 class VerifyRegionClosure: public HeapRegionClosure { |
3063 private: | 3158 private: |
3064 bool _par; | 3159 bool _par; |
3065 VerifyOption _vo; | 3160 VerifyOption _vo; |
3066 bool _failures; | 3161 bool _failures; |
3067 public: | 3162 public: |
3068 // _vo == UsePrevMarking -> use "prev" marking information, | 3163 // _vo == UsePrevMarking -> use "prev" marking information, |
3069 // _vo == UseNextMarking -> use "next" marking information, | 3164 // _vo == UseNextMarking -> use "next" marking information, |
3070 // _vo == UseMarkWord -> use mark word from object header. | 3165 // _vo == UseMarkWord -> use mark word from object header. |
3071 VerifyRegionClosure(bool par, VerifyOption vo) | 3166 VerifyRegionClosure(bool par, VerifyOption vo) |
3076 bool failures() { | 3171 bool failures() { |
3077 return _failures; | 3172 return _failures; |
3078 } | 3173 } |
3079 | 3174 |
3080 bool doHeapRegion(HeapRegion* r) { | 3175 bool doHeapRegion(HeapRegion* r) { |
3081 guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue, | |
3082 "Should be unclaimed at verify points."); | |
3083 if (!r->continuesHumongous()) { | 3176 if (!r->continuesHumongous()) { |
3084 bool failures = false; | 3177 bool failures = false; |
3085 r->verify(_vo, &failures); | 3178 r->verify(_vo, &failures); |
3086 if (failures) { | 3179 if (failures) { |
3087 _failures = true; | 3180 _failures = true; |
5610 | 5703 |
5611 size_t hr_used = hr->used(); | 5704 size_t hr_used = hr->used(); |
5612 size_t hr_capacity = hr->capacity(); | 5705 size_t hr_capacity = hr->capacity(); |
5613 size_t hr_pre_used = 0; | 5706 size_t hr_pre_used = 0; |
5614 _humongous_set.remove_with_proxy(hr, humongous_proxy_set); | 5707 _humongous_set.remove_with_proxy(hr, humongous_proxy_set); |
5708 // We need to read this before we make the region non-humongous, | |
5709 // otherwise the information will be gone. | |
5710 uint last_index = hr->last_hc_index(); | |
5615 hr->set_notHumongous(); | 5711 hr->set_notHumongous(); |
5616 free_region(hr, &hr_pre_used, free_list, par); | 5712 free_region(hr, &hr_pre_used, free_list, par); |
5617 | 5713 |
5618 uint i = hr->hrs_index() + 1; | 5714 uint i = hr->hrs_index() + 1; |
5619 uint num = 1; | 5715 while (i < last_index) { |
5620 while (i < n_regions()) { | |
5621 HeapRegion* curr_hr = region_at(i); | 5716 HeapRegion* curr_hr = region_at(i); |
5622 if (!curr_hr->continuesHumongous()) { | 5717 assert(curr_hr->continuesHumongous(), "invariant"); |
5623 break; | |
5624 } | |
5625 curr_hr->set_notHumongous(); | 5718 curr_hr->set_notHumongous(); |
5626 free_region(curr_hr, &hr_pre_used, free_list, par); | 5719 free_region(curr_hr, &hr_pre_used, free_list, par); |
5627 num += 1; | |
5628 i += 1; | 5720 i += 1; |
5629 } | 5721 } |
5630 assert(hr_pre_used == hr_used, | 5722 assert(hr_pre_used == hr_used, |
5631 err_msg("hr_pre_used: "SIZE_FORMAT" and hr_used: "SIZE_FORMAT" " | 5723 err_msg("hr_pre_used: "SIZE_FORMAT" and hr_used: "SIZE_FORMAT" " |
5632 "should be the same", hr_pre_used, hr_used)); | 5724 "should be the same", hr_pre_used, hr_used)); |
5730 } | 5822 } |
5731 } | 5823 } |
5732 | 5824 |
5733 void G1CollectedHeap::verify_dirty_young_regions() { | 5825 void G1CollectedHeap::verify_dirty_young_regions() { |
5734 verify_dirty_young_list(_young_list->first_region()); | 5826 verify_dirty_young_list(_young_list->first_region()); |
5735 verify_dirty_young_list(_young_list->first_survivor_region()); | |
5736 } | 5827 } |
5737 #endif | 5828 #endif |
5738 | 5829 |
5739 void G1CollectedHeap::cleanUpCardTable() { | 5830 void G1CollectedHeap::cleanUpCardTable() { |
5740 CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set()); | 5831 CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set()); |