Mercurial > hg > truffle
diff src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 1020:ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
Summary: 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
author | tonyp |
---|---|
date | Fri, 02 Oct 2009 16:20:42 -0400 |
parents | 035d2e036a9b |
children | 6270f80a7331 |
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Oct 02 16:12:07 2009 -0400 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Oct 02 16:20:42 2009 -0400 @@ -2210,40 +2210,58 @@ bool _allow_dirty; bool _par; bool _use_prev_marking; + bool _failures; public: // use_prev_marking == true -> use "prev" marking information, // use_prev_marking == false -> use "next" marking information VerifyRegionClosure(bool allow_dirty, bool par, bool use_prev_marking) : _allow_dirty(allow_dirty), _par(par), - _use_prev_marking(use_prev_marking) {} + _use_prev_marking(use_prev_marking), + _failures(false) {} + + bool failures() { + return _failures; + } bool doHeapRegion(HeapRegion* r) { guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue, "Should be unclaimed at verify points."); if (!r->continuesHumongous()) { - VerifyObjsInRegionClosure not_dead_yet_cl(r, _use_prev_marking); - r->verify(_allow_dirty, _use_prev_marking); - r->object_iterate(¬_dead_yet_cl); - guarantee(r->max_live_bytes() >= not_dead_yet_cl.live_bytes(), - "More live objects than counted in last complete marking."); + bool failures = false; + r->verify(_allow_dirty, _use_prev_marking, &failures); + if (failures) { + _failures = true; + } else { + VerifyObjsInRegionClosure not_dead_yet_cl(r, _use_prev_marking); + r->object_iterate(¬_dead_yet_cl); + if (r->max_live_bytes() < not_dead_yet_cl.live_bytes()) { + gclog_or_tty->print_cr("["PTR_FORMAT","PTR_FORMAT"] " + "max_live_bytes "SIZE_FORMAT" " + "< calculated "SIZE_FORMAT, + r->bottom(), r->end(), + r->max_live_bytes(), + not_dead_yet_cl.live_bytes()); + _failures = true; + } + } } - return false; + return false; // stop the region iteration if we hit a failure } }; class VerifyRootsClosure: public OopsInGenClosure { private: G1CollectedHeap* _g1h; + bool _use_prev_marking; bool _failures; - bool _use_prev_marking; public: // use_prev_marking == true -> use "prev" marking information, // use_prev_marking == false -> use "next" marking information VerifyRootsClosure(bool use_prev_marking) : _g1h(G1CollectedHeap::heap()), - _failures(false), - _use_prev_marking(use_prev_marking) { } + _use_prev_marking(use_prev_marking), + _failures(false) { } bool failures() { return _failures; } @@ -2253,7 +2271,7 @@ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); if (_g1h->is_obj_dead_cond(obj, _use_prev_marking)) { gclog_or_tty->print_cr("Root location "PTR_FORMAT" " - "points to dead obj "PTR_FORMAT, p, (void*) obj); + "points to dead obj "PTR_FORMAT, p, (void*) obj); obj->print_on(gclog_or_tty); _failures = true; } @@ -2271,6 +2289,7 @@ G1CollectedHeap* _g1h; bool _allow_dirty; bool _use_prev_marking; + bool _failures; public: // use_prev_marking == true -> use "prev" marking information, @@ -2280,13 +2299,21 @@ AbstractGangTask("Parallel verify task"), _g1h(g1h), _allow_dirty(allow_dirty), - _use_prev_marking(use_prev_marking) { } + _use_prev_marking(use_prev_marking), + _failures(false) { } + + bool failures() { + return _failures; + } void work(int worker_i) { HandleMark hm; VerifyRegionClosure blk(_allow_dirty, true, _use_prev_marking); _g1h->heap_region_par_iterate_chunked(&blk, worker_i, HeapRegion::ParVerifyClaimValue); + if (blk.failures()) { + _failures = true; + } } }; @@ -2307,6 +2334,7 @@ &rootsCl, &blobsCl, &rootsCl); + bool failures = rootsCl.failures(); rem_set()->invalidate(perm_gen()->used_region(), false); if (!silent) { gclog_or_tty->print("heapRegions "); } if (GCParallelVerificationEnabled && ParallelGCThreads > 1) { @@ -2318,6 +2346,9 @@ set_par_threads(n_workers); workers()->run_task(&task); set_par_threads(0); + if (task.failures()) { + failures = true; + } assert(check_heap_region_claim_values(HeapRegion::ParVerifyClaimValue), "sanity check"); @@ -2329,10 +2360,23 @@ } else { VerifyRegionClosure blk(allow_dirty, false, use_prev_marking); _hrs->iterate(&blk); + if (blk.failures()) { + failures = true; + } } if (!silent) gclog_or_tty->print("remset "); rem_set()->verify(); - guarantee(!rootsCl.failures(), "should not have had failures"); + + if (failures) { + gclog_or_tty->print_cr("Heap:"); + print_on(gclog_or_tty, true /* extended */); + gclog_or_tty->print_cr(""); + if (VerifyDuringGC && G1VerifyConcMarkPrintReachable) { + concurrent_mark()->print_prev_bitmap_reachable(); + } + gclog_or_tty->flush(); + } + guarantee(!failures, "there should not have been any failures"); } else { if (!silent) gclog_or_tty->print("(SKIPPING roots, heapRegions, remset) "); } @@ -2374,6 +2418,7 @@ st->cr(); perm()->as_gen()->print_on(st); if (extended) { + st->cr(); print_on_extended(st); } }