Print this page
rev 3640 : 7200261: G1: Liveness counting inconsistencies during marking verification
Summary: The clipping code in the routine that sets the bits for a range of cards, in the liveness accounting verification code was incorrect. It set all the bits in the card bitmap from the given starting index which would lead to spurious marking verification failures.
Reviewed-by:
* * *
[mq]: code-review-comments

Split Close
Expand all
Collapse all
          --- old/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp
          +++ new/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp
↓ open down ↓ 20 lines elided ↑ open up ↑
  21   21   * questions.
  22   22   *
  23   23   */
  24   24  
  25   25  #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_INLINE_HPP
  26   26  #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_INLINE_HPP
  27   27  
  28   28  #include "gc_implementation/g1/concurrentMark.hpp"
  29   29  #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
  30   30  
       31 +// Utility routine to set an exclusive range of cards on the given
       32 +// card liveness bitmap
       33 +inline void ConcurrentMark::set_card_bitmap_range(BitMap* card_bm,
       34 +                                                  BitMap::idx_t start_idx,
       35 +                                                  BitMap::idx_t end_idx,
       36 +                                                  bool is_par) {
       37 +
       38 +  // Set the exclusive bit range [start_idx, end_idx).
       39 +  assert((end_idx - start_idx) > 0, "at least one card");
       40 +  assert(end_idx <= card_bm->size(), "sanity");
       41 +
       42 +  // Silently clip the end index
       43 +  end_idx = MIN2(end_idx, card_bm->size());
       44 +
       45 +  // For small ranges use a simple loop; otherwise use set_range or
       46 +  // use par_at_put_range (if parallel). The range is made up of the
       47 +  // cards that are spanned by an object/mem region so 8 cards will
       48 +  // allow up to object sizes up to 4K to be handled using the loop.
       49 +  if ((end_idx - start_idx) <= 8) {
       50 +    for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) {
       51 +      if (is_par) {
       52 +        card_bm->par_set_bit(i);
       53 +      } else {
       54 +        card_bm->set_bit(i);
       55 +      }
       56 +    }
       57 +  } else {
       58 +    // Note BitMap::par_at_put_range() and BitMap::set_range() are exclusive.
       59 +    if (is_par) {
       60 +      card_bm->par_at_put_range(start_idx, end_idx, true);
       61 +    } else {
       62 +      card_bm->set_range(start_idx, end_idx);
       63 +    }
       64 +  }
       65 +}
       66 +
  31   67  // Returns the index in the liveness accounting card bitmap
  32   68  // for the given address
  33   69  inline BitMap::idx_t ConcurrentMark::card_bitmap_index_for(HeapWord* addr) {
  34   70    // Below, the term "card num" means the result of shifting an address
  35   71    // by the card shift -- address 0 corresponds to card number 0.  One
  36   72    // must subtract the card num of the bottom of the heap to obtain a
  37   73    // card table index.
  38      -
  39   74    intptr_t card_num = intptr_t(uintptr_t(addr) >> CardTableModRefBS::card_shift);
  40   75    return card_num - heap_bottom_card_num();
  41   76  }
  42   77  
  43   78  // Counts the given memory region in the given task/worker
  44   79  // counting data structures.
  45   80  inline void ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr,
  46   81                                           size_t* marked_bytes_array,
  47   82                                           BitMap* task_card_bm) {
  48   83    G1CollectedHeap* g1h = _g1h;
       84 +  CardTableModRefBS* ct_bs = (CardTableModRefBS*) (g1h->barrier_set());
       85 +
  49   86    HeapWord* start = mr.start();
  50      -  HeapWord* last = mr.last();
       87 +  HeapWord* end = mr.end();
  51   88    size_t region_size_bytes = mr.byte_size();
  52   89    uint index = hr->hrs_index();
  53   90  
  54   91    assert(!hr->continuesHumongous(), "should not be HC region");
  55   92    assert(hr == g1h->heap_region_containing(start), "sanity");
  56   93    assert(hr == g1h->heap_region_containing(mr.last()), "sanity");
  57   94    assert(marked_bytes_array != NULL, "pre-condition");
  58   95    assert(task_card_bm != NULL, "pre-condition");
  59   96  
  60   97    // Add to the task local marked bytes for this region.
  61   98    marked_bytes_array[index] += region_size_bytes;
  62   99  
  63  100    BitMap::idx_t start_idx = card_bitmap_index_for(start);
  64      -  BitMap::idx_t last_idx = card_bitmap_index_for(last);
      101 +  BitMap::idx_t end_idx = card_bitmap_index_for(end);
  65  102  
  66      -  // The card bitmap is task/worker specific => no need to use 'par' routines.
  67      -  // Set bits in the inclusive bit range [start_idx, last_idx].
  68      -  //
  69      -  // For small ranges use a simple loop; otherwise use set_range
  70      -  // The range are the cards that are spanned by the object/region
  71      -  // so 8 cards will allow objects/regions up to 4K to be handled
  72      -  // using the loop.
  73      -  if ((last_idx - start_idx) <= 8) {
  74      -    for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) {
  75      -     task_card_bm->set_bit(i);
  76      -    }
  77      -  } else {
  78      -    assert(last_idx < task_card_bm->size(), "sanity");
  79      -    // Note: BitMap::set_range() is exclusive.
  80      -    task_card_bm->set_range(start_idx, last_idx+1);
  81      -  }
      103 +  // Note: if we're looking at a region that coincides with the end
      104 +  // of the heap - end could actually be outside the heap and end_idx
      105 +  // correspond to a card that is also outside the heap.
      106 +  if (g1h->is_in_g1_reserved(end) && !ct_bs->is_card_aligned(end)) {
      107 +    // end of region is not card aligned - incremement to cover
      108 +    // all the cards spanned by the region.
      109 +    end_idx += 1;
      110 +  }
      111 +  // The card bitmap is task/worker specific => no need to use
      112 +  // the 'par' BitMap routines.
      113 +  // Set bits in the exclusive bit range [start_idx, end_idx).
      114 +  set_card_bitmap_range(task_card_bm, start_idx, end_idx, false /* is_par */);
  82  115  }
  83  116  
  84  117  // Counts the given memory region in the task/worker counting
  85  118  // data structures for the given worker id.
  86  119  inline void ConcurrentMark::count_region(MemRegion mr,
  87  120                                           HeapRegion* hr,
  88  121                                           uint worker_id) {
  89  122    size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id);
  90  123    BitMap* task_card_bm = count_card_bitmap_for(worker_id);
  91  124    count_region(mr, hr, marked_bytes_array, task_card_bm);
↓ open down ↓ 311 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX