Mercurial > hg > truffle
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; |