< prev index next >

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

Print this page




  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;


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







 557   G1RemSetSummary current;
 558   current.initialize(this);
 559 
 560   _prev_period_summary.subtract_from(&current);
 561   print_summary_info(&_prev_period_summary, header);




 562 
 563   _prev_period_summary.set(&current);

 564 }
 565 
 566 void G1RemSet::print_summary_info() {



 567   G1RemSetSummary current;
 568   current.initialize(this);
 569 
 570   print_summary_info(&current, " Cumulative RS summary");
 571 }
 572 
 573 void G1RemSet::print_summary_info(G1RemSetSummary * summary, const char * header) {
 574   assert(summary != NULL, "just checking");
 575 
 576   if (header != NULL) {
 577     gclog_or_tty->print_cr("%s", header);
 578   }
 579 
 580   summary->print_on(gclog_or_tty);
 581 }
 582 
 583 void G1RemSet::prepare_for_verify() {
 584   if (G1HRRSFlushLogBuffersOnVerify &&
 585       (VerifyBeforeGC || VerifyAfterGC)
 586       &&  (!_g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC)) {
 587     cleanupHRRS();
 588     _g1->set_refine_cte_cl_concurrency(false);
 589     if (SafepointSynchronize::is_at_safepoint()) {
 590       DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
 591       dcqs.concatenate_logs();
 592     }
 593 
 594     G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
 595     bool use_hot_card_cache = hot_card_cache->use_cache();
 596     hot_card_cache->set_use_cache(false);
 597 
 598     DirtyCardQueue into_cset_dcq(&_into_cset_dirty_card_queue_set);
 599     updateRS(&into_cset_dcq, 0);
 600     _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;


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

 550     _prev_period_summary.subtract_from(&current);
 551 
 552     LogHandle(gc, remset) log;
 553     log.trace("%s", header);
 554     ResourceMark rm;
 555     _prev_period_summary.print_on(log.trace_stream());
 556 
 557     _prev_period_summary.set(&current);
 558   }
 559 }
 560 
 561 void G1RemSet::print_summary_info() {
 562   LogHandle(gc, remset, exit) log;
 563   if (log.is_trace()) {
 564     log.trace(" Cumulative RS summary");
 565     G1RemSetSummary current;
 566     current.initialize(this);
 567     ResourceMark rm;
 568     current.print_on(log.trace_stream());







 569   }


 570 }
 571 
 572 void G1RemSet::prepare_for_verify() {
 573   if (G1HRRSFlushLogBuffersOnVerify &&
 574       (VerifyBeforeGC || VerifyAfterGC)
 575       &&  (!_g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC)) {
 576     cleanupHRRS();
 577     _g1->set_refine_cte_cl_concurrency(false);
 578     if (SafepointSynchronize::is_at_safepoint()) {
 579       DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
 580       dcqs.concatenate_logs();
 581     }
 582 
 583     G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
 584     bool use_hot_card_cache = hot_card_cache->use_cache();
 585     hot_card_cache->set_use_cache(false);
 586 
 587     DirtyCardQueue into_cset_dcq(&_into_cset_dirty_card_queue_set);
 588     updateRS(&into_cset_dcq, 0);
 589     _into_cset_dirty_card_queue_set.clear();
< prev index next >