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;
|