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

Print this page
rev 2585 : [mq]: g1-reference-processing


 217 // Then thread t will start at region t * floor (n/p)
 218 
 219 HeapRegion* G1RemSet::calculateStartRegion(int worker_i) {
 220   HeapRegion* result = _g1p->collection_set();
 221   if (ParallelGCThreads > 0) {
 222     size_t cs_size = _g1p->collection_set_size();
 223     int n_workers = _g1->workers()->total_workers();
 224     size_t cs_spans = cs_size / n_workers;
 225     size_t ind      = cs_spans * worker_i;
 226     for (size_t i = 0; i < ind; i++)
 227       result = result->next_in_collection_set();
 228   }
 229   return result;
 230 }
 231 
 232 void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
 233   double rs_time_start = os::elapsedTime();
 234   HeapRegion *startRegion = calculateStartRegion(worker_i);
 235 
 236   ScanRSClosure scanRScl(oc, worker_i);

 237   _g1->collection_set_iterate_from(startRegion, &scanRScl);
 238   scanRScl.set_try_claimed();
 239   _g1->collection_set_iterate_from(startRegion, &scanRScl);
 240 
 241   double scan_rs_time_sec = os::elapsedTime() - rs_time_start;
 242 
 243   assert( _cards_scanned != NULL, "invariant" );
 244   _cards_scanned[worker_i] = scanRScl.cards_done();
 245 
 246   _g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
 247 }
 248 
 249 // Closure used for updating RSets and recording references that
 250 // point into the collection set. Only called during an
 251 // evacuation pause.
 252 
 253 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
 254   G1RemSet* _g1rs;
 255   DirtyCardQueue* _into_cset_dcq;
 256 public:


 266     assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
 267     assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker");
 268 
 269     if (_g1rs->concurrentRefineOneCard(card_ptr, worker_i, true)) {
 270       // 'card_ptr' contains references that point into the collection
 271       // set. We need to record the card in the DCQS
 272       // (G1CollectedHeap::into_cset_dirty_card_queue_set())
 273       // that's used for that purpose.
 274       //
 275       // Enqueue the card
 276       _into_cset_dcq->enqueue(card_ptr);
 277     }
 278     return true;
 279   }
 280 };
 281 
 282 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
 283   double start = os::elapsedTime();
 284   // Apply the given closure to all remaining log entries.
 285   RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);

 286   _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
 287 
 288   // Now there should be no dirty cards.
 289   if (G1RSLogCheckCardTable) {
 290     CountNonCleanMemRegionClosure cl(_g1);
 291     _ct_bs->mod_card_iterate(&cl);
 292     // XXX This isn't true any more: keeping cards of young regions
 293     // marked dirty broke it.  Need some reasonable fix.
 294     guarantee(cl.n() == 0, "Card table should be clean.");
 295   }
 296 
 297   _g1p->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
 298 }
 299 
 300 class CountRSSizeClosure: public HeapRegionClosure {
 301   size_t _n;
 302   size_t _tot;
 303   size_t _max;
 304   HeapRegion* _max_r;
 305   enum {


 449   G1CollectedHeap* _g1;
 450   CardTableModRefBS* _ct_bs;
 451 public:
 452   UpdateRSetCardTableEntryIntoCSetClosure(G1CollectedHeap* g1,
 453                                           CardTableModRefBS* bs):
 454     _g1(g1), _ct_bs(bs)
 455   { }
 456 
 457   bool do_card_ptr(jbyte* card_ptr, int worker_i) {
 458     // Construct the region representing the card.
 459     HeapWord* start = _ct_bs->addr_for(card_ptr);
 460     // And find the region containing it.
 461     HeapRegion* r = _g1->heap_region_containing(start);
 462     assert(r != NULL, "unexpected null");
 463 
 464     // Scan oops in the card looking for references into the collection set
 465     HeapWord* end   = _ct_bs->addr_for(card_ptr + 1);
 466     MemRegion scanRegion(start, end);
 467 
 468     UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set());
 469     FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl);
 470     FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl);
 471 
 472     // We can pass false as the "filter_young" parameter here as:
 473     // * we should be in a STW pause,
 474     // * the DCQS to which this closure is applied is used to hold
 475     //   references that point into the collection set from the prior
 476     //   RSet updating,
 477     // * the post-write barrier shouldn't be logging updates to young
 478     //   regions (but there is a situation where this can happen - see
 479     //   the comment in G1RemSet::concurrentRefineOneCard below -
 480     //   that should not be applicable here), and
 481     // * during actual RSet updating, the filtering of cards in young
 482     //   regions in HeapRegion::oops_on_card_seq_iterate_careful is
 483     //   employed.
 484     // As a result, when this closure is applied to "refs into cset"
 485     // DCQS, we shouldn't see any cards in young regions.
 486     update_rs_cl.set_region(r);
 487     HeapWord* stop_point =
 488       r->oops_on_card_seq_iterate_careful(scanRegion,
 489                                           &filter_then_update_rs_cset_oop_cl,


 625   HeapRegion* r = _g1->heap_region_containing(start);
 626   assert(r != NULL, "unexpected null");
 627 
 628   HeapWord* end   = _ct_bs->addr_for(card_ptr + 1);
 629   MemRegion dirtyRegion(start, end);
 630 
 631 #if CARD_REPEAT_HISTO
 632   init_ct_freq_table(_g1->max_capacity());
 633   ct_freq_note_card(_ct_bs->index_for(start));
 634 #endif
 635 
 636   assert(!check_for_refs_into_cset || _cset_rs_update_cl[worker_i] != NULL, "sanity");
 637   UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1,
 638                                                _g1->g1_rem_set(),
 639                                                _cset_rs_update_cl[worker_i],
 640                                                check_for_refs_into_cset,
 641                                                worker_i);
 642   update_rs_oop_cl.set_from(r);
 643 
 644   TriggerClosure trigger_cl;
 645   FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl);
 646   InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl);
 647   Mux2Closure mux(&invoke_cl, &update_rs_oop_cl);
 648 
 649   FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r,
 650                         (check_for_refs_into_cset ?
 651                                 (OopClosure*)&mux :
 652                                 (OopClosure*)&update_rs_oop_cl));
 653 
 654   // The region for the current card may be a young region. The
 655   // current card may have been a card that was evicted from the
 656   // card cache. When the card was inserted into the cache, we had
 657   // determined that its region was non-young. While in the cache,
 658   // the region may have been freed during a cleanup pause, reallocated
 659   // and tagged as young.
 660   //
 661   // We wish to filter out cards for such a region but the current
 662   // thread, if we're running concurrently, may "see" the young type
 663   // change at any time (so an earlier "is_young" check may pass or
 664   // fail arbitrarily). We tell the iteration code to perform this
 665   // filtering when it has been determined that there has been an actual




 217 // Then thread t will start at region t * floor (n/p)
 218 
 219 HeapRegion* G1RemSet::calculateStartRegion(int worker_i) {
 220   HeapRegion* result = _g1p->collection_set();
 221   if (ParallelGCThreads > 0) {
 222     size_t cs_size = _g1p->collection_set_size();
 223     int n_workers = _g1->workers()->total_workers();
 224     size_t cs_spans = cs_size / n_workers;
 225     size_t ind      = cs_spans * worker_i;
 226     for (size_t i = 0; i < ind; i++)
 227       result = result->next_in_collection_set();
 228   }
 229   return result;
 230 }
 231 
 232 void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
 233   double rs_time_start = os::elapsedTime();
 234   HeapRegion *startRegion = calculateStartRegion(worker_i);
 235 
 236   ScanRSClosure scanRScl(oc, worker_i);
 237 
 238   _g1->collection_set_iterate_from(startRegion, &scanRScl);
 239   scanRScl.set_try_claimed();
 240   _g1->collection_set_iterate_from(startRegion, &scanRScl);
 241 
 242   double scan_rs_time_sec = os::elapsedTime() - rs_time_start;
 243 
 244   assert( _cards_scanned != NULL, "invariant" );
 245   _cards_scanned[worker_i] = scanRScl.cards_done();
 246 
 247   _g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
 248 }
 249 
 250 // Closure used for updating RSets and recording references that
 251 // point into the collection set. Only called during an
 252 // evacuation pause.
 253 
 254 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
 255   G1RemSet* _g1rs;
 256   DirtyCardQueue* _into_cset_dcq;
 257 public:


 267     assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
 268     assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker");
 269 
 270     if (_g1rs->concurrentRefineOneCard(card_ptr, worker_i, true)) {
 271       // 'card_ptr' contains references that point into the collection
 272       // set. We need to record the card in the DCQS
 273       // (G1CollectedHeap::into_cset_dirty_card_queue_set())
 274       // that's used for that purpose.
 275       //
 276       // Enqueue the card
 277       _into_cset_dcq->enqueue(card_ptr);
 278     }
 279     return true;
 280   }
 281 };
 282 
 283 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
 284   double start = os::elapsedTime();
 285   // Apply the given closure to all remaining log entries.
 286   RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
 287 
 288   _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
 289 
 290   // Now there should be no dirty cards.
 291   if (G1RSLogCheckCardTable) {
 292     CountNonCleanMemRegionClosure cl(_g1);
 293     _ct_bs->mod_card_iterate(&cl);
 294     // XXX This isn't true any more: keeping cards of young regions
 295     // marked dirty broke it.  Need some reasonable fix.
 296     guarantee(cl.n() == 0, "Card table should be clean.");
 297   }
 298 
 299   _g1p->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
 300 }
 301 
 302 class CountRSSizeClosure: public HeapRegionClosure {
 303   size_t _n;
 304   size_t _tot;
 305   size_t _max;
 306   HeapRegion* _max_r;
 307   enum {


 451   G1CollectedHeap* _g1;
 452   CardTableModRefBS* _ct_bs;
 453 public:
 454   UpdateRSetCardTableEntryIntoCSetClosure(G1CollectedHeap* g1,
 455                                           CardTableModRefBS* bs):
 456     _g1(g1), _ct_bs(bs)
 457   { }
 458 
 459   bool do_card_ptr(jbyte* card_ptr, int worker_i) {
 460     // Construct the region representing the card.
 461     HeapWord* start = _ct_bs->addr_for(card_ptr);
 462     // And find the region containing it.
 463     HeapRegion* r = _g1->heap_region_containing(start);
 464     assert(r != NULL, "unexpected null");
 465 
 466     // Scan oops in the card looking for references into the collection set
 467     HeapWord* end   = _ct_bs->addr_for(card_ptr + 1);
 468     MemRegion scanRegion(start, end);
 469 
 470     UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set());
 471     FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl, NULL /* rp */);
 472     FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl);
 473 
 474     // We can pass false as the "filter_young" parameter here as:
 475     // * we should be in a STW pause,
 476     // * the DCQS to which this closure is applied is used to hold
 477     //   references that point into the collection set from the prior
 478     //   RSet updating,
 479     // * the post-write barrier shouldn't be logging updates to young
 480     //   regions (but there is a situation where this can happen - see
 481     //   the comment in G1RemSet::concurrentRefineOneCard below -
 482     //   that should not be applicable here), and
 483     // * during actual RSet updating, the filtering of cards in young
 484     //   regions in HeapRegion::oops_on_card_seq_iterate_careful is
 485     //   employed.
 486     // As a result, when this closure is applied to "refs into cset"
 487     // DCQS, we shouldn't see any cards in young regions.
 488     update_rs_cl.set_region(r);
 489     HeapWord* stop_point =
 490       r->oops_on_card_seq_iterate_careful(scanRegion,
 491                                           &filter_then_update_rs_cset_oop_cl,


 627   HeapRegion* r = _g1->heap_region_containing(start);
 628   assert(r != NULL, "unexpected null");
 629 
 630   HeapWord* end   = _ct_bs->addr_for(card_ptr + 1);
 631   MemRegion dirtyRegion(start, end);
 632 
 633 #if CARD_REPEAT_HISTO
 634   init_ct_freq_table(_g1->max_capacity());
 635   ct_freq_note_card(_ct_bs->index_for(start));
 636 #endif
 637 
 638   assert(!check_for_refs_into_cset || _cset_rs_update_cl[worker_i] != NULL, "sanity");
 639   UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1,
 640                                                _g1->g1_rem_set(),
 641                                                _cset_rs_update_cl[worker_i],
 642                                                check_for_refs_into_cset,
 643                                                worker_i);
 644   update_rs_oop_cl.set_from(r);
 645 
 646   TriggerClosure trigger_cl;
 647   FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl, NULL /* rp */);
 648   InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl);
 649   Mux2Closure mux(&invoke_cl, &update_rs_oop_cl);
 650 
 651   FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r,
 652                         (check_for_refs_into_cset ?
 653                                 (OopClosure*)&mux :
 654                                 (OopClosure*)&update_rs_oop_cl));
 655 
 656   // The region for the current card may be a young region. The
 657   // current card may have been a card that was evicted from the
 658   // card cache. When the card was inserted into the cache, we had
 659   // determined that its region was non-young. While in the cache,
 660   // the region may have been freed during a cleanup pause, reallocated
 661   // and tagged as young.
 662   //
 663   // We wish to filter out cards for such a region but the current
 664   // thread, if we're running concurrently, may "see" the young type
 665   // change at any time (so an earlier "is_young" check may pass or
 666   // fail arbitrarily). We tell the iteration code to perform this
 667   // filtering when it has been determined that there has been an actual