6841313: G1: dirty cards of survivor regions in parallel

Mon, 31 Aug 2009 05:27:29 -0700

author
apetrusenko
date
Mon, 31 Aug 2009 05:27:29 -0700
changeset 1375
8624da129f0b
parent 1374
9eebd3ac74cf
child 1376
8b46c4d82093

6841313: G1: dirty cards of survivor regions in parallel
Reviewed-by: tonyp, iveresov

src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1_globals.hpp file | annotate | diff | comparison | revisions
src/share/vm/memory/cardTableModRefBS.cpp file | annotate | diff | comparison | revisions
src/share/vm/memory/cardTableModRefBS.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Aug 13 16:22:45 2009 -0700
     1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon Aug 31 05:27:29 2009 -0700
     1.3 @@ -2739,8 +2739,6 @@
     1.4          _in_cset_fast_test = NULL;
     1.5          _in_cset_fast_test_base = NULL;
     1.6  
     1.7 -        release_gc_alloc_regions(false /* totally */);
     1.8 -
     1.9          cleanup_surviving_young_words();
    1.10  
    1.11          if (g1_policy()->in_young_gc_mode()) {
    1.12 @@ -4132,6 +4130,7 @@
    1.13      G1KeepAliveClosure keep_alive(this);
    1.14      JNIHandles::weak_oops_do(&is_alive, &keep_alive);
    1.15    }
    1.16 +  release_gc_alloc_regions(false /* totally */);
    1.17    g1_rem_set()->cleanup_after_oops_into_collection_set_do();
    1.18  
    1.19    concurrent_g1_refine()->clear_hot_cache();
    1.20 @@ -4265,12 +4264,18 @@
    1.21  class G1ParCleanupCTTask : public AbstractGangTask {
    1.22    CardTableModRefBS* _ct_bs;
    1.23    G1CollectedHeap* _g1h;
    1.24 +  HeapRegion* volatile _so_head;
    1.25 +  HeapRegion* volatile _su_head;
    1.26  public:
    1.27    G1ParCleanupCTTask(CardTableModRefBS* ct_bs,
    1.28 -                     G1CollectedHeap* g1h) :
    1.29 +                     G1CollectedHeap* g1h,
    1.30 +                     HeapRegion* scan_only_list,
    1.31 +                     HeapRegion* survivor_list) :
    1.32      AbstractGangTask("G1 Par Cleanup CT Task"),
    1.33      _ct_bs(ct_bs),
    1.34 -    _g1h(g1h)
    1.35 +    _g1h(g1h),
    1.36 +    _so_head(scan_only_list),
    1.37 +    _su_head(survivor_list)
    1.38    { }
    1.39  
    1.40    void work(int i) {
    1.41 @@ -4278,22 +4283,64 @@
    1.42      while (r = _g1h->pop_dirty_cards_region()) {
    1.43        clear_cards(r);
    1.44      }
    1.45 -  }
    1.46 +    // Redirty the cards of the scan-only and survivor regions.
    1.47 +    dirty_list(&this->_so_head);
    1.48 +    dirty_list(&this->_su_head);
    1.49 +  }
    1.50 +
    1.51    void clear_cards(HeapRegion* r) {
    1.52      // Cards for Survivor and Scan-Only regions will be dirtied later.
    1.53      if (!r->is_scan_only() && !r->is_survivor()) {
    1.54        _ct_bs->clear(MemRegion(r->bottom(), r->end()));
    1.55      }
    1.56    }
    1.57 +
    1.58 +  void dirty_list(HeapRegion* volatile * head_ptr) {
    1.59 +    HeapRegion* head;
    1.60 +    do {
    1.61 +      // Pop region off the list.
    1.62 +      head = *head_ptr;
    1.63 +      if (head != NULL) {
    1.64 +        HeapRegion* r = (HeapRegion*)
    1.65 +          Atomic::cmpxchg_ptr(head->get_next_young_region(), head_ptr, head);
    1.66 +        if (r == head) {
    1.67 +          assert(!r->isHumongous(), "Humongous regions shouldn't be on survivor list");
    1.68 +          _ct_bs->dirty(MemRegion(r->bottom(), r->end()));
    1.69 +        }
    1.70 +      }
    1.71 +    } while (*head_ptr != NULL);
    1.72 +  }
    1.73  };
    1.74  
    1.75  
    1.76 +#ifndef PRODUCT
    1.77 +class G1VerifyCardTableCleanup: public HeapRegionClosure {
    1.78 +  CardTableModRefBS* _ct_bs;
    1.79 +public:
    1.80 +  G1VerifyCardTableCleanup(CardTableModRefBS* ct_bs)
    1.81 +    : _ct_bs(ct_bs)
    1.82 +  { }
    1.83 +  virtual bool doHeapRegion(HeapRegion* r)
    1.84 +  {
    1.85 +    MemRegion mr(r->bottom(), r->end());
    1.86 +    if (r->is_scan_only() || r->is_survivor()) {
    1.87 +      _ct_bs->verify_dirty_region(mr);
    1.88 +    } else {
    1.89 +      _ct_bs->verify_clean_region(mr);
    1.90 +    }
    1.91 +    return false;
    1.92 +  }
    1.93 +};
    1.94 +#endif
    1.95 +
    1.96  void G1CollectedHeap::cleanUpCardTable() {
    1.97    CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set());
    1.98    double start = os::elapsedTime();
    1.99  
   1.100    // Iterate over the dirty cards region list.
   1.101 -  G1ParCleanupCTTask cleanup_task(ct_bs, this);
   1.102 +  G1ParCleanupCTTask cleanup_task(ct_bs, this,
   1.103 +                                  _young_list->first_scan_only_region(),
   1.104 +                                  _young_list->first_survivor_region());
   1.105    if (ParallelGCThreads > 0) {
   1.106      set_par_threads(workers()->total_workers());
   1.107      workers()->run_task(&cleanup_task);
   1.108 @@ -4309,18 +4356,22 @@
   1.109        }
   1.110        r->set_next_dirty_cards_region(NULL);
   1.111      }
   1.112 -  }
   1.113 -  // now, redirty the cards of the scan-only and survivor regions
   1.114 -  // (it seemed faster to do it this way, instead of iterating over
   1.115 -  // all regions and then clearing / dirtying as appropriate)
   1.116 -  dirtyCardsForYoungRegions(ct_bs, _young_list->first_scan_only_region());
   1.117 -  dirtyCardsForYoungRegions(ct_bs, _young_list->first_survivor_region());
   1.118 -
   1.119 +    // now, redirty the cards of the scan-only and survivor regions
   1.120 +    // (it seemed faster to do it this way, instead of iterating over
   1.121 +    // all regions and then clearing / dirtying as appropriate)
   1.122 +    dirtyCardsForYoungRegions(ct_bs, _young_list->first_scan_only_region());
   1.123 +    dirtyCardsForYoungRegions(ct_bs, _young_list->first_survivor_region());
   1.124 +  }
   1.125    double elapsed = os::elapsedTime() - start;
   1.126    g1_policy()->record_clear_ct_time( elapsed * 1000.0);
   1.127 +#ifndef PRODUCT
   1.128 +  if (G1VerifyCTCleanup || VerifyAfterGC) {
   1.129 +    G1VerifyCardTableCleanup cleanup_verifier(ct_bs);
   1.130 +    heap_region_iterate(&cleanup_verifier);
   1.131 +  }
   1.132 +#endif
   1.133  }
   1.134  
   1.135 -
   1.136  void G1CollectedHeap::do_collection_pause_if_appropriate(size_t word_size) {
   1.137    if (g1_policy()->should_do_collection_pause(word_size)) {
   1.138      do_collection_pause();
     2.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu Aug 13 16:22:45 2009 -0700
     2.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Mon Aug 31 05:27:29 2009 -0700
     2.3 @@ -260,6 +260,9 @@
     2.4                                                                              \
     2.5    develop(intx, G1CardCountCacheExpandThreshold, 16,                        \
     2.6            "Expand the card count cache if the number of collisions for "    \
     2.7 -          "a particular entry exceeds this value.")
     2.8 +          "a particular entry exceeds this value.")                         \
     2.9 +                                                                            \
    2.10 +  develop(bool, G1VerifyCTCleanup, false,                                   \
    2.11 +          "Verify card table cleanup.")
    2.12  
    2.13  G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
     3.1 --- a/src/share/vm/memory/cardTableModRefBS.cpp	Thu Aug 13 16:22:45 2009 -0700
     3.2 +++ b/src/share/vm/memory/cardTableModRefBS.cpp	Mon Aug 31 05:27:29 2009 -0700
     3.3 @@ -660,6 +660,29 @@
     3.4    GuaranteeNotModClosure blk(this);
     3.5    non_clean_card_iterate_work(mr, &blk, false);
     3.6  }
     3.7 +
     3.8 +// To verify a MemRegion is entirely dirty this closure is passed to
     3.9 +// dirty_card_iterate. If the region is dirty do_MemRegion will be
    3.10 +// invoked only once with a MemRegion equal to the one being
    3.11 +// verified.
    3.12 +class GuaranteeDirtyClosure: public MemRegionClosure {
    3.13 +  CardTableModRefBS* _ct;
    3.14 +  MemRegion _mr;
    3.15 +  bool _result;
    3.16 +public:
    3.17 +  GuaranteeDirtyClosure(CardTableModRefBS* ct, MemRegion mr)
    3.18 +    : _ct(ct), _mr(mr), _result(false) {}
    3.19 +  void do_MemRegion(MemRegion mr) {
    3.20 +    _result = _mr.equals(mr);
    3.21 +  }
    3.22 +  bool result() const { return _result; }
    3.23 +};
    3.24 +
    3.25 +void CardTableModRefBS::verify_dirty_region(MemRegion mr) {
    3.26 +  GuaranteeDirtyClosure blk(this, mr);
    3.27 +  dirty_card_iterate(mr, &blk);
    3.28 +  guarantee(blk.result(), "Non-dirty cards in region that should be dirty");
    3.29 +}
    3.30  #endif
    3.31  
    3.32  bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) {
     4.1 --- a/src/share/vm/memory/cardTableModRefBS.hpp	Thu Aug 13 16:22:45 2009 -0700
     4.2 +++ b/src/share/vm/memory/cardTableModRefBS.hpp	Mon Aug 31 05:27:29 2009 -0700
     4.3 @@ -456,6 +456,7 @@
     4.4    void verify_guard();
     4.5  
     4.6    void verify_clean_region(MemRegion mr) PRODUCT_RETURN;
     4.7 +  void verify_dirty_region(MemRegion mr) PRODUCT_RETURN;
     4.8  
     4.9    static size_t par_chunk_heapword_alignment() {
    4.10      return CardsPerStrideChunk * card_size_in_words;

mercurial