mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
6882730: G1: parallel heap verification messes up region dump
It tidies up the G1 heap verification a bit. In particular, when the verification is done in parallel and there is a failure, this is propagated to the top level and the heap is dumped at the end, not by every thread that encounters a failure. Reviewed-by: johnc, jmasa
This commit is contained in:
parent
99a529bb86
commit
2684c3a431
3 changed files with 116 additions and 37 deletions
|
@ -722,12 +722,13 @@ void HeapRegion::print_on(outputStream* st) const {
|
|||
st->print(" F");
|
||||
else
|
||||
st->print(" ");
|
||||
st->print(" %d", _gc_time_stamp);
|
||||
st->print(" %5d", _gc_time_stamp);
|
||||
G1OffsetTableContigSpace::print_on(st);
|
||||
}
|
||||
|
||||
void HeapRegion::verify(bool allow_dirty) const {
|
||||
verify(allow_dirty, /* use_prev_marking */ true);
|
||||
bool dummy = false;
|
||||
verify(allow_dirty, /* use_prev_marking */ true, /* failures */ &dummy);
|
||||
}
|
||||
|
||||
#define OBJ_SAMPLE_INTERVAL 0
|
||||
|
@ -736,8 +737,11 @@ void HeapRegion::verify(bool allow_dirty) const {
|
|||
// This really ought to be commoned up into OffsetTableContigSpace somehow.
|
||||
// We would need a mechanism to make that code skip dead objects.
|
||||
|
||||
void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const {
|
||||
void HeapRegion::verify(bool allow_dirty,
|
||||
bool use_prev_marking,
|
||||
bool* failures) const {
|
||||
G1CollectedHeap* g1 = G1CollectedHeap::heap();
|
||||
*failures = false;
|
||||
HeapWord* p = bottom();
|
||||
HeapWord* prev_p = NULL;
|
||||
int objs = 0;
|
||||
|
@ -746,8 +750,14 @@ void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const {
|
|||
while (p < top()) {
|
||||
size_t size = oop(p)->size();
|
||||
if (blocks == BLOCK_SAMPLE_INTERVAL) {
|
||||
guarantee(p == block_start_const(p + (size/2)),
|
||||
"check offset computation");
|
||||
HeapWord* res = block_start_const(p + (size/2));
|
||||
if (p != res) {
|
||||
gclog_or_tty->print_cr("offset computation 1 for "PTR_FORMAT" and "
|
||||
SIZE_FORMAT" returned "PTR_FORMAT,
|
||||
p, size, res);
|
||||
*failures = true;
|
||||
return;
|
||||
}
|
||||
blocks = 0;
|
||||
} else {
|
||||
blocks++;
|
||||
|
@ -755,11 +765,34 @@ void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const {
|
|||
if (objs == OBJ_SAMPLE_INTERVAL) {
|
||||
oop obj = oop(p);
|
||||
if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) {
|
||||
obj->verify();
|
||||
vl_cl.set_containing_obj(obj);
|
||||
obj->oop_iterate(&vl_cl);
|
||||
if (G1MaxVerifyFailures >= 0
|
||||
&& vl_cl.n_failures() >= G1MaxVerifyFailures) break;
|
||||
if (obj->is_oop()) {
|
||||
klassOop klass = obj->klass();
|
||||
if (!klass->is_perm()) {
|
||||
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
|
||||
"not in perm", klass, obj);
|
||||
*failures = true;
|
||||
return;
|
||||
} else if (!klass->is_klass()) {
|
||||
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
|
||||
"not a klass", klass, obj);
|
||||
*failures = true;
|
||||
return;
|
||||
} else {
|
||||
vl_cl.set_containing_obj(obj);
|
||||
obj->oop_iterate(&vl_cl);
|
||||
if (vl_cl.failures()) {
|
||||
*failures = true;
|
||||
}
|
||||
if (G1MaxVerifyFailures >= 0 &&
|
||||
vl_cl.n_failures() >= G1MaxVerifyFailures) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj);
|
||||
*failures = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
objs = 0;
|
||||
} else {
|
||||
|
@ -771,21 +804,22 @@ void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const {
|
|||
HeapWord* rend = end();
|
||||
HeapWord* rtop = top();
|
||||
if (rtop < rend) {
|
||||
guarantee(block_start_const(rtop + (rend - rtop) / 2) == rtop,
|
||||
"check offset computation");
|
||||
HeapWord* res = block_start_const(rtop + (rend - rtop) / 2);
|
||||
if (res != rtop) {
|
||||
gclog_or_tty->print_cr("offset computation 2 for "PTR_FORMAT" and "
|
||||
PTR_FORMAT" returned "PTR_FORMAT,
|
||||
rtop, rend, res);
|
||||
*failures = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (vl_cl.failures()) {
|
||||
gclog_or_tty->print_cr("Heap:");
|
||||
G1CollectedHeap::heap()->print_on(gclog_or_tty, true /* extended */);
|
||||
gclog_or_tty->print_cr("");
|
||||
|
||||
if (p != top()) {
|
||||
gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
|
||||
"does not match top "PTR_FORMAT, p, top());
|
||||
*failures = true;
|
||||
return;
|
||||
}
|
||||
if (VerifyDuringGC &&
|
||||
G1VerifyConcMarkPrintReachable &&
|
||||
vl_cl.failures()) {
|
||||
g1->concurrent_mark()->print_prev_bitmap_reachable();
|
||||
}
|
||||
guarantee(!vl_cl.failures(), "region verification failed");
|
||||
guarantee(p == top(), "end of last object must match end of space");
|
||||
}
|
||||
|
||||
// G1OffsetTableContigSpace code; copied from space.cpp. Hope this can go
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue