< prev index next >

src/hotspot/share/gc/g1/g1RemSet.cpp

Print this page
rev 56956 : 8141637: Parallelize single threaded heap region iteration during Pre Evacuate Collection Set
Reviewed-by:


 179 
 180       bool marked_as_dirty = Atomic::cmpxchg(true, &_contains[region], false) == false;
 181       if (marked_as_dirty) {
 182         uint allocated = Atomic::add(1u, &_cur_idx) - 1;
 183         _buffer[allocated] = region;
 184       }
 185     }
 186 
 187     // Creates the union of this and the other G1DirtyRegions.
 188     void merge(const G1DirtyRegions* other) {
 189       for (uint i = 0; i < other->size(); i++) {
 190         uint region = other->at(i);
 191         if (!_contains[region]) {
 192           _buffer[_cur_idx++] = region;
 193           _contains[region] = true;
 194         }
 195       }
 196     }
 197   };
 198 
 199   // Creates a snapshot of the current _top values at the start of collection to
 200   // filter out card marks that we do not want to scan.
 201   class G1ResetScanTopClosure : public HeapRegionClosure {
 202     G1RemSetScanState* _scan_state;
 203 
 204   public:
 205     G1ResetScanTopClosure(G1RemSetScanState* scan_state) : _scan_state(scan_state) { }
 206 
 207     virtual bool do_heap_region(HeapRegion* r) {
 208       uint hrm_index = r->hrm_index();
 209       if (r->in_collection_set()) {
 210         // Young regions had their card table marked as young at their allocation;
 211         // we need to make sure that these marks are cleared at the end of GC, *but*
 212         // they should not be scanned for cards.
 213         // So directly add them to the "all_dirty_regions".
 214         // Same for regions in the (initial) collection set: they may contain cards from
 215         // the log buffers, make sure they are cleaned.
 216         _scan_state->add_all_dirty_region(hrm_index);
 217        } else if (r->is_old_or_humongous_or_archive()) {
 218         _scan_state->set_scan_top(hrm_index, r->top());
 219        }
 220        return false;
 221      }
 222   };
 223   // For each region, contains the maximum top() value to be used during this garbage
 224   // collection. Subsumes common checks like filtering out everything but old and
 225   // humongous regions outside the collection set.
 226   // This is valid because we are not interested in scanning stray remembered set
 227   // entries from free or archive regions.
 228   HeapWord** _scan_top;
 229 
 230   class G1ClearCardTableTask : public AbstractGangTask {
 231     G1CollectedHeap* _g1h;
 232     G1DirtyRegions* _regions;
 233     uint _chunk_length;
 234 
 235     uint volatile _cur_dirty_regions;
 236 
 237     G1RemSetScanState* _scan_state;
 238 
 239   public:
 240     G1ClearCardTableTask(G1CollectedHeap* g1h,
 241                          G1DirtyRegions* regions,
 242                          uint chunk_length,


 318   void initialize(size_t max_regions) {
 319     assert(_collection_set_iter_state == NULL, "Must not be initialized twice");
 320     _max_regions = max_regions;
 321     _collection_set_iter_state = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_regions, mtGC);
 322     _card_table_scan_state = NEW_C_HEAP_ARRAY(uint, max_regions, mtGC);
 323     _num_total_scan_chunks = max_regions * _scan_chunks_per_region;
 324     _region_scan_chunks = NEW_C_HEAP_ARRAY(bool, _num_total_scan_chunks, mtGC);
 325 
 326     _scan_chunks_shift = (uint8_t)log2_intptr(HeapRegion::CardsPerRegion / _scan_chunks_per_region);
 327     _scan_top = NEW_C_HEAP_ARRAY(HeapWord*, max_regions, mtGC);
 328   }
 329 
 330   void prepare() {
 331     for (size_t i = 0; i < _max_regions; i++) {
 332       _collection_set_iter_state[i] = false;
 333       clear_scan_top((uint)i);
 334     }
 335 
 336     _all_dirty_regions = new G1DirtyRegions(_max_regions);
 337     _next_dirty_regions = new G1DirtyRegions(_max_regions);
 338 
 339     G1ResetScanTopClosure cl(this);
 340     G1CollectedHeap::heap()->heap_region_iterate(&cl);
 341   }
 342 
 343   void prepare_for_merge_heap_roots() {
 344     _all_dirty_regions->merge(_next_dirty_regions);
 345 
 346     _next_dirty_regions->reset();
 347     for (size_t i = 0; i < _max_regions; i++) {
 348       _card_table_scan_state[i] = 0;
 349     }
 350 
 351     ::memset(_region_scan_chunks, false, _num_total_scan_chunks * sizeof(*_region_scan_chunks));
 352   }
 353 
 354   // Returns whether the given region contains cards we need to scan. The remembered
 355   // set and other sources may contain cards that
 356   // - are in uncommitted regions
 357   // - are located in the collection set
 358   // - are located in free regions
 359   // as we do not clean up remembered sets before merging heap roots.
 360   bool contains_cards_to_process(uint const region_idx) const {


 889 void G1RemSet::scan_collection_set_regions(G1ParScanThreadState* pss,
 890                                            uint worker_id,
 891                                            G1GCPhaseTimes::GCParPhases scan_phase,
 892                                            G1GCPhaseTimes::GCParPhases coderoots_phase,
 893                                            G1GCPhaseTimes::GCParPhases objcopy_phase) {
 894   G1ScanCollectionSetRegionClosure cl(_scan_state, pss, worker_id, scan_phase, coderoots_phase);
 895   _g1h->collection_set_iterate_increment_from(&cl, worker_id);
 896 
 897   G1GCPhaseTimes* p = _g1h->phase_times();
 898 
 899   p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_root_scan_time().seconds());
 900   p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_trim_partially_time().seconds());
 901 
 902   p->record_or_add_time_secs(coderoots_phase, worker_id, cl.strong_code_root_scan_time().seconds());
 903   p->add_time_secs(objcopy_phase, worker_id, cl.strong_code_root_trim_partially_time().seconds());
 904 
 905   // At this time we record some metrics only for the evacuations after the initial one.
 906   if (scan_phase == G1GCPhaseTimes::OptScanHR) {
 907     p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_scanned(), G1GCPhaseTimes::ScanHRScannedOptRefs);
 908     p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_memory_used(), G1GCPhaseTimes::ScanHRUsedMemory);

















 909   }
 910 }
 911 
 912 void G1RemSet::prepare_for_scan_heap_roots() {
 913   G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
 914   dcqs.concatenate_logs();
 915 
 916   _scan_state->prepare();
 917 }
 918 
 919 class G1MergeHeapRootsTask : public AbstractGangTask {
 920 
 921   // Visitor for remembered sets, dropping entries onto the card table.
 922   class G1MergeCardSetClosure : public HeapRegionClosure {
 923     G1RemSetScanState* _scan_state;
 924     G1CardTable* _ct;
 925 
 926     uint _merged_sparse;
 927     uint _merged_fine;
 928     uint _merged_coarse;




 179 
 180       bool marked_as_dirty = Atomic::cmpxchg(true, &_contains[region], false) == false;
 181       if (marked_as_dirty) {
 182         uint allocated = Atomic::add(1u, &_cur_idx) - 1;
 183         _buffer[allocated] = region;
 184       }
 185     }
 186 
 187     // Creates the union of this and the other G1DirtyRegions.
 188     void merge(const G1DirtyRegions* other) {
 189       for (uint i = 0; i < other->size(); i++) {
 190         uint region = other->at(i);
 191         if (!_contains[region]) {
 192           _buffer[_cur_idx++] = region;
 193           _contains[region] = true;
 194         }
 195       }
 196     }
 197   };
 198 
























 199   // For each region, contains the maximum top() value to be used during this garbage
 200   // collection. Subsumes common checks like filtering out everything but old and
 201   // humongous regions outside the collection set.
 202   // This is valid because we are not interested in scanning stray remembered set
 203   // entries from free or archive regions.
 204   HeapWord** _scan_top;
 205 
 206   class G1ClearCardTableTask : public AbstractGangTask {
 207     G1CollectedHeap* _g1h;
 208     G1DirtyRegions* _regions;
 209     uint _chunk_length;
 210 
 211     uint volatile _cur_dirty_regions;
 212 
 213     G1RemSetScanState* _scan_state;
 214 
 215   public:
 216     G1ClearCardTableTask(G1CollectedHeap* g1h,
 217                          G1DirtyRegions* regions,
 218                          uint chunk_length,


 294   void initialize(size_t max_regions) {
 295     assert(_collection_set_iter_state == NULL, "Must not be initialized twice");
 296     _max_regions = max_regions;
 297     _collection_set_iter_state = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_regions, mtGC);
 298     _card_table_scan_state = NEW_C_HEAP_ARRAY(uint, max_regions, mtGC);
 299     _num_total_scan_chunks = max_regions * _scan_chunks_per_region;
 300     _region_scan_chunks = NEW_C_HEAP_ARRAY(bool, _num_total_scan_chunks, mtGC);
 301 
 302     _scan_chunks_shift = (uint8_t)log2_intptr(HeapRegion::CardsPerRegion / _scan_chunks_per_region);
 303     _scan_top = NEW_C_HEAP_ARRAY(HeapWord*, max_regions, mtGC);
 304   }
 305 
 306   void prepare() {
 307     for (size_t i = 0; i < _max_regions; i++) {
 308       _collection_set_iter_state[i] = false;
 309       clear_scan_top((uint)i);
 310     }
 311 
 312     _all_dirty_regions = new G1DirtyRegions(_max_regions);
 313     _next_dirty_regions = new G1DirtyRegions(_max_regions);



 314   }
 315 
 316   void prepare_for_merge_heap_roots() {
 317     _all_dirty_regions->merge(_next_dirty_regions);
 318 
 319     _next_dirty_regions->reset();
 320     for (size_t i = 0; i < _max_regions; i++) {
 321       _card_table_scan_state[i] = 0;
 322     }
 323 
 324     ::memset(_region_scan_chunks, false, _num_total_scan_chunks * sizeof(*_region_scan_chunks));
 325   }
 326 
 327   // Returns whether the given region contains cards we need to scan. The remembered
 328   // set and other sources may contain cards that
 329   // - are in uncommitted regions
 330   // - are located in the collection set
 331   // - are located in free regions
 332   // as we do not clean up remembered sets before merging heap roots.
 333   bool contains_cards_to_process(uint const region_idx) const {


 862 void G1RemSet::scan_collection_set_regions(G1ParScanThreadState* pss,
 863                                            uint worker_id,
 864                                            G1GCPhaseTimes::GCParPhases scan_phase,
 865                                            G1GCPhaseTimes::GCParPhases coderoots_phase,
 866                                            G1GCPhaseTimes::GCParPhases objcopy_phase) {
 867   G1ScanCollectionSetRegionClosure cl(_scan_state, pss, worker_id, scan_phase, coderoots_phase);
 868   _g1h->collection_set_iterate_increment_from(&cl, worker_id);
 869 
 870   G1GCPhaseTimes* p = _g1h->phase_times();
 871 
 872   p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_root_scan_time().seconds());
 873   p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_trim_partially_time().seconds());
 874 
 875   p->record_or_add_time_secs(coderoots_phase, worker_id, cl.strong_code_root_scan_time().seconds());
 876   p->add_time_secs(objcopy_phase, worker_id, cl.strong_code_root_trim_partially_time().seconds());
 877 
 878   // At this time we record some metrics only for the evacuations after the initial one.
 879   if (scan_phase == G1GCPhaseTimes::OptScanHR) {
 880     p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_scanned(), G1GCPhaseTimes::ScanHRScannedOptRefs);
 881     p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_memory_used(), G1GCPhaseTimes::ScanHRUsedMemory);
 882   }
 883 }
 884 
 885 // Creates a snapshot of the current _top values at the start of collection to
 886 // filter out card marks that we do not want to scan.
 887 void G1RemSet::prepare_region_for_scanning(HeapRegion* region) {
 888   uint hrm_index = region->hrm_index();
 889   if (region->in_collection_set()) {
 890     // Young regions had their card table marked as young at their allocation;
 891     // we need to make sure that these marks are cleared at the end of GC, *but*
 892     // they should not be scanned for cards.
 893     // So directly add them to the "all_dirty_regions".
 894     // Same for regions in the (initial) collection set: they may contain cards from
 895     // the log buffers, make sure they are cleaned.
 896     _scan_state->add_all_dirty_region(hrm_index);
 897   } else if (region->is_old_or_humongous_or_archive()) {
 898     _scan_state->set_scan_top(hrm_index, region->top());
 899   }
 900 }
 901 
 902 void G1RemSet::prepare_for_scan_heap_roots() {
 903   G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
 904   dcqs.concatenate_logs();
 905 
 906   _scan_state->prepare();
 907 }
 908 
 909 class G1MergeHeapRootsTask : public AbstractGangTask {
 910 
 911   // Visitor for remembered sets, dropping entries onto the card table.
 912   class G1MergeCardSetClosure : public HeapRegionClosure {
 913     G1RemSetScanState* _scan_state;
 914     G1CardTable* _ct;
 915 
 916     uint _merged_sparse;
 917     uint _merged_fine;
 918     uint _merged_coarse;


< prev index next >