< 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;


 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(&current);
 562   print_summary_info(&_prev_period_summary, header);




 563 
 564   _prev_period_summary.set(&current);

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



 568   G1RemSetSummary current;
 569   current.initialize(this);
 570 
 571   print_summary_info(&current, " 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(&current);
 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(&current);
 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();
< prev index next >