< prev index next >

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

Print this page




  34 #include "gc/g1/g1RemSet.inline.hpp"
  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 {
  50   _cset_rs_update_cl = NEW_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, n_workers(), mtGC);
  51   for (uint i = 0; i < n_workers(); i++) {
  52     _cset_rs_update_cl[i] = NULL;
  53   }
  54   if (G1SummarizeRSetStats) {
  55     _prev_period_summary.initialize(this);
  56   }
  57 }
  58 
  59 G1RemSet::~G1RemSet() {
  60   for (uint i = 0; i < n_workers(); i++) {
  61     assert(_cset_rs_update_cl[i] == NULL, "it should be");
  62   }
  63   FREE_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, _cset_rs_update_cl);
  64 }
  65 
  66 class ScanRSClosure : public HeapRegionClosure {
  67   size_t _cards_done, _cards;
  68   G1CollectedHeap* _g1h;
  69 
  70   G1ParPushHeapRSClosure* _oc;
  71   CodeBlobClosure* _code_root_cl;
  72 
  73   G1BlockOffsetSharedArray* _bot_shared;
  74   G1SATBCardTableModRefBS *_ct_bs;


 101   void scanCard(size_t index, HeapRegion *r) {
 102     // Stack allocate the DirtyCardToOopClosure instance
 103     HeapRegionDCTOC cl(_g1h, r, _oc,
 104                        CardTableModRefBS::Precise);
 105 
 106     // Set the "from" region in the closure.
 107     _oc->set_region(r);
 108     MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
 109     MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
 110     MemRegion mr = pre_gc_allocated.intersection(card_region);
 111     if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
 112       // We make the card as "claimed" lazily (so races are possible
 113       // but they're benign), which reduces the number of duplicate
 114       // scans (the rsets of the regions in the cset can intersect).
 115       _ct_bs->set_card_claimed(index);
 116       _cards_done++;
 117       cl.do_MemRegion(mr);
 118     }
 119   }
 120 
 121   void printCard(HeapRegion* card_region, size_t card_index,
 122                  HeapWord* card_start) {
 123     gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") "
 124                            "RS names card " SIZE_FORMAT_HEX ": "
 125                            "[" PTR_FORMAT ", " PTR_FORMAT ")",
 126                            _worker_i,
 127                            p2i(card_region->bottom()), p2i(card_region->end()),
 128                            card_index,
 129                            p2i(card_start), p2i(card_start + G1BlockOffsetSharedArray::N_words));
 130   }
 131 
 132   void scan_strong_code_roots(HeapRegion* r) {
 133     double scan_start = os::elapsedTime();
 134     r->strong_code_roots_do(_code_root_cl);
 135     _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
 136   }
 137 
 138   bool doHeapRegion(HeapRegion* r) {
 139     assert(r->in_collection_set(), "should only be called on elements of CS.");
 140     HeapRegionRemSet* hrrs = r->rem_set();
 141     if (hrrs->iter_is_complete()) return false; // All done.
 142     if (!_try_claimed && !hrrs->claim_iter()) return false;
 143     // If we ever free the collection set concurrently, we should also
 144     // clear the card table concurrently therefore we won't need to
 145     // add regions of the collection set to the dirty cards region.
 146     _g1h->push_dirty_cards_region(r);
 147     // If we didn't return above, then
 148     //   _try_claimed || r->claim_iter()
 149     // is true: either we're supposed to work on claimed-but-not-complete
 150     // regions, or we successfully claimed the region.
 151 
 152     HeapRegionRemSetIterator iter(hrrs);
 153     size_t card_index;
 154 
 155     // We claim cards in block so as to reduce the contention. The block size is determined by
 156     // the G1RSetScanBlockSize parameter.
 157     size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
 158     for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
 159       if (current_card >= jump_to_card + _block_size) {
 160         jump_to_card = hrrs->iter_claimed_next(_block_size);
 161       }
 162       if (current_card < jump_to_card) continue;
 163       HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
 164 #if 0
 165       gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n",
 166                           card_start, card_start + CardTableModRefBS::card_size_in_words);
 167 #endif
 168 
 169       HeapRegion* card_region = _g1h->heap_region_containing(card_start);
 170       _cards++;
 171 
 172       if (!card_region->is_on_dirty_cards_region_list()) {
 173         _g1h->push_dirty_cards_region(card_region);
 174       }
 175 
 176       // If the card is dirty, then we will scan it during updateRS.
 177       if (!card_region->in_collection_set() &&
 178           !_ct_bs->is_card_dirty(card_index)) {
 179         scanCard(card_index, card_region);
 180       }
 181     }
 182     if (!_try_claimed) {
 183       // Scan the strong code root list attached to the current region
 184       scan_strong_code_roots(r);
 185 
 186       hrrs->set_iter_complete();
 187     }
 188     return false;


 527         JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
 528       sdcq->enqueue(card_ptr);
 529     }
 530   } else {
 531     _conc_refine_cards++;
 532   }
 533 
 534   // This gets set to true if the card being refined has
 535   // references that point into the collection set.
 536   bool has_refs_into_cset = trigger_cl.triggered();
 537 
 538   // We should only be detecting that the card contains references
 539   // that point into the collection set if the current thread is
 540   // a GC worker thread.
 541   assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
 542            "invalid result at non safepoint");
 543 
 544   return has_refs_into_cset;
 545 }
 546 
 547 void G1RemSet::print_periodic_summary_info(const char* header) {







 548   G1RemSetSummary current;
 549   current.initialize(this);
 550 
 551   _prev_period_summary.subtract_from(&current);
 552   print_summary_info(&_prev_period_summary, header);




 553 
 554   _prev_period_summary.set(&current);

 555 }
 556 
 557 void G1RemSet::print_summary_info() {



 558   G1RemSetSummary current;
 559   current.initialize(this);
 560 
 561   print_summary_info(&current, " Cumulative RS summary");
 562 }
 563 
 564 void G1RemSet::print_summary_info(G1RemSetSummary * summary, const char * header) {
 565   assert(summary != NULL, "just checking");
 566 
 567   if (header != NULL) {
 568     gclog_or_tty->print_cr("%s", header);
 569   }
 570 
 571   summary->print_on(gclog_or_tty);
 572 }
 573 
 574 void G1RemSet::prepare_for_verify() {
 575   if (G1HRRSFlushLogBuffersOnVerify &&
 576       (VerifyBeforeGC || VerifyAfterGC)
 577       &&  (!_g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC)) {
 578     cleanupHRRS();
 579     _g1->set_refine_cte_cl_concurrency(false);
 580     if (SafepointSynchronize::is_at_safepoint()) {
 581       DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
 582       dcqs.concatenate_logs();
 583     }
 584 
 585     G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
 586     bool use_hot_card_cache = hot_card_cache->use_cache();
 587     hot_card_cache->set_use_cache(false);
 588 
 589     DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
 590     updateRS(&into_cset_dcq, 0);
 591     _g1->into_cset_dirty_card_queue_set().clear();


  34 #include "gc/g1/g1RemSet.inline.hpp"
  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 {
  50   _cset_rs_update_cl = NEW_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, n_workers(), mtGC);
  51   for (uint i = 0; i < n_workers(); i++) {
  52     _cset_rs_update_cl[i] = NULL;
  53   }
  54   if (log_is_enabled(Trace, gc, remset)) {
  55     _prev_period_summary.initialize(this);
  56   }
  57 }
  58 
  59 G1RemSet::~G1RemSet() {
  60   for (uint i = 0; i < n_workers(); i++) {
  61     assert(_cset_rs_update_cl[i] == NULL, "it should be");
  62   }
  63   FREE_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, _cset_rs_update_cl);
  64 }
  65 
  66 class ScanRSClosure : public HeapRegionClosure {
  67   size_t _cards_done, _cards;
  68   G1CollectedHeap* _g1h;
  69 
  70   G1ParPushHeapRSClosure* _oc;
  71   CodeBlobClosure* _code_root_cl;
  72 
  73   G1BlockOffsetSharedArray* _bot_shared;
  74   G1SATBCardTableModRefBS *_ct_bs;


 101   void scanCard(size_t index, HeapRegion *r) {
 102     // Stack allocate the DirtyCardToOopClosure instance
 103     HeapRegionDCTOC cl(_g1h, r, _oc,
 104                        CardTableModRefBS::Precise);
 105 
 106     // Set the "from" region in the closure.
 107     _oc->set_region(r);
 108     MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
 109     MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
 110     MemRegion mr = pre_gc_allocated.intersection(card_region);
 111     if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
 112       // We make the card as "claimed" lazily (so races are possible
 113       // but they're benign), which reduces the number of duplicate
 114       // scans (the rsets of the regions in the cset can intersect).
 115       _ct_bs->set_card_claimed(index);
 116       _cards_done++;
 117       cl.do_MemRegion(mr);
 118     }
 119   }
 120 











 121   void scan_strong_code_roots(HeapRegion* r) {
 122     double scan_start = os::elapsedTime();
 123     r->strong_code_roots_do(_code_root_cl);
 124     _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
 125   }
 126 
 127   bool doHeapRegion(HeapRegion* r) {
 128     assert(r->in_collection_set(), "should only be called on elements of CS.");
 129     HeapRegionRemSet* hrrs = r->rem_set();
 130     if (hrrs->iter_is_complete()) return false; // All done.
 131     if (!_try_claimed && !hrrs->claim_iter()) return false;
 132     // If we ever free the collection set concurrently, we should also
 133     // clear the card table concurrently therefore we won't need to
 134     // add regions of the collection set to the dirty cards region.
 135     _g1h->push_dirty_cards_region(r);
 136     // If we didn't return above, then
 137     //   _try_claimed || r->claim_iter()
 138     // is true: either we're supposed to work on claimed-but-not-complete
 139     // regions, or we successfully claimed the region.
 140 
 141     HeapRegionRemSetIterator iter(hrrs);
 142     size_t card_index;
 143 
 144     // We claim cards in block so as to reduce the contention. The block size is determined by
 145     // the G1RSetScanBlockSize parameter.
 146     size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
 147     for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
 148       if (current_card >= jump_to_card + _block_size) {
 149         jump_to_card = hrrs->iter_claimed_next(_block_size);
 150       }
 151       if (current_card < jump_to_card) continue;
 152       HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);





 153       HeapRegion* card_region = _g1h->heap_region_containing(card_start);
 154       _cards++;
 155 
 156       if (!card_region->is_on_dirty_cards_region_list()) {
 157         _g1h->push_dirty_cards_region(card_region);
 158       }
 159 
 160       // If the card is dirty, then we will scan it during updateRS.
 161       if (!card_region->in_collection_set() &&
 162           !_ct_bs->is_card_dirty(card_index)) {
 163         scanCard(card_index, card_region);
 164       }
 165     }
 166     if (!_try_claimed) {
 167       // Scan the strong code root list attached to the current region
 168       scan_strong_code_roots(r);
 169 
 170       hrrs->set_iter_complete();
 171     }
 172     return false;


 511         JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
 512       sdcq->enqueue(card_ptr);
 513     }
 514   } else {
 515     _conc_refine_cards++;
 516   }
 517 
 518   // This gets set to true if the card being refined has
 519   // references that point into the collection set.
 520   bool has_refs_into_cset = trigger_cl.triggered();
 521 
 522   // We should only be detecting that the card contains references
 523   // that point into the collection set if the current thread is
 524   // a GC worker thread.
 525   assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
 526            "invalid result at non safepoint");
 527 
 528   return has_refs_into_cset;
 529 }
 530 
 531 void G1RemSet::print_periodic_summary_info(const char* header, uint period_count) {
 532   if ((G1SummarizeRSetStatsPeriod > 0) && log_is_enabled(Trace, gc, remset) &&
 533       (period_count % G1SummarizeRSetStatsPeriod == 0)) {
 534 
 535     if (!_prev_period_summary.initialized()) {
 536       _prev_period_summary.initialize(this);
 537     }
 538 
 539     G1RemSetSummary current;
 540     current.initialize(this);

 541     _prev_period_summary.subtract_from(&current);
 542 
 543     LogHandle(gc, remset) log;
 544     log.trace("%s", header);
 545     ResourceMark rm;
 546     _prev_period_summary.print_on(log.trace_stream());
 547 
 548     _prev_period_summary.set(&current);
 549   }
 550 }
 551 
 552 void G1RemSet::print_summary_info() {
 553   LogHandle(gc, remset, exit) log;
 554   if (log.is_trace()) {
 555     log.trace(" Cumulative RS summary");
 556     G1RemSetSummary current;
 557     current.initialize(this);
 558     ResourceMark rm;
 559     current.print_on(log.trace_stream());







 560   }


 561 }
 562 
 563 void G1RemSet::prepare_for_verify() {
 564   if (G1HRRSFlushLogBuffersOnVerify &&
 565       (VerifyBeforeGC || VerifyAfterGC)
 566       &&  (!_g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC)) {
 567     cleanupHRRS();
 568     _g1->set_refine_cte_cl_concurrency(false);
 569     if (SafepointSynchronize::is_at_safepoint()) {
 570       DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
 571       dcqs.concatenate_logs();
 572     }
 573 
 574     G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
 575     bool use_hot_card_cache = hot_card_cache->use_cache();
 576     hot_card_cache->set_use_cache(false);
 577 
 578     DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
 579     updateRS(&into_cset_dcq, 0);
 580     _g1->into_cset_dirty_card_queue_set().clear();
< prev index next >