comparison src/share/vm/gc_implementation/g1/concurrentMark.cpp @ 2152:0fa27f37d4d4

6977804: G1: remove the zero-filling thread Summary: This changeset removes the zero-filling thread from G1 and collapses the two free region lists we had before (the "free" and "unclean" lists) into one. The new free list uses the new heap region sets / lists abstractions that we'll ultimately use it to keep track of all regions in the heap. A heap region set was also introduced for the humongous regions. Finally, this change increases the concurrency between the thread that completes freeing regions (after a cleanup pause) and the rest of the system (before we'd have to wait for said thread to complete before allocating a new region). The changest also includes a lot of refactoring and code simplification. Reviewed-by: jcoomes, johnc
author tonyp
date Wed, 19 Jan 2011 19:30:42 -0500
parents 7e37af9d69ef
children 97ba643ea3ed 234761c55641
comparison
equal deleted inserted replaced
2151:cb913d743d09 2152:0fa27f37d4d4
456 _parallel_marking_threads(0), 456 _parallel_marking_threads(0),
457 _sleep_factor(0.0), 457 _sleep_factor(0.0),
458 _marking_task_overhead(1.0), 458 _marking_task_overhead(1.0),
459 _cleanup_sleep_factor(0.0), 459 _cleanup_sleep_factor(0.0),
460 _cleanup_task_overhead(1.0), 460 _cleanup_task_overhead(1.0),
461 _cleanup_list("Cleanup List"),
461 _region_bm(max_regions, false /* in_resource_area*/), 462 _region_bm(max_regions, false /* in_resource_area*/),
462 _card_bm((rs.size() + CardTableModRefBS::card_size - 1) >> 463 _card_bm((rs.size() + CardTableModRefBS::card_size - 1) >>
463 CardTableModRefBS::card_shift, 464 CardTableModRefBS::card_shift,
464 false /* in_resource_area*/), 465 false /* in_resource_area*/),
465 _prevMarkBitMap(&_markBitMap1), 466 _prevMarkBitMap(&_markBitMap1),
518 assert(_markBitMap1.covers(rs), "_markBitMap1 inconsistency"); 519 assert(_markBitMap1.covers(rs), "_markBitMap1 inconsistency");
519 assert(_markBitMap2.covers(rs), "_markBitMap2 inconsistency"); 520 assert(_markBitMap2.covers(rs), "_markBitMap2 inconsistency");
520 521
521 SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set(); 522 SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set();
522 satb_qs.set_buffer_size(G1SATBBufferSize); 523 satb_qs.set_buffer_size(G1SATBBufferSize);
523
524 int size = (int) MAX2(ParallelGCThreads, (size_t)1);
525 _par_cleanup_thread_state = NEW_C_HEAP_ARRAY(ParCleanupThreadState*, size);
526 for (int i = 0 ; i < size; i++) {
527 _par_cleanup_thread_state[i] = new ParCleanupThreadState;
528 }
529 524
530 _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num); 525 _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num);
531 _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num); 526 _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num);
532 527
533 // so that the assertion in MarkingTaskQueue::task_queue doesn't fail 528 // so that the assertion in MarkingTaskQueue::task_queue doesn't fail
709 _active_tasks = 0; 704 _active_tasks = 0;
710 clear_concurrent_marking_in_progress(); 705 clear_concurrent_marking_in_progress();
711 } 706 }
712 707
713 ConcurrentMark::~ConcurrentMark() { 708 ConcurrentMark::~ConcurrentMark() {
714 int size = (int) MAX2(ParallelGCThreads, (size_t)1);
715 for (int i = 0; i < size; i++) delete _par_cleanup_thread_state[i];
716 FREE_C_HEAP_ARRAY(ParCleanupThreadState*,
717 _par_cleanup_thread_state);
718
719 for (int i = 0; i < (int) _max_task_num; ++i) { 709 for (int i = 0; i < (int) _max_task_num; ++i) {
720 delete _task_queues->queue(i); 710 delete _task_queues->queue(i);
721 delete _tasks[i]; 711 delete _tasks[i];
722 } 712 }
723 delete _task_queues; 713 delete _task_queues;
1508 G1CollectedHeap* _g1; 1498 G1CollectedHeap* _g1;
1509 int _worker_num; 1499 int _worker_num;
1510 size_t _max_live_bytes; 1500 size_t _max_live_bytes;
1511 size_t _regions_claimed; 1501 size_t _regions_claimed;
1512 size_t _freed_bytes; 1502 size_t _freed_bytes;
1513 size_t _cleared_h_regions; 1503 FreeRegionList _local_cleanup_list;
1514 size_t _freed_regions; 1504 HumongousRegionSet _humongous_proxy_set;
1515 UncleanRegionList* _unclean_region_list;
1516 double _claimed_region_time; 1505 double _claimed_region_time;
1517 double _max_region_time; 1506 double _max_region_time;
1518 1507
1519 public: 1508 public:
1520 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, 1509 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
1521 UncleanRegionList* list,
1522 int worker_num); 1510 int worker_num);
1523 size_t freed_bytes() { return _freed_bytes; } 1511 size_t freed_bytes() { return _freed_bytes; }
1524 size_t cleared_h_regions() { return _cleared_h_regions; } 1512 FreeRegionList* local_cleanup_list() {
1525 size_t freed_regions() { return _freed_regions; } 1513 return &_local_cleanup_list;
1526 UncleanRegionList* unclean_region_list() { 1514 }
1527 return _unclean_region_list; 1515 HumongousRegionSet* humongous_proxy_set() {
1516 return &_humongous_proxy_set;
1528 } 1517 }
1529 1518
1530 bool doHeapRegion(HeapRegion *r); 1519 bool doHeapRegion(HeapRegion *r);
1531 1520
1532 size_t max_live_bytes() { return _max_live_bytes; } 1521 size_t max_live_bytes() { return _max_live_bytes; }
1535 double max_region_time_sec() { return _max_region_time; } 1524 double max_region_time_sec() { return _max_region_time; }
1536 }; 1525 };
1537 1526
1538 class G1ParNoteEndTask: public AbstractGangTask { 1527 class G1ParNoteEndTask: public AbstractGangTask {
1539 friend class G1NoteEndOfConcMarkClosure; 1528 friend class G1NoteEndOfConcMarkClosure;
1529
1540 protected: 1530 protected:
1541 G1CollectedHeap* _g1h; 1531 G1CollectedHeap* _g1h;
1542 size_t _max_live_bytes; 1532 size_t _max_live_bytes;
1543 size_t _freed_bytes; 1533 size_t _freed_bytes;
1544 ConcurrentMark::ParCleanupThreadState** _par_cleanup_thread_state; 1534 FreeRegionList* _cleanup_list;
1535
1545 public: 1536 public:
1546 G1ParNoteEndTask(G1CollectedHeap* g1h, 1537 G1ParNoteEndTask(G1CollectedHeap* g1h,
1547 ConcurrentMark::ParCleanupThreadState** 1538 FreeRegionList* cleanup_list) :
1548 par_cleanup_thread_state) :
1549 AbstractGangTask("G1 note end"), _g1h(g1h), 1539 AbstractGangTask("G1 note end"), _g1h(g1h),
1550 _max_live_bytes(0), _freed_bytes(0), 1540 _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { }
1551 _par_cleanup_thread_state(par_cleanup_thread_state)
1552 {}
1553 1541
1554 void work(int i) { 1542 void work(int i) {
1555 double start = os::elapsedTime(); 1543 double start = os::elapsedTime();
1556 G1NoteEndOfConcMarkClosure g1_note_end(_g1h, 1544 G1NoteEndOfConcMarkClosure g1_note_end(_g1h, i);
1557 &_par_cleanup_thread_state[i]->list,
1558 i);
1559 if (G1CollectedHeap::use_parallel_gc_threads()) { 1545 if (G1CollectedHeap::use_parallel_gc_threads()) {
1560 _g1h->heap_region_par_iterate_chunked(&g1_note_end, i, 1546 _g1h->heap_region_par_iterate_chunked(&g1_note_end, i,
1561 HeapRegion::NoteEndClaimValue); 1547 HeapRegion::NoteEndClaimValue);
1562 } else { 1548 } else {
1563 _g1h->heap_region_iterate(&g1_note_end); 1549 _g1h->heap_region_iterate(&g1_note_end);
1564 } 1550 }
1565 assert(g1_note_end.complete(), "Shouldn't have yielded!"); 1551 assert(g1_note_end.complete(), "Shouldn't have yielded!");
1566 1552
1567 // Now finish up freeing the current thread's regions. 1553 // Now update the lists
1568 _g1h->finish_free_region_work(g1_note_end.freed_bytes(), 1554 _g1h->update_sets_after_freeing_regions(g1_note_end.freed_bytes(),
1569 g1_note_end.cleared_h_regions(), 1555 NULL /* free_list */,
1570 0, NULL); 1556 g1_note_end.humongous_proxy_set(),
1557 true /* par */);
1571 { 1558 {
1572 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); 1559 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
1573 _max_live_bytes += g1_note_end.max_live_bytes(); 1560 _max_live_bytes += g1_note_end.max_live_bytes();
1574 _freed_bytes += g1_note_end.freed_bytes(); 1561 _freed_bytes += g1_note_end.freed_bytes();
1562
1563 _cleanup_list->add_as_tail(g1_note_end.local_cleanup_list());
1564 assert(g1_note_end.local_cleanup_list()->is_empty(), "post-condition");
1575 } 1565 }
1576 double end = os::elapsedTime(); 1566 double end = os::elapsedTime();
1577 if (G1PrintParCleanupStats) { 1567 if (G1PrintParCleanupStats) {
1578 gclog_or_tty->print(" Worker thread %d [%8.3f..%8.3f = %8.3f ms] " 1568 gclog_or_tty->print(" Worker thread %d [%8.3f..%8.3f = %8.3f ms] "
1579 "claimed %d regions (tot = %8.3f ms, max = %8.3f ms).\n", 1569 "claimed %d regions (tot = %8.3f ms, max = %8.3f ms).\n",
1610 1600
1611 }; 1601 };
1612 1602
1613 G1NoteEndOfConcMarkClosure:: 1603 G1NoteEndOfConcMarkClosure::
1614 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, 1604 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
1615 UncleanRegionList* list,
1616 int worker_num) 1605 int worker_num)
1617 : _g1(g1), _worker_num(worker_num), 1606 : _g1(g1), _worker_num(worker_num),
1618 _max_live_bytes(0), _regions_claimed(0), 1607 _max_live_bytes(0), _regions_claimed(0),
1619 _freed_bytes(0), _cleared_h_regions(0), _freed_regions(0), 1608 _freed_bytes(0),
1620 _claimed_region_time(0.0), _max_region_time(0.0), 1609 _claimed_region_time(0.0), _max_region_time(0.0),
1621 _unclean_region_list(list) 1610 _local_cleanup_list("Local Cleanup List"),
1622 {} 1611 _humongous_proxy_set("Local Cleanup Humongous Proxy Set") { }
1623 1612
1624 bool G1NoteEndOfConcMarkClosure::doHeapRegion(HeapRegion *r) { 1613 bool G1NoteEndOfConcMarkClosure::doHeapRegion(HeapRegion *hr) {
1625 // We use a claim value of zero here because all regions 1614 // We use a claim value of zero here because all regions
1626 // were claimed with value 1 in the FinalCount task. 1615 // were claimed with value 1 in the FinalCount task.
1627 r->reset_gc_time_stamp(); 1616 hr->reset_gc_time_stamp();
1628 if (!r->continuesHumongous()) { 1617 if (!hr->continuesHumongous()) {
1629 double start = os::elapsedTime(); 1618 double start = os::elapsedTime();
1630 _regions_claimed++; 1619 _regions_claimed++;
1631 r->note_end_of_marking(); 1620 hr->note_end_of_marking();
1632 _max_live_bytes += r->max_live_bytes(); 1621 _max_live_bytes += hr->max_live_bytes();
1633 _g1->free_region_if_totally_empty_work(r, 1622 _g1->free_region_if_totally_empty(hr,
1634 _freed_bytes, 1623 &_freed_bytes,
1635 _cleared_h_regions, 1624 &_local_cleanup_list,
1636 _freed_regions, 1625 &_humongous_proxy_set,
1637 _unclean_region_list, 1626 true /* par */);
1638 true /*par*/);
1639 double region_time = (os::elapsedTime() - start); 1627 double region_time = (os::elapsedTime() - start);
1640 _claimed_region_time += region_time; 1628 _claimed_region_time += region_time;
1641 if (region_time > _max_region_time) _max_region_time = region_time; 1629 if (region_time > _max_region_time) _max_region_time = region_time;
1642 } 1630 }
1643 return false; 1631 return false;
1652 // If a full collection has happened, we shouldn't do this. 1640 // If a full collection has happened, we shouldn't do this.
1653 if (has_aborted()) { 1641 if (has_aborted()) {
1654 g1h->set_marking_complete(); // So bitmap clearing isn't confused 1642 g1h->set_marking_complete(); // So bitmap clearing isn't confused
1655 return; 1643 return;
1656 } 1644 }
1645
1646 g1h->verify_region_sets_optional();
1657 1647
1658 if (VerifyDuringGC) { 1648 if (VerifyDuringGC) {
1659 HandleMark hm; // handle scope 1649 HandleMark hm; // handle scope
1660 gclog_or_tty->print(" VerifyDuringGC:(before)"); 1650 gclog_or_tty->print(" VerifyDuringGC:(before)");
1661 Universe::heap()->prepare_for_verify(); 1651 Universe::heap()->prepare_for_verify();
1717 1707
1718 g1h->reset_gc_time_stamp(); 1708 g1h->reset_gc_time_stamp();
1719 1709
1720 // Note end of marking in all heap regions. 1710 // Note end of marking in all heap regions.
1721 double note_end_start = os::elapsedTime(); 1711 double note_end_start = os::elapsedTime();
1722 G1ParNoteEndTask g1_par_note_end_task(g1h, _par_cleanup_thread_state); 1712 G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list);
1723 if (G1CollectedHeap::use_parallel_gc_threads()) { 1713 if (G1CollectedHeap::use_parallel_gc_threads()) {
1724 int n_workers = g1h->workers()->total_workers(); 1714 int n_workers = g1h->workers()->total_workers();
1725 g1h->set_par_threads(n_workers); 1715 g1h->set_par_threads(n_workers);
1726 g1h->workers()->run_task(&g1_par_note_end_task); 1716 g1h->workers()->run_task(&g1_par_note_end_task);
1727 g1h->set_par_threads(0); 1717 g1h->set_par_threads(0);
1729 assert(g1h->check_heap_region_claim_values(HeapRegion::NoteEndClaimValue), 1719 assert(g1h->check_heap_region_claim_values(HeapRegion::NoteEndClaimValue),
1730 "sanity check"); 1720 "sanity check");
1731 } else { 1721 } else {
1732 g1_par_note_end_task.work(0); 1722 g1_par_note_end_task.work(0);
1733 } 1723 }
1734 g1h->set_unclean_regions_coming(true); 1724
1725 if (!cleanup_list_is_empty()) {
1726 // The cleanup list is not empty, so we'll have to process it
1727 // concurrently. Notify anyone else that might be wanting free
1728 // regions that there will be more free regions coming soon.
1729 g1h->set_free_regions_coming();
1730 }
1735 double note_end_end = os::elapsedTime(); 1731 double note_end_end = os::elapsedTime();
1736 // Tell the mutators that there might be unclean regions coming...
1737 if (G1PrintParCleanupStats) { 1732 if (G1PrintParCleanupStats) {
1738 gclog_or_tty->print_cr(" note end of marking: %8.3f ms.", 1733 gclog_or_tty->print_cr(" note end of marking: %8.3f ms.",
1739 (note_end_end - note_end_start)*1000.0); 1734 (note_end_end - note_end_start)*1000.0);
1740 } 1735 }
1741 1736
1797 Universe::heap()->prepare_for_verify(); 1792 Universe::heap()->prepare_for_verify();
1798 Universe::verify(/* allow dirty */ true, 1793 Universe::verify(/* allow dirty */ true,
1799 /* silent */ false, 1794 /* silent */ false,
1800 /* prev marking */ true); 1795 /* prev marking */ true);
1801 } 1796 }
1797
1798 g1h->verify_region_sets_optional();
1802 } 1799 }
1803 1800
1804 void ConcurrentMark::completeCleanup() { 1801 void ConcurrentMark::completeCleanup() {
1805 // A full collection intervened.
1806 if (has_aborted()) return; 1802 if (has_aborted()) return;
1807 1803
1808 int first = 0; 1804 G1CollectedHeap* g1h = G1CollectedHeap::heap();
1809 int last = (int)MAX2(ParallelGCThreads, (size_t)1); 1805
1810 for (int t = 0; t < last; t++) { 1806 _cleanup_list.verify_optional();
1811 UncleanRegionList* list = &_par_cleanup_thread_state[t]->list; 1807 FreeRegionList local_free_list("Local Cleanup List");
1812 assert(list->well_formed(), "Inv"); 1808
1813 HeapRegion* hd = list->hd(); 1809 if (G1ConcRegionFreeingVerbose) {
1814 while (hd != NULL) { 1810 gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
1815 // Now finish up the other stuff. 1811 "cleanup list has "SIZE_FORMAT" entries",
1816 hd->rem_set()->clear(); 1812 _cleanup_list.length());
1817 HeapRegion* next_hd = hd->next_from_unclean_list(); 1813 }
1818 (void)list->pop(); 1814
1819 assert(list->hd() == next_hd, "how not?"); 1815 // Noone else should be accessing the _cleanup_list at this point,
1820 _g1h->put_region_on_unclean_list(hd); 1816 // so it's not necessary to take any locks
1821 if (!hd->isHumongous()) { 1817 while (!_cleanup_list.is_empty()) {
1822 // Add this to the _free_regions count by 1. 1818 HeapRegion* hr = _cleanup_list.remove_head();
1823 _g1h->finish_free_region_work(0, 0, 1, NULL); 1819 assert(hr != NULL, "the list was not empty");
1820 hr->rem_set()->clear();
1821 local_free_list.add_as_tail(hr);
1822
1823 // Instead of adding one region at a time to the secondary_free_list,
1824 // we accumulate them in the local list and move them a few at a
1825 // time. This also cuts down on the number of notify_all() calls
1826 // we do during this process. We'll also append the local list when
1827 // _cleanup_list is empty (which means we just removed the last
1828 // region from the _cleanup_list).
1829 if ((local_free_list.length() % G1SecondaryFreeListAppendLength == 0) ||
1830 _cleanup_list.is_empty()) {
1831 if (G1ConcRegionFreeingVerbose) {
1832 gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
1833 "appending "SIZE_FORMAT" entries to the "
1834 "secondary_free_list, clean list still has "
1835 SIZE_FORMAT" entries",
1836 local_free_list.length(),
1837 _cleanup_list.length());
1824 } 1838 }
1825 hd = list->hd(); 1839
1826 assert(hd == next_hd, "how not?"); 1840 {
1827 } 1841 MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
1828 } 1842 g1h->secondary_free_list_add_as_tail(&local_free_list);
1843 SecondaryFreeList_lock->notify_all();
1844 }
1845
1846 if (G1StressConcRegionFreeing) {
1847 for (uintx i = 0; i < G1StressConcRegionFreeingDelayMillis; ++i) {
1848 os::sleep(Thread::current(), (jlong) 1, false);
1849 }
1850 }
1851 }
1852 }
1853 assert(local_free_list.is_empty(), "post-condition");
1829 } 1854 }
1830 1855
1831 bool G1CMIsAliveClosure::do_object_b(oop obj) { 1856 bool G1CMIsAliveClosure::do_object_b(oop obj) {
1832 HeapWord* addr = (HeapWord*)obj; 1857 HeapWord* addr = (HeapWord*)obj;
1833 return addr != NULL && 1858 return addr != NULL &&
2895 public: 2920 public:
2896 virtual void do_oop(narrowOop* p) { do_oop_work(p); } 2921 virtual void do_oop(narrowOop* p) { do_oop_work(p); }
2897 virtual void do_oop( oop* p) { do_oop_work(p); } 2922 virtual void do_oop( oop* p) { do_oop_work(p); }
2898 2923
2899 template <class T> void do_oop_work(T* p) { 2924 template <class T> void do_oop_work(T* p) {
2900 assert(_g1h->is_in_g1_reserved((HeapWord*) p), "invariant"); 2925 assert( _g1h->is_in_g1_reserved((HeapWord*) p), "invariant");
2901 assert(!_g1h->heap_region_containing((HeapWord*) p)->is_on_free_list(), 2926 assert(!_g1h->is_on_free_list(
2902 "invariant"); 2927 _g1h->heap_region_containing((HeapWord*) p)), "invariant");
2903 2928
2904 oop obj = oopDesc::load_decode_heap_oop(p); 2929 oop obj = oopDesc::load_decode_heap_oop(p);
2905 if (_cm->verbose_high()) 2930 if (_cm->verbose_high())
2906 gclog_or_tty->print_cr("[%d] we're looking at location " 2931 gclog_or_tty->print_cr("[%d] we're looking at location "
2907 "*"PTR_FORMAT" = "PTR_FORMAT, 2932 "*"PTR_FORMAT" = "PTR_FORMAT,
3117 } 3142 }
3118 3143
3119 void CMTask::push(oop obj) { 3144 void CMTask::push(oop obj) {
3120 HeapWord* objAddr = (HeapWord*) obj; 3145 HeapWord* objAddr = (HeapWord*) obj;
3121 assert(_g1h->is_in_g1_reserved(objAddr), "invariant"); 3146 assert(_g1h->is_in_g1_reserved(objAddr), "invariant");
3122 assert(!_g1h->heap_region_containing(objAddr)->is_on_free_list(), 3147 assert(!_g1h->is_on_free_list(
3123 "invariant"); 3148 _g1h->heap_region_containing((HeapWord*) objAddr)), "invariant");
3124 assert(!_g1h->is_obj_ill(obj), "invariant"); 3149 assert(!_g1h->is_obj_ill(obj), "invariant");
3125 assert(_nextMarkBitMap->isMarked(objAddr), "invariant"); 3150 assert(_nextMarkBitMap->isMarked(objAddr), "invariant");
3126 3151
3127 if (_cm->verbose_high()) 3152 if (_cm->verbose_high())
3128 gclog_or_tty->print_cr("[%d] pushing "PTR_FORMAT, _task_id, (void*) obj); 3153 gclog_or_tty->print_cr("[%d] pushing "PTR_FORMAT, _task_id, (void*) obj);
3363 if (_cm->verbose_high()) 3388 if (_cm->verbose_high())
3364 gclog_or_tty->print_cr("[%d] popped "PTR_FORMAT, _task_id, 3389 gclog_or_tty->print_cr("[%d] popped "PTR_FORMAT, _task_id,
3365 (void*) obj); 3390 (void*) obj);
3366 3391
3367 assert(_g1h->is_in_g1_reserved((HeapWord*) obj), "invariant" ); 3392 assert(_g1h->is_in_g1_reserved((HeapWord*) obj), "invariant" );
3368 assert(!_g1h->heap_region_containing(obj)->is_on_free_list(), 3393 assert(!_g1h->is_on_free_list(
3369 "invariant"); 3394 _g1h->heap_region_containing((HeapWord*) obj)), "invariant");
3370 3395
3371 scan_object(obj); 3396 scan_object(obj);
3372 3397
3373 if (_task_queue->size() <= target_size || has_aborted()) 3398 if (_task_queue->size() <= target_size || has_aborted())
3374 ret = false; 3399 ret = false;