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
92 void ScanRSClosure::scanCard(size_t index, HeapRegion *r) {
93 // Stack allocate the DirtyCardToOopClosure instance
94 HeapRegionDCTOC cl(_g1h, r, _oc,
95 CardTableModRefBS::Precise);
96
97 // Set the "from" region in the closure.
98 _oc->set_region(r);
99 MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
100 MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
101 MemRegion mr = pre_gc_allocated.intersection(card_region);
102 if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
103 // We make the card as "claimed" lazily (so races are possible
104 // but they're benign), which reduces the number of duplicate
105 // scans (the rsets of the regions in the cset can intersect).
106 _ct_bs->set_card_claimed(index);
107 _cards_done++;
108 cl.do_MemRegion(mr);
109 }
110 }
111
112 void ScanRSClosure::printCard(HeapRegion* card_region, size_t card_index,
113 HeapWord* card_start) {
114 gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") "
115 "RS names card " SIZE_FORMAT_HEX ": "
116 "[" PTR_FORMAT ", " PTR_FORMAT ")",
117 _worker_i,
118 p2i(card_region->bottom()), p2i(card_region->end()),
119 card_index,
120 p2i(card_start), p2i(card_start + G1BlockOffsetSharedArray::N_words));
121 }
122
123 void ScanRSClosure::scan_strong_code_roots(HeapRegion* r) {
124 double scan_start = os::elapsedTime();
125 r->strong_code_roots_do(_code_root_cl);
126 _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
127 }
128
129 bool ScanRSClosure::doHeapRegion(HeapRegion* r) {
130 assert(r->in_collection_set(), "should only be called on elements of CS.");
131 HeapRegionRemSet* hrrs = r->rem_set();
132 if (hrrs->iter_is_complete()) return false; // All done.
133 if (!_try_claimed && !hrrs->claim_iter()) return false;
134 // If we ever free the collection set concurrently, we should also
135 // clear the card table concurrently therefore we won't need to
136 // add regions of the collection set to the dirty cards region.
137 _g1h->push_dirty_cards_region(r);
138 // If we didn't return above, then
139 // _try_claimed || r->claim_iter()
140 // is true: either we're supposed to work on claimed-but-not-complete
141 // regions, or we successfully claimed the region.
142
143 HeapRegionRemSetIterator iter(hrrs);
144 size_t card_index;
145
146 // We claim cards in block so as to reduce the contention. The block size is determined by
147 // the G1RSetScanBlockSize parameter.
148 size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
149 for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
150 if (current_card >= jump_to_card + _block_size) {
151 jump_to_card = hrrs->iter_claimed_next(_block_size);
152 }
153 if (current_card < jump_to_card) continue;
154 HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
155 #if 0
156 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n",
157 card_start, card_start + CardTableModRefBS::card_size_in_words);
158 #endif
159
160 HeapRegion* card_region = _g1h->heap_region_containing(card_start);
161 _cards++;
162
163 if (!card_region->is_on_dirty_cards_region_list()) {
164 _g1h->push_dirty_cards_region(card_region);
165 }
166
167 // If the card is dirty, then we will scan it during updateRS.
168 if (!card_region->in_collection_set() &&
169 !_ct_bs->is_card_dirty(card_index)) {
170 scanCard(card_index, card_region);
171 }
172 }
173 if (!_try_claimed) {
174 // Scan the strong code root list attached to the current region
175 scan_strong_code_roots(r);
176
177 hrrs->set_iter_complete();
178 }
509 JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
510 sdcq->enqueue(card_ptr);
511 }
512 } else {
513 _conc_refine_cards++;
514 }
515
516 // This gets set to true if the card being refined has
517 // references that point into the collection set.
518 bool has_refs_into_cset = trigger_cl.triggered();
519
520 // We should only be detecting that the card contains references
521 // that point into the collection set if the current thread is
522 // a GC worker thread.
523 assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
524 "invalid result at non safepoint");
525
526 return has_refs_into_cset;
527 }
528
529 void G1RemSet::print_periodic_summary_info(const char* header) {
530 G1RemSetSummary current;
531 current.initialize(this);
532
533 _prev_period_summary.subtract_from(¤t);
534 print_summary_info(&_prev_period_summary, header);
535
536 _prev_period_summary.set(¤t);
537 }
538
539 void G1RemSet::print_summary_info() {
540 G1RemSetSummary current;
541 current.initialize(this);
542
543 print_summary_info(¤t, " Cumulative RS summary");
544 }
545
546 void G1RemSet::print_summary_info(G1RemSetSummary * summary, const char * header) {
547 assert(summary != NULL, "just checking");
548
549 if (header != NULL) {
550 gclog_or_tty->print_cr("%s", header);
551 }
552
553 summary->print_on(gclog_or_tty);
554 }
555
556 void G1RemSet::prepare_for_verify() {
557 if (G1HRRSFlushLogBuffersOnVerify &&
558 (VerifyBeforeGC || VerifyAfterGC)
559 && (!_g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC)) {
560 cleanupHRRS();
561 _g1->set_refine_cte_cl_concurrency(false);
562 if (SafepointSynchronize::is_at_safepoint()) {
563 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
564 dcqs.concatenate_logs();
565 }
566
567 G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
568 bool use_hot_card_cache = hot_card_cache->use_cache();
569 hot_card_cache->set_use_cache(false);
570
571 DirtyCardQueue into_cset_dcq(&_into_cset_dirty_card_queue_set);
572 updateRS(&into_cset_dcq, 0);
573 _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
92 void ScanRSClosure::scanCard(size_t index, HeapRegion *r) {
93 // Stack allocate the DirtyCardToOopClosure instance
94 HeapRegionDCTOC cl(_g1h, r, _oc,
95 CardTableModRefBS::Precise);
96
97 // Set the "from" region in the closure.
98 _oc->set_region(r);
99 MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
100 MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
101 MemRegion mr = pre_gc_allocated.intersection(card_region);
102 if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
103 // We make the card as "claimed" lazily (so races are possible
104 // but they're benign), which reduces the number of duplicate
105 // scans (the rsets of the regions in the cset can intersect).
106 _ct_bs->set_card_claimed(index);
107 _cards_done++;
108 cl.do_MemRegion(mr);
109 }
110 }
111
112 void ScanRSClosure::scan_strong_code_roots(HeapRegion* r) {
113 double scan_start = os::elapsedTime();
114 r->strong_code_roots_do(_code_root_cl);
115 _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
116 }
117
118 bool ScanRSClosure::doHeapRegion(HeapRegion* r) {
119 assert(r->in_collection_set(), "should only be called on elements of CS.");
120 HeapRegionRemSet* hrrs = r->rem_set();
121 if (hrrs->iter_is_complete()) return false; // All done.
122 if (!_try_claimed && !hrrs->claim_iter()) return false;
123 // If we ever free the collection set concurrently, we should also
124 // clear the card table concurrently therefore we won't need to
125 // add regions of the collection set to the dirty cards region.
126 _g1h->push_dirty_cards_region(r);
127 // If we didn't return above, then
128 // _try_claimed || r->claim_iter()
129 // is true: either we're supposed to work on claimed-but-not-complete
130 // regions, or we successfully claimed the region.
131
132 HeapRegionRemSetIterator iter(hrrs);
133 size_t card_index;
134
135 // We claim cards in block so as to reduce the contention. The block size is determined by
136 // the G1RSetScanBlockSize parameter.
137 size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
138 for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
139 if (current_card >= jump_to_card + _block_size) {
140 jump_to_card = hrrs->iter_claimed_next(_block_size);
141 }
142 if (current_card < jump_to_card) continue;
143 HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
144
145 HeapRegion* card_region = _g1h->heap_region_containing(card_start);
146 _cards++;
147
148 if (!card_region->is_on_dirty_cards_region_list()) {
149 _g1h->push_dirty_cards_region(card_region);
150 }
151
152 // If the card is dirty, then we will scan it during updateRS.
153 if (!card_region->in_collection_set() &&
154 !_ct_bs->is_card_dirty(card_index)) {
155 scanCard(card_index, card_region);
156 }
157 }
158 if (!_try_claimed) {
159 // Scan the strong code root list attached to the current region
160 scan_strong_code_roots(r);
161
162 hrrs->set_iter_complete();
163 }
494 JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
495 sdcq->enqueue(card_ptr);
496 }
497 } else {
498 _conc_refine_cards++;
499 }
500
501 // This gets set to true if the card being refined has
502 // references that point into the collection set.
503 bool has_refs_into_cset = trigger_cl.triggered();
504
505 // We should only be detecting that the card contains references
506 // that point into the collection set if the current thread is
507 // a GC worker thread.
508 assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
509 "invalid result at non safepoint");
510
511 return has_refs_into_cset;
512 }
513
514 void G1RemSet::print_periodic_summary_info(const char* header, uint period_count) {
515 if ((G1SummarizeRSetStatsPeriod > 0) && log_is_enabled(Trace, gc, remset) &&
516 (period_count % G1SummarizeRSetStatsPeriod == 0)) {
517
518 if (!_prev_period_summary.initialized()) {
519 _prev_period_summary.initialize(this);
520 }
521
522 G1RemSetSummary current;
523 current.initialize(this);
524 _prev_period_summary.subtract_from(¤t);
525
526 LogHandle(gc, remset) log;
527 log.trace("%s", header);
528 ResourceMark rm;
529 _prev_period_summary.print_on(log.trace_stream());
530
531 _prev_period_summary.set(¤t);
532 }
533 }
534
535 void G1RemSet::print_summary_info() {
536 LogHandle(gc, remset, exit) log;
537 if (log.is_trace()) {
538 log.trace(" Cumulative RS summary");
539 G1RemSetSummary current;
540 current.initialize(this);
541 ResourceMark rm;
542 current.print_on(log.trace_stream());
543 }
544 }
545
546 void G1RemSet::prepare_for_verify() {
547 if (G1HRRSFlushLogBuffersOnVerify &&
548 (VerifyBeforeGC || VerifyAfterGC)
549 && (!_g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC)) {
550 cleanupHRRS();
551 _g1->set_refine_cte_cl_concurrency(false);
552 if (SafepointSynchronize::is_at_safepoint()) {
553 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
554 dcqs.concatenate_logs();
555 }
556
557 G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
558 bool use_hot_card_cache = hot_card_cache->use_cache();
559 hot_card_cache->set_use_cache(false);
560
561 DirtyCardQueue into_cset_dcq(&_into_cset_dirty_card_queue_set);
562 updateRS(&into_cset_dcq, 0);
563 _into_cset_dirty_card_queue_set.clear();
|