# HG changeset patch # User johnc # Date 1354054297 28800 # Node ID 2fc0334f613aef43d1b3e7101df43473dcd3fcc1 # Parent f34d701e952ea378167b2eac6f9ec9fddba0b539 7194633: G1: Assertion and guarantee failures in block offset table Summary: Add detailed error messages to assertions and guarantees in G1's block offset table. Reviewed-by: ysr, brutisso diff -r f34d701e952e -r 2fc0334f613a src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp --- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Tue Nov 27 14:20:21 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Tue Nov 27 14:11:37 2012 -0800 @@ -302,16 +302,28 @@ for (size_t c = start_card + 1; c <= end_card; c++ /* yeah! */) { u_char entry = _array->offset_array(c); if (c - start_card > BlockOffsetArray::power_to_cards_back(1)) { - guarantee(entry > N_words, "Should be in logarithmic region"); + guarantee(entry > N_words, + err_msg("Should be in logarithmic region - " + "entry: " UINT32_FORMAT ", " + "_array->offset_array(c): " UINT32_FORMAT ", " + "N_words: " UINT32_FORMAT, + entry, _array->offset_array(c), N_words)); } size_t backskip = BlockOffsetArray::entry_to_cards_back(entry); size_t landing_card = c - backskip; guarantee(landing_card >= (start_card - 1), "Inv"); if (landing_card >= start_card) { - guarantee(_array->offset_array(landing_card) <= entry, "monotonicity"); + guarantee(_array->offset_array(landing_card) <= entry, + err_msg("Monotonicity - landing_card offset: " UINT32_FORMAT ", " + "entry: " UINT32_FORMAT, + _array->offset_array(landing_card), entry)); } else { guarantee(landing_card == start_card - 1, "Tautology"); - guarantee(_array->offset_array(landing_card) <= N_words, "Offset value"); + // Note that N_words is the maximum offset value + guarantee(_array->offset_array(landing_card) <= N_words, + err_msg("landing card offset: " UINT32_FORMAT ", " + "N_words: " UINT32_FORMAT, + _array->offset_array(landing_card), N_words)); } } } @@ -536,17 +548,27 @@ // The offset can be 0 if the block starts on a boundary. That // is checked by an assertion above. size_t start_index = _array->index_for(blk_start); - HeapWord* boundary = _array->address_for_index(start_index); + HeapWord* boundary = _array->address_for_index(start_index); assert((_array->offset_array(orig_index) == 0 && blk_start == boundary) || (_array->offset_array(orig_index) > 0 && _array->offset_array(orig_index) <= N_words), - "offset array should have been set"); + err_msg("offset array should have been set - " + "orig_index offset: " UINT32_FORMAT ", " + "blk_start: " PTR_FORMAT ", " + "boundary: " PTR_FORMAT, + _array->offset_array(orig_index), + blk_start, boundary)); for (size_t j = orig_index + 1; j <= end_index; j++) { assert(_array->offset_array(j) > 0 && _array->offset_array(j) <= (u_char) (N_words+BlockOffsetArray::N_powers-1), - "offset array should have been set"); + err_msg("offset array should have been set - " + UINT32_FORMAT " not > 0 OR " + UINT32_FORMAT " not <= " UINT32_FORMAT, + _array->offset_array(j), + _array->offset_array(j), + (u_char) (N_words+BlockOffsetArray::N_powers-1))); } #endif } diff -r f34d701e952e -r 2fc0334f613a src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp --- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Tue Nov 27 14:20:21 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Tue Nov 27 14:11:37 2012 -0800 @@ -78,7 +78,9 @@ virtual void resize(size_t new_word_size) = 0; virtual void set_bottom(HeapWord* new_bottom) { - assert(new_bottom <= _end, "new_bottom > _end"); + assert(new_bottom <= _end, + err_msg("new_bottom (" PTR_FORMAT ") > _end (" PTR_FORMAT ")", + new_bottom, _end)); _bottom = new_bottom; resize(pointer_delta(_end, _bottom)); } @@ -134,29 +136,42 @@ VirtualSpace _vs; u_char* _offset_array; // byte array keeping backwards offsets + void check_index(size_t index, const char* msg) const { + assert(index < _vs.committed_size(), + err_msg("%s - " + "index: " SIZE_FORMAT ", _vs.committed_size: " SIZE_FORMAT, + msg, index, _vs.committed_size())); + } + + void check_offset(size_t offset, const char* msg) const { + assert(offset <= N_words, + err_msg("%s - " + "offset: " UINT32_FORMAT", N_words: " UINT32_FORMAT, + msg, offset, N_words)); + } + // Bounds checking accessors: // For performance these have to devolve to array accesses in product builds. u_char offset_array(size_t index) const { - assert(index < _vs.committed_size(), "index out of range"); + check_index(index, "index out of range"); return _offset_array[index]; } void set_offset_array(size_t index, u_char offset) { - assert(index < _vs.committed_size(), "index out of range"); - assert(offset <= N_words, "offset too large"); + check_index(index, "index out of range"); + check_offset(offset, "offset too large"); _offset_array[index] = offset; } void set_offset_array(size_t index, HeapWord* high, HeapWord* low) { - assert(index < _vs.committed_size(), "index out of range"); + check_index(index, "index out of range"); assert(high >= low, "addresses out of order"); - assert(pointer_delta(high, low) <= N_words, "offset too large"); + check_offset(pointer_delta(high, low), "offset too large"); _offset_array[index] = (u_char) pointer_delta(high, low); } void set_offset_array(HeapWord* left, HeapWord* right, u_char offset) { - assert(index_for(right - 1) < _vs.committed_size(), - "right address out of range"); + check_index(index_for(right - 1), "right address out of range"); assert(left < right, "Heap addresses out of order"); size_t num_cards = pointer_delta(right, left) >> LogN_words; if (UseMemSetInBOT) { @@ -171,7 +186,7 @@ } void set_offset_array(size_t left, size_t right, u_char offset) { - assert(right < _vs.committed_size(), "right address out of range"); + check_index(right, "right index out of range"); assert(left <= right, "indexes out of order"); size_t num_cards = right - left + 1; if (UseMemSetInBOT) { @@ -186,11 +201,10 @@ } void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const { - assert(index < _vs.committed_size(), "index out of range"); + check_index(index, "index out of range"); assert(high >= low, "addresses out of order"); - assert(pointer_delta(high, low) <= N_words, "offset too large"); - assert(_offset_array[index] == pointer_delta(high, low), - "Wrong offset"); + check_offset(pointer_delta(high, low), "offset too large"); + assert(_offset_array[index] == pointer_delta(high, low), "Wrong offset"); } bool is_card_boundary(HeapWord* p) const; @@ -481,7 +495,6 @@ blk_start, blk_end); } - public: G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array, MemRegion mr); diff -r f34d701e952e -r 2fc0334f613a src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp --- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp Tue Nov 27 14:20:21 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp Tue Nov 27 14:11:37 2012 -0800 @@ -49,16 +49,17 @@ char* pc = (char*)p; assert(pc >= (char*)_reserved.start() && pc < (char*)_reserved.end(), - "p not in range."); + err_msg("p (" PTR_FORMAT ") not in reserved [" PTR_FORMAT ", " PTR_FORMAT ")", + p, (char*)_reserved.start(), (char*)_reserved.end())); size_t delta = pointer_delta(pc, _reserved.start(), sizeof(char)); size_t result = delta >> LogN; - assert(result < _vs.committed_size(), "bad index from address"); + check_index(result, "bad index from address"); return result; } inline HeapWord* G1BlockOffsetSharedArray::address_for_index(size_t index) const { - assert(index < _vs.committed_size(), "bad index"); + check_index(index, "index out of range"); HeapWord* result = _reserved.start() + (index << LogN_words); assert(result >= _reserved.start() && result < _reserved.end(), err_msg("bad address from index result " PTR_FORMAT diff -r f34d701e952e -r 2fc0334f613a src/share/vm/memory/space.cpp --- a/src/share/vm/memory/space.cpp Tue Nov 27 14:20:21 2012 +0100 +++ b/src/share/vm/memory/space.cpp Tue Nov 27 14:11:37 2012 -0800 @@ -790,7 +790,9 @@ // Very general, slow implementation. HeapWord* ContiguousSpace::block_start_const(const void* p) const { - assert(MemRegion(bottom(), end()).contains(p), "p not in space"); + assert(MemRegion(bottom(), end()).contains(p), + err_msg("p (" PTR_FORMAT ") not in space [" PTR_FORMAT ", " PTR_FORMAT ")", + p, bottom(), end())); if (p >= top()) { return top(); } else { @@ -800,19 +802,27 @@ last = cur; cur += oop(cur)->size(); } - assert(oop(last)->is_oop(), "Should be an object start"); + assert(oop(last)->is_oop(), + err_msg(PTR_FORMAT " should be an object start", last)); return last; } } size_t ContiguousSpace::block_size(const HeapWord* p) const { - assert(MemRegion(bottom(), end()).contains(p), "p not in space"); + assert(MemRegion(bottom(), end()).contains(p), + err_msg("p (" PTR_FORMAT ") not in space [" PTR_FORMAT ", " PTR_FORMAT ")", + p, bottom(), end())); HeapWord* current_top = top(); - assert(p <= current_top, "p is not a block start"); - assert(p == current_top || oop(p)->is_oop(), "p is not a block start"); - if (p < current_top) + assert(p <= current_top, + err_msg("p > current top - p: " PTR_FORMAT ", current top: " PTR_FORMAT, + p, current_top)); + assert(p == current_top || oop(p)->is_oop(), + err_msg("p (" PTR_FORMAT ") is not a block start - " + "current_top: " PTR_FORMAT ", is_oop: %s", + p, current_top, BOOL_TO_STR(oop(p)->is_oop()))); + if (p < current_top) { return oop(p)->size(); - else { + } else { assert(p == current_top, "just checking"); return pointer_delta(end(), (HeapWord*) p); }