@@ -131,8 +131,17 @@ class G1RemSetScanState : public CHeapObj<mtGC> {
131131 }
132132
133133private:
134- // The complete set of regions which card table needs to be cleared at the end of GC because
135- // we scribbled all over them.
134+ // The complete set of regions which card table needs to be cleared at the end
135+ // of GC because we scribbled over these card tables.
136+ //
137+ // Regions may be added for two reasons:
138+ // - they were part of the collection set: they may contain g1_young_card_val
139+ // or regular card marks that we never scan so we must always clear their card
140+ // table
141+ // - or in case g1 does an optional evacuation pass, g1 marks the cards in there
142+ // as g1_scanned_card_val. If G1 only did an initial evacuation pass, the
143+ // scanning already cleared these cards. In that case they are not in this set
144+ // at the end of the collection.
136145 G1DirtyRegions* _all_dirty_regions;
137146 // The set of regions which card table needs to be scanned for new dirty cards
138147 // in the current evacuation pass.
@@ -321,16 +330,22 @@ class G1RemSetScanState : public CHeapObj<mtGC> {
321330 }
322331
323332 void prepare_for_merge_heap_roots () {
324- _all_dirty_regions-> merge (_next_dirty_regions );
333+ assert (_next_dirty_regions-> size () == 0 , " next dirty regions must be empty " );
325334
326- _next_dirty_regions->reset ();
327335 for (size_t i = 0 ; i < _max_reserved_regions; i++) {
328336 _card_table_scan_state[i] = 0 ;
329337 }
330338
331339 ::memset (_region_scan_chunks, false , _num_total_scan_chunks * sizeof (*_region_scan_chunks));
332340 }
333341
342+ void complete_evac_phase (bool merge_dirty_regions) {
343+ if (merge_dirty_regions) {
344+ _all_dirty_regions->merge (_next_dirty_regions);
345+ }
346+ _next_dirty_regions->reset ();
347+ }
348+
334349 // Returns whether the given region contains cards we need to scan. The remembered
335350 // set and other sources may contain cards that
336351 // - are in uncommitted regions
@@ -374,8 +389,6 @@ class G1RemSetScanState : public CHeapObj<mtGC> {
374389 }
375390
376391 void cleanup (WorkGang* workers) {
377- _all_dirty_regions->merge (_next_dirty_regions);
378-
379392 clear_card_table (workers);
380393
381394 delete _all_dirty_regions;
@@ -448,7 +461,7 @@ class G1RemSetScanState : public CHeapObj<mtGC> {
448461#ifdef ASSERT
449462 HeapRegion* hr = G1CollectedHeap::heap ()->region_at (region);
450463 assert (hr->in_collection_set (),
451- " Only add young regions to all dirty regions directly but %u is %s" ,
464+ " Only add collection set regions to all dirty regions directly but %u is %s" ,
452465 hr->hrm_index (), hr->get_short_type_str ());
453466#endif
454467 _all_dirty_regions->add_dirty_region (region);
@@ -641,6 +654,7 @@ class G1ScanHRForRegionClosure : public HeapRegionClosure {
641654 // The address to which this thread already scanned (walked the heap) up to during
642655 // card scanning (exclusive).
643656 HeapWord* _scanned_to;
657+ G1CardTable::CardValue _scanned_card_value;
644658
645659 HeapWord* scan_memregion (uint region_idx_for_card, MemRegion mr) {
646660 HeapRegion* const card_region = _g1h->region_at (region_idx_for_card);
@@ -677,7 +691,7 @@ class G1ScanHRForRegionClosure : public HeapRegionClosure {
677691 }
678692
679693 ALWAYSINLINE void do_card_block (uint const region_idx, size_t const first_card, size_t const num_cards) {
680- _ct->mark_as_scanned (first_card, num_cards);
694+ _ct->change_dirty_cards_to (first_card, num_cards, _scanned_card_value );
681695 do_claimed_block (region_idx, first_card, num_cards);
682696 _blocks_scanned++;
683697 }
@@ -727,7 +741,8 @@ class G1ScanHRForRegionClosure : public HeapRegionClosure {
727741 G1ScanHRForRegionClosure (G1RemSetScanState* scan_state,
728742 G1ParScanThreadState* pss,
729743 uint worker_id,
730- G1GCPhaseTimes::GCParPhases phase) :
744+ G1GCPhaseTimes::GCParPhases phase,
745+ bool remember_already_scanned_cards) :
731746 _g1h (G1CollectedHeap::heap()),
732747 _ct (_g1h->card_table ()),
733748 _bot(_g1h->bot ()),
@@ -740,7 +755,9 @@ class G1ScanHRForRegionClosure : public HeapRegionClosure {
740755 _chunks_claimed(0 ),
741756 _rem_set_root_scan_time(),
742757 _rem_set_trim_partially_time(),
743- _scanned_to(NULL ) {
758+ _scanned_to(NULL ),
759+ _scanned_card_value(remember_already_scanned_cards ? G1CardTable::g1_scanned_card_val()
760+ : G1CardTable::clean_card_val()) {
744761 }
745762
746763 bool do_heap_region (HeapRegion* r) {
@@ -765,10 +782,11 @@ class G1ScanHRForRegionClosure : public HeapRegionClosure {
765782};
766783
767784void G1RemSet::scan_heap_roots (G1ParScanThreadState* pss,
768- uint worker_id,
769- G1GCPhaseTimes::GCParPhases scan_phase,
770- G1GCPhaseTimes::GCParPhases objcopy_phase) {
771- G1ScanHRForRegionClosure cl (_scan_state, pss, worker_id, scan_phase);
785+ uint worker_id,
786+ G1GCPhaseTimes::GCParPhases scan_phase,
787+ G1GCPhaseTimes::GCParPhases objcopy_phase,
788+ bool remember_already_scanned_cards) {
789+ G1ScanHRForRegionClosure cl (_scan_state, pss, worker_id, scan_phase, remember_already_scanned_cards);
772790 _scan_state->iterate_dirty_regions_from (&cl, worker_id);
773791
774792 G1GCPhaseTimes* p = _g1p->phase_times ();
@@ -891,18 +909,11 @@ void G1RemSet::scan_collection_set_regions(G1ParScanThreadState* pss,
891909void G1RemSet::prepare_region_for_scan (HeapRegion* region) {
892910 uint hrm_index = region->hrm_index ();
893911
894- if (region->in_collection_set ()) {
895- // Young regions had their card table marked as young at their allocation;
896- // we need to make sure that these marks are cleared at the end of GC, *but*
897- // they should not be scanned for cards.
898- // So directly add them to the "all_dirty_regions".
899- // Same for regions in the (initial) collection set: they may contain cards from
900- // the log buffers, make sure they are cleaned.
901- _scan_state->add_all_dirty_region (hrm_index);
902- } else if (region->is_old_or_humongous_or_archive ()) {
912+ if (region->is_old_or_humongous_or_archive ()) {
903913 _scan_state->set_scan_top (hrm_index, region->top ());
904914 } else {
905- assert (region->is_free (), " Should only be free region at this point %s" , region->get_type_str ());
915+ assert (region->in_collection_set () || region->is_free (),
916+ " Should only be free or in the collection set at this point %s" , region->get_type_str ());
906917 }
907918}
908919
@@ -984,13 +995,34 @@ class G1MergeHeapRootsTask : public AbstractGangTask {
984995 }
985996 }
986997
987- virtual bool do_heap_region (HeapRegion* r) {
998+ // Helper to put the remembered set cards for these regions onto the card
999+ // table.
1000+ //
1001+ // Called directly for humongous starts regions because we should not add
1002+ // humongous eager reclaim candidates to the "all" list of regions to
1003+ // clear the card table by default as we do not know yet whether this region
1004+ // will be reclaimed (and reused).
1005+ // If the humongous region contains dirty cards, g1 will scan them
1006+ // because dumping the remembered set entries onto the card table will add
1007+ // the humongous region to the "dirty" region list to scan. Then scanning
1008+ // either clears the card during scan (if there is only an initial evacuation
1009+ // pass) or the "dirty" list will be merged with the "all" list later otherwise.
1010+ // (And there is no problem either way if the region does not contain dirty
1011+ // cards).
1012+ void dump_rem_set_for_region (HeapRegion* r) {
9881013 assert (r->in_collection_set () || r->is_starts_humongous (), " must be" );
9891014
9901015 HeapRegionRemSet* rem_set = r->rem_set ();
9911016 if (!rem_set->is_empty ()) {
9921017 rem_set->iterate_prts (*this );
9931018 }
1019+ }
1020+
1021+ virtual bool do_heap_region (HeapRegion* r) {
1022+ assert (r->in_collection_set (), " must be" );
1023+
1024+ _scan_state->add_all_dirty_region (r->hrm_index ());
1025+ dump_rem_set_for_region (r);
9941026
9951027 return false ;
9961028 }
@@ -1022,7 +1054,7 @@ class G1MergeHeapRootsTask : public AbstractGangTask {
10221054 guarantee (r->rem_set ()->occupancy_less_or_equal_than (G1RSetSparseRegionEntries),
10231055 " Found a not-small remembered set here. This is inconsistent with previous assumptions." );
10241056
1025- _cl.do_heap_region (r);
1057+ _cl.dump_rem_set_for_region (r);
10261058
10271059 // We should only clear the card based remembered set here as we will not
10281060 // implicitly rebuild anything else during eager reclaim. Note that at the moment
@@ -1239,6 +1271,10 @@ void G1RemSet::merge_heap_roots(bool initial_evacuation) {
12391271 }
12401272}
12411273
1274+ void G1RemSet::complete_evac_phase (bool has_more_than_one_evacuation_phase) {
1275+ _scan_state->complete_evac_phase (has_more_than_one_evacuation_phase);
1276+ }
1277+
12421278void G1RemSet::exclude_region_from_scan (uint region_idx) {
12431279 _scan_state->clear_scan_top (region_idx);
12441280}
0 commit comments