comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 796:29e7d79232b9

6819065: G1: eliminate high serial card table clearing time Reviewed-by: iveresov, tonyp
author apetrusenko
date Tue, 19 May 2009 04:05:31 -0700
parents 315a5d70b295
children d44bdab1c03d
comparison
equal deleted inserted replaced
795:215f81b4d9b3 796:29e7d79232b9
442 curr = curr->get_next_young_region(); 442 curr = curr->get_next_young_region();
443 } 443 }
444 } 444 }
445 445
446 gclog_or_tty->print_cr(""); 446 gclog_or_tty->print_cr("");
447 }
448
449 void G1CollectedHeap::push_dirty_cards_region(HeapRegion* hr)
450 {
451 // Claim the right to put the region on the dirty cards region list
452 // by installing a self pointer.
453 HeapRegion* next = hr->get_next_dirty_cards_region();
454 if (next == NULL) {
455 HeapRegion* res = (HeapRegion*)
456 Atomic::cmpxchg_ptr(hr, hr->next_dirty_cards_region_addr(),
457 NULL);
458 if (res == NULL) {
459 HeapRegion* head;
460 do {
461 // Put the region to the dirty cards region list.
462 head = _dirty_cards_region_list;
463 next = (HeapRegion*)
464 Atomic::cmpxchg_ptr(hr, &_dirty_cards_region_list, head);
465 if (next == head) {
466 assert(hr->get_next_dirty_cards_region() == hr,
467 "hr->get_next_dirty_cards_region() != hr");
468 if (next == NULL) {
469 // The last region in the list points to itself.
470 hr->set_next_dirty_cards_region(hr);
471 } else {
472 hr->set_next_dirty_cards_region(next);
473 }
474 }
475 } while (next != head);
476 }
477 }
478 }
479
480 HeapRegion* G1CollectedHeap::pop_dirty_cards_region()
481 {
482 HeapRegion* head;
483 HeapRegion* hr;
484 do {
485 head = _dirty_cards_region_list;
486 if (head == NULL) {
487 return NULL;
488 }
489 HeapRegion* new_head = head->get_next_dirty_cards_region();
490 if (head == new_head) {
491 // The last region.
492 new_head = NULL;
493 }
494 hr = (HeapRegion*)Atomic::cmpxchg_ptr(new_head, &_dirty_cards_region_list,
495 head);
496 } while (hr != head);
497 assert(hr != NULL, "invariant");
498 hr->set_next_dirty_cards_region(NULL);
499 return hr;
447 } 500 }
448 501
449 void G1CollectedHeap::stop_conc_gc_threads() { 502 void G1CollectedHeap::stop_conc_gc_threads() {
450 _cg1r->stop(); 503 _cg1r->stop();
451 _czft->stop(); 504 _czft->stop();
1327 _unclean_regions_coming(false), 1380 _unclean_regions_coming(false),
1328 _young_list(new YoungList(this)), 1381 _young_list(new YoungList(this)),
1329 _gc_time_stamp(0), 1382 _gc_time_stamp(0),
1330 _surviving_young_words(NULL), 1383 _surviving_young_words(NULL),
1331 _in_cset_fast_test(NULL), 1384 _in_cset_fast_test(NULL),
1332 _in_cset_fast_test_base(NULL) { 1385 _in_cset_fast_test_base(NULL),
1386 _dirty_cards_region_list(NULL) {
1333 _g1h = this; // To catch bugs. 1387 _g1h = this; // To catch bugs.
1334 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { 1388 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) {
1335 vm_exit_during_initialization("Failed necessary allocation."); 1389 vm_exit_during_initialization("Failed necessary allocation.");
1336 } 1390 }
1337 int n_queues = MAX2((int)ParallelGCThreads, 1); 1391 int n_queues = MAX2((int)ParallelGCThreads, 1);
4689 4743
4690 list = list->get_next_young_region(); 4744 list = list->get_next_young_region();
4691 } 4745 }
4692 } 4746 }
4693 4747
4748
4749 class G1ParCleanupCTTask : public AbstractGangTask {
4750 CardTableModRefBS* _ct_bs;
4751 G1CollectedHeap* _g1h;
4752 public:
4753 G1ParCleanupCTTask(CardTableModRefBS* ct_bs,
4754 G1CollectedHeap* g1h) :
4755 AbstractGangTask("G1 Par Cleanup CT Task"),
4756 _ct_bs(ct_bs),
4757 _g1h(g1h)
4758 { }
4759
4760 void work(int i) {
4761 HeapRegion* r;
4762 while (r = _g1h->pop_dirty_cards_region()) {
4763 clear_cards(r);
4764 }
4765 }
4766 void clear_cards(HeapRegion* r) {
4767 // Cards for Survivor and Scan-Only regions will be dirtied later.
4768 if (!r->is_scan_only() && !r->is_survivor()) {
4769 _ct_bs->clear(MemRegion(r->bottom(), r->end()));
4770 }
4771 }
4772 };
4773
4774
4694 void G1CollectedHeap::cleanUpCardTable() { 4775 void G1CollectedHeap::cleanUpCardTable() {
4695 CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set()); 4776 CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set());
4696 double start = os::elapsedTime(); 4777 double start = os::elapsedTime();
4697 4778
4698 ct_bs->clear(_g1_committed); 4779 // Iterate over the dirty cards region list.
4699 4780 G1ParCleanupCTTask cleanup_task(ct_bs, this);
4781 if (ParallelGCThreads > 0) {
4782 set_par_threads(workers()->total_workers());
4783 workers()->run_task(&cleanup_task);
4784 set_par_threads(0);
4785 } else {
4786 while (_dirty_cards_region_list) {
4787 HeapRegion* r = _dirty_cards_region_list;
4788 cleanup_task.clear_cards(r);
4789 _dirty_cards_region_list = r->get_next_dirty_cards_region();
4790 if (_dirty_cards_region_list == r) {
4791 // The last region.
4792 _dirty_cards_region_list = NULL;
4793 }
4794 r->set_next_dirty_cards_region(NULL);
4795 }
4796 }
4700 // now, redirty the cards of the scan-only and survivor regions 4797 // now, redirty the cards of the scan-only and survivor regions
4701 // (it seemed faster to do it this way, instead of iterating over 4798 // (it seemed faster to do it this way, instead of iterating over
4702 // all regions and then clearing / dirtying as approprite) 4799 // all regions and then clearing / dirtying as appropriate)
4703 dirtyCardsForYoungRegions(ct_bs, _young_list->first_scan_only_region()); 4800 dirtyCardsForYoungRegions(ct_bs, _young_list->first_scan_only_region());
4704 dirtyCardsForYoungRegions(ct_bs, _young_list->first_survivor_region()); 4801 dirtyCardsForYoungRegions(ct_bs, _young_list->first_survivor_region());
4705 4802
4706 double elapsed = os::elapsedTime() - start; 4803 double elapsed = os::elapsedTime() - start;
4707 g1_policy()->record_clear_ct_time( elapsed * 1000.0); 4804 g1_policy()->record_clear_ct_time( elapsed * 1000.0);