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