src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp

Print this page
rev 3635 : 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:

*** 26,35 **** --- 26,69 ---- #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_INLINE_HPP #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" + // Utility routine to set an inclusive range of cards on the given + // card liveness bitmap + inline void ConcurrentMark::set_card_bitmap_range(BitMap* card_bm, + BitMap::idx_t start_idx, + BitMap::idx_t last_idx, + bool is_par) { + // Set the inclusive bit range [start_idx, last_idx]. + + assert(start_idx <= last_idx, "sanity"); + assert(last_idx < card_bm->size(), "sanity"); + BitMap::idx_t end_idx = MIN2(last_idx+1, card_bm->size()); + + // For small ranges use a simple loop; otherwise use set_range or + // use par_at_put_range (if parallel). The range is made up of the + // cards that are spanned by an object/mem region so 8 cards will + // allow up to object sizes up to 4K to be handled using the loop. + if ((end_idx - start_idx) <= 8) { + for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { + if (is_par) { + card_bm->par_set_bit(i); + } else { + card_bm->set_bit(i); + } + } + } else { + // Note BitMap::par_at_put_range() and BitMap::set_range() are exclusive. + if (is_par) { + card_bm->par_at_put_range(start_idx, end_idx, true); + } else { + card_bm->set_range(start_idx, end_idx); + } + } + } + // Returns the index in the liveness accounting card bitmap // for the given address inline BitMap::idx_t ConcurrentMark::card_bitmap_index_for(HeapWord* addr) { // Below, the term "card num" means the result of shifting an address // by the card shift -- address 0 corresponds to card number 0. One
*** 61,86 **** marked_bytes_array[index] += region_size_bytes; BitMap::idx_t start_idx = card_bitmap_index_for(start); BitMap::idx_t last_idx = card_bitmap_index_for(last); ! // The card bitmap is task/worker specific => no need to use 'par' routines. // Set bits in the inclusive bit range [start_idx, last_idx]. ! // ! // For small ranges use a simple loop; otherwise use set_range ! // The range are the cards that are spanned by the object/region ! // so 8 cards will allow objects/regions up to 4K to be handled ! // using the loop. ! if ((last_idx - start_idx) <= 8) { ! for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) { ! task_card_bm->set_bit(i); ! } ! } else { ! assert(last_idx < task_card_bm->size(), "sanity"); ! // Note: BitMap::set_range() is exclusive. ! task_card_bm->set_range(start_idx, last_idx+1); ! } } // Counts the given memory region in the task/worker counting // data structures for the given worker id. inline void ConcurrentMark::count_region(MemRegion mr, --- 95,108 ---- marked_bytes_array[index] += region_size_bytes; BitMap::idx_t start_idx = card_bitmap_index_for(start); BitMap::idx_t last_idx = card_bitmap_index_for(last); ! // The card bitmap is task/worker specific => no need to use ! // the 'par' BitMap routines. // Set bits in the inclusive bit range [start_idx, last_idx]. ! set_card_bitmap_range(task_card_bm, start_idx, last_idx, false /* is_par */); } // Counts the given memory region in the task/worker counting // data structures for the given worker id. inline void ConcurrentMark::count_region(MemRegion mr,