35 #include "gc/g1/heapRegionManager.inline.hpp"
36 #include "gc/g1/heapRegionRemSet.hpp"
37 #include "memory/iterator.hpp"
38 #include "oops/oop.inline.hpp"
39 #include "utilities/globalDefinitions.hpp"
40 #include "utilities/intHisto.hpp"
41 #include "utilities/stack.inline.hpp"
42
43 G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
44 : _g1(g1), _conc_refine_cards(0),
45 _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
46 _cg1r(g1->concurrent_g1_refine()),
47 _cset_rs_update_cl(NULL),
48 _prev_period_summary(),
49 _into_cset_dirty_card_queue_set(false)
50 {
51 _cset_rs_update_cl = NEW_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, n_workers(), mtGC);
52 for (uint i = 0; i < n_workers(); i++) {
53 _cset_rs_update_cl[i] = NULL;
54 }
55 if (G1SummarizeRSetStats) {
56 _prev_period_summary.initialize(this);
57 }
58 // Initialize the card queue set used to hold cards containing
59 // references into the collection set.
60 _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code
61 DirtyCardQ_CBL_mon,
62 DirtyCardQ_FL_lock,
63 -1, // never trigger processing
64 -1, // no limit on length
65 Shared_DirtyCardQ_lock,
66 &JavaThread::dirty_card_queue_set());
67 }
68
69 G1RemSet::~G1RemSet() {
70 for (uint i = 0; i < n_workers(); i++) {
71 assert(_cset_rs_update_cl[i] == NULL, "it should be");
72 }
73 FREE_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, _cset_rs_update_cl);
74 }
75
111 void scanCard(size_t index, HeapRegion *r) {
112 // Stack allocate the DirtyCardToOopClosure instance
113 HeapRegionDCTOC cl(_g1h, r, _oc,
114 CardTableModRefBS::Precise);
115
116 // Set the "from" region in the closure.
117 _oc->set_region(r);
118 MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
119 MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
120 MemRegion mr = pre_gc_allocated.intersection(card_region);
121 if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
122 // We make the card as "claimed" lazily (so races are possible
123 // but they're benign), which reduces the number of duplicate
124 // scans (the rsets of the regions in the cset can intersect).
125 _ct_bs->set_card_claimed(index);
126 _cards_done++;
127 cl.do_MemRegion(mr);
128 }
129 }
130
131 void printCard(HeapRegion* card_region, size_t card_index,
132 HeapWord* card_start) {
133 gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") "
134 "RS names card " SIZE_FORMAT_HEX ": "
135 "[" PTR_FORMAT ", " PTR_FORMAT ")",
136 _worker_i,
137 p2i(card_region->bottom()), p2i(card_region->end()),
138 card_index,
139 p2i(card_start), p2i(card_start + G1BlockOffsetSharedArray::N_words));
140 }
141
142 void scan_strong_code_roots(HeapRegion* r) {
143 double scan_start = os::elapsedTime();
144 r->strong_code_roots_do(_code_root_cl);
145 _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
146 }
147
148 bool doHeapRegion(HeapRegion* r) {
149 assert(r->in_collection_set(), "should only be called on elements of CS.");
150 HeapRegionRemSet* hrrs = r->rem_set();
151 if (hrrs->iter_is_complete()) return false; // All done.
152 if (!_try_claimed && !hrrs->claim_iter()) return false;
153 // If we ever free the collection set concurrently, we should also
154 // clear the card table concurrently therefore we won't need to
155 // add regions of the collection set to the dirty cards region.
156 _g1h->push_dirty_cards_region(r);
157 // If we didn't return above, then
158 // _try_claimed || r->claim_iter()
159 // is true: either we're supposed to work on claimed-but-not-complete
160 // regions, or we successfully claimed the region.
161
162 HeapRegionRemSetIterator iter(hrrs);
163 size_t card_index;
164
165 // We claim cards in block so as to reduce the contention. The block size is determined by
166 // the G1RSetScanBlockSize parameter.
167 size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
168 for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
169 if (current_card >= jump_to_card + _block_size) {
170 jump_to_card = hrrs->iter_claimed_next(_block_size);
171 }
172 if (current_card < jump_to_card) continue;
173 HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
174 #if 0
175 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n",
176 card_start, card_start + CardTableModRefBS::card_size_in_words);
177 #endif
178
179 HeapRegion* card_region = _g1h->heap_region_containing(card_start);
180 _cards++;
181
182 if (!card_region->is_on_dirty_cards_region_list()) {
183 _g1h->push_dirty_cards_region(card_region);
184 }
185
186 // If the card is dirty, then we will scan it during updateRS.
187 if (!card_region->in_collection_set() &&
188 !_ct_bs->is_card_dirty(card_index)) {
189 scanCard(card_index, card_region);
190 }
191 }
192 if (!_try_claimed) {
193 // Scan the strong code root list attached to the current region
194 scan_strong_code_roots(r);
195
196 hrrs->set_iter_complete();
197 }
198 return false;
537 JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
538 sdcq->enqueue(card_ptr);
539 }
540 } else {
541 _conc_refine_cards++;
542 }
543
544 // This gets set to true if the card being refined has
545 // references that point into the collection set.
546 bool has_refs_into_cset = trigger_cl.triggered();
547
548 // We should only be detecting that the card contains references
549 // that point into the collection set if the current thread is
550 // a GC worker thread.
551 assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
552 "invalid result at non safepoint");
553
554 return has_refs_into_cset;
555 }
556
557 void G1RemSet::print_periodic_summary_info(const char* header) {
558 G1RemSetSummary current;
559 current.initialize(this);
560
561 _prev_period_summary.subtract_from(¤t);
562 print_summary_info(&_prev_period_summary, header);
563
564 _prev_period_summary.set(¤t);
565 }
566
567 void G1RemSet::print_summary_info() {
568 G1RemSetSummary current;
569 current.initialize(this);
570
571 print_summary_info(¤t, " Cumulative RS summary");
572 }
573
574 void G1RemSet::print_summary_info(G1RemSetSummary * summary, const char * header) {
575 assert(summary != NULL, "just checking");
576
577 if (header != NULL) {
578 gclog_or_tty->print_cr("%s", header);
579 }
580
581 summary->print_on(gclog_or_tty);
582 }
583
584 void G1RemSet::prepare_for_verify() {
585 if (G1HRRSFlushLogBuffersOnVerify &&
586 (VerifyBeforeGC || VerifyAfterGC)
587 && (!_g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC)) {
588 cleanupHRRS();
589 _g1->set_refine_cte_cl_concurrency(false);
590 if (SafepointSynchronize::is_at_safepoint()) {
591 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
592 dcqs.concatenate_logs();
593 }
594
595 G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
596 bool use_hot_card_cache = hot_card_cache->use_cache();
597 hot_card_cache->set_use_cache(false);
598
599 DirtyCardQueue into_cset_dcq(&_into_cset_dirty_card_queue_set);
600 updateRS(&into_cset_dcq, 0);
601 _into_cset_dirty_card_queue_set.clear();
|
35 #include "gc/g1/heapRegionManager.inline.hpp"
36 #include "gc/g1/heapRegionRemSet.hpp"
37 #include "memory/iterator.hpp"
38 #include "oops/oop.inline.hpp"
39 #include "utilities/globalDefinitions.hpp"
40 #include "utilities/intHisto.hpp"
41 #include "utilities/stack.inline.hpp"
42
43 G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
44 : _g1(g1), _conc_refine_cards(0),
45 _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
46 _cg1r(g1->concurrent_g1_refine()),
47 _cset_rs_update_cl(NULL),
48 _prev_period_summary(),
49 _into_cset_dirty_card_queue_set(false)
50 {
51 _cset_rs_update_cl = NEW_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, n_workers(), mtGC);
52 for (uint i = 0; i < n_workers(); i++) {
53 _cset_rs_update_cl[i] = NULL;
54 }
55 if (log_is_enabled(Trace, gc, remset)) {
56 _prev_period_summary.initialize(this);
57 }
58 // Initialize the card queue set used to hold cards containing
59 // references into the collection set.
60 _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code
61 DirtyCardQ_CBL_mon,
62 DirtyCardQ_FL_lock,
63 -1, // never trigger processing
64 -1, // no limit on length
65 Shared_DirtyCardQ_lock,
66 &JavaThread::dirty_card_queue_set());
67 }
68
69 G1RemSet::~G1RemSet() {
70 for (uint i = 0; i < n_workers(); i++) {
71 assert(_cset_rs_update_cl[i] == NULL, "it should be");
72 }
73 FREE_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, _cset_rs_update_cl);
74 }
75
111 void scanCard(size_t index, HeapRegion *r) {
112 // Stack allocate the DirtyCardToOopClosure instance
113 HeapRegionDCTOC cl(_g1h, r, _oc,
114 CardTableModRefBS::Precise);
115
116 // Set the "from" region in the closure.
117 _oc->set_region(r);
118 MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
119 MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
120 MemRegion mr = pre_gc_allocated.intersection(card_region);
121 if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
122 // We make the card as "claimed" lazily (so races are possible
123 // but they're benign), which reduces the number of duplicate
124 // scans (the rsets of the regions in the cset can intersect).
125 _ct_bs->set_card_claimed(index);
126 _cards_done++;
127 cl.do_MemRegion(mr);
128 }
129 }
130
131 void scan_strong_code_roots(HeapRegion* r) {
132 double scan_start = os::elapsedTime();
133 r->strong_code_roots_do(_code_root_cl);
134 _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
135 }
136
137 bool doHeapRegion(HeapRegion* r) {
138 assert(r->in_collection_set(), "should only be called on elements of CS.");
139 HeapRegionRemSet* hrrs = r->rem_set();
140 if (hrrs->iter_is_complete()) return false; // All done.
141 if (!_try_claimed && !hrrs->claim_iter()) return false;
142 // If we ever free the collection set concurrently, we should also
143 // clear the card table concurrently therefore we won't need to
144 // add regions of the collection set to the dirty cards region.
145 _g1h->push_dirty_cards_region(r);
146 // If we didn't return above, then
147 // _try_claimed || r->claim_iter()
148 // is true: either we're supposed to work on claimed-but-not-complete
149 // regions, or we successfully claimed the region.
150
151 HeapRegionRemSetIterator iter(hrrs);
152 size_t card_index;
153
154 // We claim cards in block so as to reduce the contention. The block size is determined by
155 // the G1RSetScanBlockSize parameter.
156 size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
157 for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
158 if (current_card >= jump_to_card + _block_size) {
159 jump_to_card = hrrs->iter_claimed_next(_block_size);
160 }
161 if (current_card < jump_to_card) continue;
162 HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
163 HeapRegion* card_region = _g1h->heap_region_containing(card_start);
164 _cards++;
165
166 if (!card_region->is_on_dirty_cards_region_list()) {
167 _g1h->push_dirty_cards_region(card_region);
168 }
169
170 // If the card is dirty, then we will scan it during updateRS.
171 if (!card_region->in_collection_set() &&
172 !_ct_bs->is_card_dirty(card_index)) {
173 scanCard(card_index, card_region);
174 }
175 }
176 if (!_try_claimed) {
177 // Scan the strong code root list attached to the current region
178 scan_strong_code_roots(r);
179
180 hrrs->set_iter_complete();
181 }
182 return false;
521 JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
522 sdcq->enqueue(card_ptr);
523 }
524 } else {
525 _conc_refine_cards++;
526 }
527
528 // This gets set to true if the card being refined has
529 // references that point into the collection set.
530 bool has_refs_into_cset = trigger_cl.triggered();
531
532 // We should only be detecting that the card contains references
533 // that point into the collection set if the current thread is
534 // a GC worker thread.
535 assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
536 "invalid result at non safepoint");
537
538 return has_refs_into_cset;
539 }
540
541 void G1RemSet::print_periodic_summary_info(const char* header, uint period_count) {
542 if ((G1SummarizeRSetStatsPeriod > 0) && log_is_enabled(Trace, gc, remset) &&
543 (period_count % G1SummarizeRSetStatsPeriod == 0)) {
544
545 if (!_prev_period_summary.initialized()) {
546 _prev_period_summary.initialize(this);
547 }
548
549 G1RemSetSummary current;
550 current.initialize(this);
551 _prev_period_summary.subtract_from(¤t);
552
553 LogHandle(gc, remset) log;
554 log.trace("%s", header);
555 ResourceMark rm;
556 _prev_period_summary.print_on(log.trace_stream());
557
558 _prev_period_summary.set(¤t);
559 }
560 }
561
562 void G1RemSet::print_summary_info() {
563 LogHandle(gc, remset, exit) log;
564 if (log.is_trace()) {
565 log.trace(" Cumulative RS summary");
566 G1RemSetSummary current;
567 current.initialize(this);
568 ResourceMark rm;
569 current.print_on(log.trace_stream());
570 }
571 }
572
573 void G1RemSet::prepare_for_verify() {
574 if (G1HRRSFlushLogBuffersOnVerify &&
575 (VerifyBeforeGC || VerifyAfterGC)
576 && (!_g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC)) {
577 cleanupHRRS();
578 _g1->set_refine_cte_cl_concurrency(false);
579 if (SafepointSynchronize::is_at_safepoint()) {
580 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
581 dcqs.concatenate_logs();
582 }
583
584 G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
585 bool use_hot_card_cache = hot_card_cache->use_cache();
586 hot_card_cache->set_use_cache(false);
587
588 DirtyCardQueue into_cset_dcq(&_into_cset_dirty_card_queue_set);
589 updateRS(&into_cset_dcq, 0);
590 _into_cset_dirty_card_queue_set.clear();
|