< prev index next >

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

Print this page
rev 49670 : imported patch 8178105-switch-at-remark
rev 49673 : imported patch 8178105-8200371-assert-problem
rev 49677 : imported patch 8200426-g1h-refactoring
rev 49678 : imported patch 8200426-sangheon-review
rev 49680 : imported patch 6672778-partial-queue-trimming
rev 49681 : [mq]: 6672778-refactoring


 289   _prev_period_summary() {
 290 }
 291 
 292 G1RemSet::~G1RemSet() {
 293   if (_scan_state != NULL) {
 294     delete _scan_state;
 295   }
 296 }
 297 
 298 uint G1RemSet::num_par_rem_sets() {
 299   return DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads() + MAX2(ConcGCThreads, ParallelGCThreads);
 300 }
 301 
 302 void G1RemSet::initialize(size_t capacity, uint max_regions) {
 303   G1FromCardCache::initialize(num_par_rem_sets(), max_regions);
 304   _scan_state->initialize(max_regions);
 305 }
 306 
 307 G1ScanRSForRegionClosure::G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
 308                                                    G1ScanObjsDuringScanRSClosure* scan_obj_on_card,
 309                                                    CodeBlobClosure* code_root_cl,
 310                                                    uint worker_i) :
 311   _scan_state(scan_state),


 312   _scan_objs_on_card_cl(scan_obj_on_card),
 313   _code_root_cl(code_root_cl),
 314   _strong_code_root_scan_time_sec(0.0),
 315   _cards_claimed(0),
 316   _cards_scanned(0),
 317   _cards_skipped(0),
 318   _worker_i(worker_i) {
 319   _g1h = G1CollectedHeap::heap();
 320   _bot = _g1h->bot();
 321   _ct = _g1h->card_table();





 322 }
 323 
 324 void G1ScanRSForRegionClosure::scan_card(MemRegion mr, uint region_idx_for_card) {
 325   HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
 326   _scan_objs_on_card_cl->set_region(card_region);
 327   card_region->oops_on_card_seq_iterate_careful<true>(mr, _scan_objs_on_card_cl);
 328   _scan_objs_on_card_cl->trim_queue_partially();
 329   _cards_scanned++;
 330 }
 331 
 332 void G1ScanRSForRegionClosure::scan_strong_code_roots(HeapRegion* r) {
 333   double scan_start = os::elapsedTime();
 334   r->strong_code_roots_do(_code_root_cl);
 335   _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
 336 }
 337 
 338 void G1ScanRSForRegionClosure::claim_card(size_t card_index, const uint region_idx_for_card){
 339   _ct->set_card_claimed(card_index);
 340   _scan_state->add_dirty_region(region_idx_for_card);
 341 }
 342 
 343 bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
 344   assert(r->in_collection_set(), "should only be called on elements of CS.");
 345   uint region_idx = r->hrm_index();
 346 
 347   if (_scan_state->iter_is_complete(region_idx)) {
 348     return false;
 349   }
 350   if (_scan_state->claim_iter(region_idx)) {
 351     // If we ever free the collection set concurrently, we should also
 352     // clear the card table concurrently therefore we won't need to
 353     // add regions of the collection set to the dirty cards region.
 354     _scan_state->add_dirty_region(region_idx);
 355   }
 356 
 357   // We claim cards in blocks so as to reduce the contention.
 358   size_t const block_size = G1RSetScanBlockSize;
 359 
 360   HeapRegionRemSetIterator iter(r->rem_set());
 361   size_t card_index;
 362 
 363   size_t claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
 364   for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
 365     if (current_card >= claimed_card_block + block_size) {
 366       claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
 367     }
 368     if (current_card < claimed_card_block) {
 369       _cards_skipped++;


 381 
 382     assert(_g1h->region_at(region_idx_for_card)->is_in_reserved(card_start),
 383            "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
 384     HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
 385     if (card_start >= top) {
 386       continue;
 387     }
 388 
 389     // We claim lazily (so races are possible but they're benign), which reduces the
 390     // number of duplicate scans (the rsets of the regions in the cset can intersect).
 391     // Claim the card after checking bounds above: the remembered set may contain
 392     // random cards into current survivor, and we would then have an incorrectly
 393     // claimed card in survivor space. Card table clear does not reset the card table
 394     // of survivor space regions.
 395     claim_card(card_index, region_idx_for_card);
 396 
 397     MemRegion const mr(card_start, MIN2(card_start + BOTConstants::N_words, top));
 398 
 399     scan_card(mr, region_idx_for_card);
 400   }



























 401   if (_scan_state->set_iter_complete(region_idx)) {

 402     // Scan the strong code root list attached to the current region
 403     scan_strong_code_roots(r);



 404   }
 405   return false;
 406 }
 407 
 408 void G1RemSet::scan_rem_set(G1ParScanThreadState* pss,
 409                             uint worker_i) {
 410   double rs_time_start = os::elapsedTime();
 411 
 412   CodeBlobClosure* heap_region_codeblobs = pss->closures()->weak_codeblobs();
 413 
 414   G1ScanObjsDuringScanRSClosure scan_cl(_g1h, pss);
 415   G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, heap_region_codeblobs, worker_i);
 416   _g1h->collection_set_iterate_from(&cl, worker_i);
 417 
 418   double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) -
 419                             cl.strong_code_root_scan_time_sec();
 420 
 421   G1GCPhaseTimes* p = _g1p->phase_times();
 422 
 423   double scan_rs_trim_queue_time = TicksToTimeHelper::seconds(scan_cl.trim_ticks_and_reset());
 424 
 425   p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec);
 426   p->move_time_secs(G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ObjCopy, worker_i, scan_rs_trim_queue_time);
 427 
 428   p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
 429   p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
 430   p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
 431 
 432   p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, cl.strong_code_root_scan_time_sec());
 433   p->move_time_secs(G1GCPhaseTimes::CodeRoots, G1GCPhaseTimes::ObjCopy, worker_i, pss->closures()->trim_time_seconds());
 434 }
 435 
 436 // Closure used for updating rem sets. Only called during an evacuation pause.
 437 class G1RefineCardClosure: public CardTableEntryClosure {
 438   G1RemSet* _g1rs;
 439   G1ScanObjsDuringUpdateRSClosure* _update_rs_cl;
 440 
 441   size_t _cards_scanned;
 442   size_t _cards_skipped;
 443 public:
 444   G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanObjsDuringUpdateRSClosure* update_rs_cl) :
 445     _g1rs(g1h->g1_rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0)
 446   {}
 447 
 448   bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
 449     // The only time we care about recording cards that
 450     // contain references that point into the collection set
 451     // is during RSet updating within an evacuation pause.
 452     // In this case worker_i should be the id of a GC worker thread.
 453     assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
 454 
 455     bool card_scanned = _g1rs->refine_card_during_gc(card_ptr, _update_rs_cl);
 456 
 457     if (card_scanned) {
 458       _update_rs_cl->trim_queue_partially();
 459       _cards_scanned++;
 460     } else {
 461       _cards_skipped++;
 462     }
 463     return true;
 464   }
 465 
 466   size_t cards_scanned() const { return _cards_scanned; }
 467   size_t cards_skipped() const { return _cards_skipped; }
 468 };
 469 
 470 void G1RemSet::update_rem_set(G1ParScanThreadState* pss, uint worker_i) {
 471   G1GCPhaseTimes* p = _g1p->phase_times();
 472   double scan_hcc_trim_queue_time = 0.0;
 473 
 474   G1ScanObjsDuringUpdateRSClosure update_rs_cl(_g1h, pss, worker_i);
 475   G1RefineCardClosure refine_card_cl(_g1h, &update_rs_cl);
 476 
 477   {
 478     G1GCParPhaseTimesTracker x(p, G1GCPhaseTimes::UpdateRS, worker_i);
 479     if (G1HotCardCache::default_use_cache()) {
 480       {
 481         // Apply the closure to the entries of the hot card cache.
 482         G1GCParPhaseTimesTracker y(p, G1GCPhaseTimes::ScanHCC, worker_i);



 483         _g1h->iterate_hcc_closure(&refine_card_cl, worker_i);
 484       }
 485       scan_hcc_trim_queue_time = TicksToTimeHelper::seconds(update_rs_cl.trim_ticks_and_reset());
 486       p->move_time_secs(G1GCPhaseTimes::ScanHCC, G1GCPhaseTimes::ObjCopy, worker_i, scan_hcc_trim_queue_time);
 487     }
 488     // Apply the closure to all remaining log entries.





 489     _g1h->iterate_dirty_card_closure(&refine_card_cl, worker_i);
 490   }
 491   double update_rs_trim_queue_time = TicksToTimeHelper::seconds(update_rs_cl.trim_ticks_and_reset());
 492 
 493   p->move_time_secs(G1GCPhaseTimes::UpdateRS, G1GCPhaseTimes::ObjCopy, worker_i, update_rs_trim_queue_time + scan_hcc_trim_queue_time);

 494 
 495   p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_scanned(), G1GCPhaseTimes::UpdateRSScannedCards);
 496   p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_skipped(), G1GCPhaseTimes::UpdateRSSkippedCards);
 497 }
 498 
 499 void G1RemSet::cleanupHRRS() {
 500   HeapRegionRemSet::cleanup();
 501 }
 502 
 503 void G1RemSet::oops_into_collection_set_do(G1ParScanThreadState* pss, uint worker_i) {
 504   update_rem_set(pss, worker_i);
 505   scan_rem_set(pss, worker_i);;
 506 }
 507 
 508 void G1RemSet::prepare_for_oops_into_collection_set_do() {
 509   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
 510   dcqs.concatenate_logs();
 511 
 512   _scan_state->reset();
 513 }




 289   _prev_period_summary() {
 290 }
 291 
 292 G1RemSet::~G1RemSet() {
 293   if (_scan_state != NULL) {
 294     delete _scan_state;
 295   }
 296 }
 297 
 298 uint G1RemSet::num_par_rem_sets() {
 299   return DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads() + MAX2(ConcGCThreads, ParallelGCThreads);
 300 }
 301 
 302 void G1RemSet::initialize(size_t capacity, uint max_regions) {
 303   G1FromCardCache::initialize(num_par_rem_sets(), max_regions);
 304   _scan_state->initialize(max_regions);
 305 }
 306 
 307 G1ScanRSForRegionClosure::G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
 308                                                    G1ScanObjsDuringScanRSClosure* scan_obj_on_card,
 309                                                    G1ParScanThreadState* pss,
 310                                                    uint worker_i) :
 311   _g1h(G1CollectedHeap::heap()),
 312   _ct(_g1h->card_table()),
 313   _pss(pss),
 314   _scan_objs_on_card_cl(scan_obj_on_card),
 315   _scan_state(scan_state),
 316   _worker_i(worker_i),
 317   _cards_claimed(0),
 318   _cards_scanned(0),
 319   _cards_skipped(0),
 320   _rem_set_root_scan_time(),
 321   _rem_set_trim_partially_time(),
 322   _strong_code_root_scan_time(),
 323   _strong_code_trim_partially_time() {
 324 }
 325 
 326 void G1ScanRSForRegionClosure::claim_card(size_t card_index, const uint region_idx_for_card){
 327   _ct->set_card_claimed(card_index);
 328   _scan_state->add_dirty_region(region_idx_for_card);
 329 }
 330 
 331 void G1ScanRSForRegionClosure::scan_card(MemRegion mr, uint region_idx_for_card) {
 332   HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
 333   _scan_objs_on_card_cl->set_region(card_region);
 334   card_region->oops_on_card_seq_iterate_careful<true>(mr, _scan_objs_on_card_cl);
 335   _scan_objs_on_card_cl->trim_queue_partially();
 336   _cards_scanned++;
 337 }
 338 
 339 void G1ScanRSForRegionClosure::scan_rem_set_roots(HeapRegion* r) {
 340   uint const region_idx = r->hrm_index();



 341 












 342   if (_scan_state->claim_iter(region_idx)) {
 343     // If we ever free the collection set concurrently, we should also
 344     // clear the card table concurrently therefore we won't need to
 345     // add regions of the collection set to the dirty cards region.
 346     _scan_state->add_dirty_region(region_idx);
 347   }
 348 
 349   // We claim cards in blocks so as to reduce the contention.
 350   size_t const block_size = G1RSetScanBlockSize;
 351 
 352   HeapRegionRemSetIterator iter(r->rem_set());
 353   size_t card_index;
 354 
 355   size_t claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
 356   for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
 357     if (current_card >= claimed_card_block + block_size) {
 358       claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
 359     }
 360     if (current_card < claimed_card_block) {
 361       _cards_skipped++;


 373 
 374     assert(_g1h->region_at(region_idx_for_card)->is_in_reserved(card_start),
 375            "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
 376     HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
 377     if (card_start >= top) {
 378       continue;
 379     }
 380 
 381     // We claim lazily (so races are possible but they're benign), which reduces the
 382     // number of duplicate scans (the rsets of the regions in the cset can intersect).
 383     // Claim the card after checking bounds above: the remembered set may contain
 384     // random cards into current survivor, and we would then have an incorrectly
 385     // claimed card in survivor space. Card table clear does not reset the card table
 386     // of survivor space regions.
 387     claim_card(card_index, region_idx_for_card);
 388 
 389     MemRegion const mr(card_start, MIN2(card_start + BOTConstants::N_words, top));
 390 
 391     scan_card(mr, region_idx_for_card);
 392   }
 393 }
 394 
 395 void G1ScanRSForRegionClosure::scan_strong_code_roots(HeapRegion* r) {
 396   Ticks const scan_start = Ticks::now();
 397   r->strong_code_roots_do(_pss->closures()->weak_codeblobs());
 398   _strong_code_root_scan_time += (Ticks::now() - scan_start);
 399 }
 400 
 401 bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
 402   assert(r->in_collection_set(),
 403          "Should only be called on elements of the collection set but region %u is not.",
 404          r->hrm_index());
 405   uint const region_idx = r->hrm_index();
 406 
 407   // Do an early out if we know we are complete.
 408   if (_scan_state->iter_is_complete(region_idx)) {
 409     return false;
 410   }
 411 
 412   {
 413     Ticks const start = Ticks::now();
 414     scan_rem_set_roots(r);
 415     Tickspan const trim_partially_time = _pss->trim_ticks_and_reset();
 416     _rem_set_root_scan_time += (Ticks::now() - start) - trim_partially_time;
 417     _rem_set_trim_partially_time += trim_partially_time;
 418   }
 419 
 420   if (_scan_state->set_iter_complete(region_idx)) {
 421     Ticks const start = Ticks::now();
 422     // Scan the strong code root list attached to the current region
 423     scan_strong_code_roots(r);
 424     Tickspan const trim_partially_time = _pss->trim_ticks_and_reset();
 425     _strong_code_root_scan_time += (Ticks::now() - start) - trim_partially_time;
 426     _strong_code_trim_partially_time += trim_partially_time;
 427   }
 428   return false;
 429 }
 430 
 431 void G1RemSet::scan_rem_set(G1ParScanThreadState* pss, uint worker_i) {





 432   G1ScanObjsDuringScanRSClosure scan_cl(_g1h, pss);
 433   G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, worker_i);
 434   _g1h->collection_set_iterate_from(&cl, worker_i);
 435 



 436   G1GCPhaseTimes* p = _g1p->phase_times();
 437 
 438   p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, TicksToTimeHelper::seconds(cl.rem_set_root_scan_time()));
 439   p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, TicksToTimeHelper::seconds(cl.rem_set_trim_partially_time()));


 440 
 441   p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
 442   p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
 443   p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
 444 
 445   p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, TicksToTimeHelper::seconds(cl.strong_code_root_scan_time()));
 446   p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, TicksToTimeHelper::seconds(cl.strong_code_root_trim_partially_time()));
 447 }
 448 
 449 // Closure used for updating rem sets. Only called during an evacuation pause.
 450 class G1RefineCardClosure: public CardTableEntryClosure {
 451   G1RemSet* _g1rs;
 452   G1ScanObjsDuringUpdateRSClosure* _update_rs_cl;
 453 
 454   size_t _cards_scanned;
 455   size_t _cards_skipped;
 456 public:
 457   G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanObjsDuringUpdateRSClosure* update_rs_cl) :
 458     _g1rs(g1h->g1_rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0)
 459   {}
 460 
 461   bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
 462     // The only time we care about recording cards that
 463     // contain references that point into the collection set
 464     // is during RSet updating within an evacuation pause.
 465     // In this case worker_i should be the id of a GC worker thread.
 466     assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
 467 
 468     bool card_scanned = _g1rs->refine_card_during_gc(card_ptr, _update_rs_cl);
 469 
 470     if (card_scanned) {
 471       _update_rs_cl->trim_queue_partially();
 472       _cards_scanned++;
 473     } else {
 474       _cards_skipped++;
 475     }
 476     return true;
 477   }
 478 
 479   size_t cards_scanned() const { return _cards_scanned; }
 480   size_t cards_skipped() const { return _cards_skipped; }
 481 };
 482 
 483 void G1RemSet::update_rem_set(G1ParScanThreadState* pss, uint worker_i) {
 484   G1GCPhaseTimes* p = _g1p->phase_times();

 485 
 486   // Apply closure to log entries in the HCC.




 487   if (G1HotCardCache::default_use_cache()) {
 488     {
 489       G1GCParPhaseTimesTracker x(p, G1GCPhaseTimes::ScanHCC, worker_i);
 490 
 491       G1ScanObjsDuringUpdateRSClosure scan_hcc_cl(_g1h, pss, worker_i);
 492       G1RefineCardClosure refine_card_cl(_g1h, &scan_hcc_cl);
 493 
 494       _g1h->iterate_hcc_closure(&refine_card_cl, worker_i);
 495     }
 496     double const scan_hcc_trim_queue_time = TicksToTimeHelper::seconds(pss->trim_ticks_and_reset());
 497     p->move_time_secs(G1GCPhaseTimes::ScanHCC, G1GCPhaseTimes::ObjCopy, worker_i, scan_hcc_trim_queue_time);
 498   }
 499 
 500   // Now apply the closure to all remaining log entries.
 501   G1ScanObjsDuringUpdateRSClosure update_rs_cl(_g1h, pss, worker_i);
 502   G1RefineCardClosure refine_card_cl(_g1h, &update_rs_cl);
 503   {
 504     G1GCParPhaseTimesTracker x(p, G1GCPhaseTimes::UpdateRS, worker_i);
 505     _g1h->iterate_dirty_card_closure(&refine_card_cl, worker_i);
 506   }

 507 
 508   double const update_rs_trim_queue_time = TicksToTimeHelper::seconds(pss->trim_ticks_and_reset());
 509   p->move_time_secs(G1GCPhaseTimes::UpdateRS, G1GCPhaseTimes::ObjCopy, worker_i, update_rs_trim_queue_time);
 510 
 511   p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_scanned(), G1GCPhaseTimes::UpdateRSScannedCards);
 512   p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_skipped(), G1GCPhaseTimes::UpdateRSSkippedCards);
 513 }
 514 
 515 void G1RemSet::cleanupHRRS() {
 516   HeapRegionRemSet::cleanup();
 517 }
 518 
 519 void G1RemSet::oops_into_collection_set_do(G1ParScanThreadState* pss, uint worker_i) {
 520   update_rem_set(pss, worker_i);
 521   scan_rem_set(pss, worker_i);;
 522 }
 523 
 524 void G1RemSet::prepare_for_oops_into_collection_set_do() {
 525   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
 526   dcqs.concatenate_logs();
 527 
 528   _scan_state->reset();
 529 }


< prev index next >