7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
Summary: When verifying clean card ranges, use memory-range-bounded iteration over oops of objects overlapping that range, thus avoiding the otherwise quadratic worst-case cost of scanning large object arrays.
Reviewed-by: jmasa, jwilhelm, tonyp
--- a/hotspot/src/share/vm/memory/cardTableRS.cpp Thu Mar 24 15:45:27 2011 -0700
+++ b/hotspot/src/share/vm/memory/cardTableRS.cpp Thu Mar 24 15:47:01 2011 -0700
@@ -318,17 +318,28 @@
protected:
template <class T> void do_oop_work(T* p) {
HeapWord* jp = (HeapWord*)p;
- if (jp >= _begin && jp < _end) {
- oop obj = oopDesc::load_decode_heap_oop(p);
- guarantee(obj == NULL ||
- (HeapWord*)p < _boundary ||
- (HeapWord*)obj >= _boundary,
- "pointer on clean card crosses boundary");
- }
+ assert(jp >= _begin && jp < _end,
+ err_msg("Error: jp " PTR_FORMAT " should be within "
+ "[_begin, _end) = [" PTR_FORMAT "," PTR_FORMAT ")",
+ _begin, _end));
+ oop obj = oopDesc::load_decode_heap_oop(p);
+ guarantee(obj == NULL || (HeapWord*)obj >= _boundary,
+ err_msg("pointer " PTR_FORMAT " at " PTR_FORMAT " on "
+ "clean card crosses boundary" PTR_FORMAT,
+ (HeapWord*)obj, jp, _boundary));
}
+
public:
VerifyCleanCardClosure(HeapWord* b, HeapWord* begin, HeapWord* end) :
- _boundary(b), _begin(begin), _end(end) {}
+ _boundary(b), _begin(begin), _end(end) {
+ assert(b <= begin,
+ err_msg("Error: boundary " PTR_FORMAT " should be at or below begin " PTR_FORMAT,
+ b, begin));
+ assert(begin <= end,
+ err_msg("Error: begin " PTR_FORMAT " should be strictly below end " PTR_FORMAT,
+ begin, end));
+ }
+
virtual void do_oop(oop* p) { VerifyCleanCardClosure::do_oop_work(p); }
virtual void do_oop(narrowOop* p) { VerifyCleanCardClosure::do_oop_work(p); }
};
@@ -392,13 +403,14 @@
}
}
// Now traverse objects until end.
- HeapWord* cur = start_block;
- VerifyCleanCardClosure verify_blk(gen_boundary, begin, end);
- while (cur < end) {
- if (s->block_is_obj(cur) && s->obj_is_alive(cur)) {
- oop(cur)->oop_iterate(&verify_blk);
+ if (begin < end) {
+ MemRegion mr(begin, end);
+ VerifyCleanCardClosure verify_blk(gen_boundary, begin, end);
+ for (HeapWord* cur = start_block; cur < end; cur += s->block_size(cur)) {
+ if (s->block_is_obj(cur) && s->obj_is_alive(cur)) {
+ oop(cur)->oop_iterate(&verify_blk, mr);
+ }
}
- cur += s->block_size(cur);
}
cur_entry = first_dirty;
} else {