44 class ConcurrentMark; |
44 class ConcurrentMark; |
45 class ConcurrentMarkThread; |
45 class ConcurrentMarkThread; |
46 class ConcurrentG1Refine; |
46 class ConcurrentG1Refine; |
47 class ConcurrentZFThread; |
47 class ConcurrentZFThread; |
48 |
48 |
49 // If want to accumulate detailed statistics on work queues |
49 typedef OverflowTaskQueue<StarTask> RefToScanQueue; |
50 // turn this on. |
|
51 #define G1_DETAILED_STATS 0 |
|
52 |
|
53 #if G1_DETAILED_STATS |
|
54 # define IF_G1_DETAILED_STATS(code) code |
|
55 #else |
|
56 # define IF_G1_DETAILED_STATS(code) |
|
57 #endif |
|
58 |
|
59 typedef GenericTaskQueue<StarTask> RefToScanQueue; |
|
60 typedef GenericTaskQueueSet<RefToScanQueue> RefToScanQueueSet; |
50 typedef GenericTaskQueueSet<RefToScanQueue> RefToScanQueueSet; |
61 |
51 |
62 typedef int RegionIdx_t; // needs to hold [ 0..max_regions() ) |
52 typedef int RegionIdx_t; // needs to hold [ 0..max_regions() ) |
63 typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion ) |
53 typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion ) |
64 |
54 |
469 // Shrink the garbage-first heap by at most the given size (in bytes!). |
459 // Shrink the garbage-first heap by at most the given size (in bytes!). |
470 // (Rounds down to a HeapRegion boundary.) |
460 // (Rounds down to a HeapRegion boundary.) |
471 virtual void shrink(size_t expand_bytes); |
461 virtual void shrink(size_t expand_bytes); |
472 void shrink_helper(size_t expand_bytes); |
462 void shrink_helper(size_t expand_bytes); |
473 |
463 |
|
464 #if TASKQUEUE_STATS |
|
465 static void print_taskqueue_stats_hdr(outputStream* const st = gclog_or_tty); |
|
466 void print_taskqueue_stats(outputStream* const st = gclog_or_tty) const; |
|
467 void reset_taskqueue_stats(); |
|
468 #endif // TASKQUEUE_STATS |
|
469 |
474 // Do an incremental collection: identify a collection set, and evacuate |
470 // Do an incremental collection: identify a collection set, and evacuate |
475 // its live objects elsewhere. |
471 // its live objects elsewhere. |
476 virtual void do_collection_pause(); |
472 virtual void do_collection_pause(); |
477 |
473 |
478 // The guts of the incremental collection pause, executed by the vm |
474 // The guts of the incremental collection pause, executed by the vm |
660 bool _unclean_regions_coming; |
656 bool _unclean_regions_coming; |
661 |
657 |
662 public: |
658 public: |
663 void set_refine_cte_cl_concurrency(bool concurrent); |
659 void set_refine_cte_cl_concurrency(bool concurrent); |
664 |
660 |
665 RefToScanQueue *task_queue(int i); |
661 RefToScanQueue *task_queue(int i) const; |
666 |
662 |
667 // A set of cards where updates happened during the GC |
663 // A set of cards where updates happened during the GC |
668 DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; } |
664 DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; } |
669 |
665 |
670 // A DirtyCardQueueSet that is used to hold cards that contain |
666 // A DirtyCardQueueSet that is used to hold cards that contain |
1577 RefToScanQueue* _refs; |
1573 RefToScanQueue* _refs; |
1578 DirtyCardQueue _dcq; |
1574 DirtyCardQueue _dcq; |
1579 CardTableModRefBS* _ct_bs; |
1575 CardTableModRefBS* _ct_bs; |
1580 G1RemSet* _g1_rem; |
1576 G1RemSet* _g1_rem; |
1581 |
1577 |
1582 typedef GrowableArray<StarTask> OverflowQueue; |
|
1583 OverflowQueue* _overflowed_refs; |
|
1584 |
|
1585 G1ParGCAllocBuffer _surviving_alloc_buffer; |
1578 G1ParGCAllocBuffer _surviving_alloc_buffer; |
1586 G1ParGCAllocBuffer _tenured_alloc_buffer; |
1579 G1ParGCAllocBuffer _tenured_alloc_buffer; |
1587 G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount]; |
1580 G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount]; |
1588 ageTable _age_table; |
1581 ageTable _age_table; |
1589 |
1582 |
1613 // surviving words. base is what we get back from the malloc call |
1602 // surviving words. base is what we get back from the malloc call |
1614 size_t* _surviving_young_words_base; |
1603 size_t* _surviving_young_words_base; |
1615 // this points into the array, as we use the first few entries for padding |
1604 // this points into the array, as we use the first few entries for padding |
1616 size_t* _surviving_young_words; |
1605 size_t* _surviving_young_words; |
1617 |
1606 |
1618 #define PADDING_ELEM_NUM (64 / sizeof(size_t)) |
1607 #define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t)) |
1619 |
1608 |
1620 void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; } |
1609 void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; } |
1621 |
1610 |
1622 void add_to_undo_waste(size_t waste) { _undo_waste += waste; } |
1611 void add_to_undo_waste(size_t waste) { _undo_waste += waste; } |
1623 |
1612 |
1648 ~G1ParScanThreadState() { |
1637 ~G1ParScanThreadState() { |
1649 FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base); |
1638 FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base); |
1650 } |
1639 } |
1651 |
1640 |
1652 RefToScanQueue* refs() { return _refs; } |
1641 RefToScanQueue* refs() { return _refs; } |
1653 OverflowQueue* overflowed_refs() { return _overflowed_refs; } |
|
1654 ageTable* age_table() { return &_age_table; } |
1642 ageTable* age_table() { return &_age_table; } |
1655 |
1643 |
1656 G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { |
1644 G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { |
1657 return _alloc_buffers[purpose]; |
1645 return _alloc_buffers[purpose]; |
1658 } |
1646 } |
1659 |
1647 |
1660 size_t alloc_buffer_waste() { return _alloc_buffer_waste; } |
1648 size_t alloc_buffer_waste() const { return _alloc_buffer_waste; } |
1661 size_t undo_waste() { return _undo_waste; } |
1649 size_t undo_waste() const { return _undo_waste; } |
1662 |
1650 |
1663 template <class T> void push_on_queue(T* ref) { |
1651 template <class T> void push_on_queue(T* ref) { |
1664 assert(ref != NULL, "invariant"); |
1652 assert(ref != NULL, "invariant"); |
1665 assert(has_partial_array_mask(ref) || |
1653 assert(has_partial_array_mask(ref) || |
1666 _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(ref)), "invariant"); |
1654 _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(ref)), "invariant"); |
1669 oop p = clear_partial_array_mask(ref); |
1657 oop p = clear_partial_array_mask(ref); |
1670 // Verify that we point into the CS |
1658 // Verify that we point into the CS |
1671 assert(_g1h->obj_in_cs(p), "Should be in CS"); |
1659 assert(_g1h->obj_in_cs(p), "Should be in CS"); |
1672 } |
1660 } |
1673 #endif |
1661 #endif |
1674 if (!refs()->push(ref)) { |
1662 refs()->push(ref); |
1675 overflowed_refs()->push(ref); |
|
1676 IF_G1_DETAILED_STATS(note_overflow_push()); |
|
1677 } else { |
|
1678 IF_G1_DETAILED_STATS(note_push()); |
|
1679 } |
|
1680 } |
1663 } |
1681 |
1664 |
1682 void pop_from_queue(StarTask& ref) { |
1665 void pop_from_queue(StarTask& ref) { |
1683 if (refs()->pop_local(ref)) { |
1666 if (refs()->pop_local(ref)) { |
1684 assert((oop*)ref != NULL, "pop_local() returned true"); |
1667 assert((oop*)ref != NULL, "pop_local() returned true"); |
1685 assert(UseCompressedOops || !ref.is_narrow(), "Error"); |
1668 assert(UseCompressedOops || !ref.is_narrow(), "Error"); |
1686 assert(has_partial_array_mask((oop*)ref) || |
1669 assert(has_partial_array_mask((oop*)ref) || |
1687 _g1h->is_in_g1_reserved(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref) |
1670 _g1h->is_in_g1_reserved(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref) |
1688 : oopDesc::load_decode_heap_oop((oop*)ref)), |
1671 : oopDesc::load_decode_heap_oop((oop*)ref)), |
1689 "invariant"); |
1672 "invariant"); |
1690 IF_G1_DETAILED_STATS(note_pop()); |
|
1691 } else { |
1673 } else { |
1692 StarTask null_task; |
1674 StarTask null_task; |
1693 ref = null_task; |
1675 ref = null_task; |
1694 } |
1676 } |
1695 } |
1677 } |
1696 |
1678 |
1697 void pop_from_overflow_queue(StarTask& ref) { |
1679 void pop_from_overflow_queue(StarTask& ref) { |
1698 StarTask new_ref = overflowed_refs()->pop(); |
1680 StarTask new_ref; |
|
1681 refs()->pop_overflow(new_ref); |
1699 assert((oop*)new_ref != NULL, "pop() from a local non-empty stack"); |
1682 assert((oop*)new_ref != NULL, "pop() from a local non-empty stack"); |
1700 assert(UseCompressedOops || !new_ref.is_narrow(), "Error"); |
1683 assert(UseCompressedOops || !new_ref.is_narrow(), "Error"); |
1701 assert(has_partial_array_mask((oop*)new_ref) || |
1684 assert(has_partial_array_mask((oop*)new_ref) || |
1702 _g1h->is_in_g1_reserved(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref) |
1685 _g1h->is_in_g1_reserved(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref) |
1703 : oopDesc::load_decode_heap_oop((oop*)new_ref)), |
1686 : oopDesc::load_decode_heap_oop((oop*)new_ref)), |
1704 "invariant"); |
1687 "invariant"); |
1705 ref = new_ref; |
1688 ref = new_ref; |
1706 } |
1689 } |
1707 |
1690 |
1708 int refs_to_scan() { return refs()->size(); } |
1691 int refs_to_scan() { return refs()->size(); } |
1709 int overflowed_refs_to_scan() { return overflowed_refs()->length(); } |
1692 int overflowed_refs_to_scan() { return refs()->overflow_stack()->length(); } |
1710 |
1693 |
1711 template <class T> void update_rs(HeapRegion* from, T* p, int tid) { |
1694 template <class T> void update_rs(HeapRegion* from, T* p, int tid) { |
1712 if (G1DeferredRSUpdate) { |
1695 if (G1DeferredRSUpdate) { |
1713 deferred_rs_update(from, p, tid); |
1696 deferred_rs_update(from, p, tid); |
1714 } else { |
1697 } else { |
1773 } |
1756 } |
1774 |
1757 |
1775 int* hash_seed() { return &_hash_seed; } |
1758 int* hash_seed() { return &_hash_seed; } |
1776 int queue_num() { return _queue_num; } |
1759 int queue_num() { return _queue_num; } |
1777 |
1760 |
1778 size_t term_attempts() { return _term_attempts; } |
1761 size_t term_attempts() const { return _term_attempts; } |
1779 void note_term_attempt() { _term_attempts++; } |
1762 void note_term_attempt() { _term_attempts++; } |
1780 |
|
1781 #if G1_DETAILED_STATS |
|
1782 int pushes() { return _pushes; } |
|
1783 int pops() { return _pops; } |
|
1784 int steals() { return _steals; } |
|
1785 int steal_attempts() { return _steal_attempts; } |
|
1786 int overflow_pushes() { return _overflow_pushes; } |
|
1787 |
|
1788 void note_push() { _pushes++; } |
|
1789 void note_pop() { _pops++; } |
|
1790 void note_steal() { _steals++; } |
|
1791 void note_steal_attempt() { _steal_attempts++; } |
|
1792 void note_overflow_push() { _overflow_pushes++; } |
|
1793 #endif |
|
1794 |
1763 |
1795 void start_strong_roots() { |
1764 void start_strong_roots() { |
1796 _start_strong_roots = os::elapsedTime(); |
1765 _start_strong_roots = os::elapsedTime(); |
1797 } |
1766 } |
1798 void end_strong_roots() { |
1767 void end_strong_roots() { |
1799 _strong_roots_time += (os::elapsedTime() - _start_strong_roots); |
1768 _strong_roots_time += (os::elapsedTime() - _start_strong_roots); |
1800 } |
1769 } |
1801 double strong_roots_time() { return _strong_roots_time; } |
1770 double strong_roots_time() const { return _strong_roots_time; } |
1802 |
1771 |
1803 void start_term_time() { |
1772 void start_term_time() { |
1804 note_term_attempt(); |
1773 note_term_attempt(); |
1805 _start_term = os::elapsedTime(); |
1774 _start_term = os::elapsedTime(); |
1806 } |
1775 } |
1807 void end_term_time() { |
1776 void end_term_time() { |
1808 _term_time += (os::elapsedTime() - _start_term); |
1777 _term_time += (os::elapsedTime() - _start_term); |
1809 } |
1778 } |
1810 double term_time() { return _term_time; } |
1779 double term_time() const { return _term_time; } |
1811 |
1780 |
1812 double elapsed() { |
1781 double elapsed_time() const { |
1813 return os::elapsedTime() - _start; |
1782 return os::elapsedTime() - _start; |
1814 } |
1783 } |
|
1784 |
|
1785 static void |
|
1786 print_termination_stats_hdr(outputStream* const st = gclog_or_tty); |
|
1787 void |
|
1788 print_termination_stats(int i, outputStream* const st = gclog_or_tty) const; |
1815 |
1789 |
1816 size_t* surviving_young_words() { |
1790 size_t* surviving_young_words() { |
1817 // We add on to hide entry 0 which accumulates surviving words for |
1791 // We add on to hide entry 0 which accumulates surviving words for |
1818 // age -1 regions (i.e. non-young ones) |
1792 // age -1 regions (i.e. non-young ones) |
1819 return _surviving_young_words; |
1793 return _surviving_young_words; |