comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @ 1709:5f429ee79634

6966222: G1: simplify TaskQueue overflow handling Reviewed-by: tonyp, ysr
author jcoomes
date Mon, 09 Aug 2010 05:41:05 -0700
parents 2d160770d2e5
children bb847e31b836
comparison
equal deleted inserted replaced
1708:a03ae377b2e8 1709:5f429ee79634
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
1596 1589
1597 int _hash_seed; 1590 int _hash_seed;
1598 int _queue_num; 1591 int _queue_num;
1599 1592
1600 size_t _term_attempts; 1593 size_t _term_attempts;
1601 #if G1_DETAILED_STATS
1602 int _pushes, _pops, _steals, _steal_attempts;
1603 int _overflow_pushes;
1604 #endif
1605 1594
1606 double _start; 1595 double _start;
1607 double _start_strong_roots; 1596 double _start_strong_roots;
1608 double _strong_roots_time; 1597 double _strong_roots_time;
1609 double _start_term; 1598 double _start_term;
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;