Mercurial > hg > truffle
comparison 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 |
comparison
equal
deleted
inserted
replaced
1019:035d2e036a9b | 1020:ff2402f6a50b |
---|---|
2208 class VerifyRegionClosure: public HeapRegionClosure { | 2208 class VerifyRegionClosure: public HeapRegionClosure { |
2209 private: | 2209 private: |
2210 bool _allow_dirty; | 2210 bool _allow_dirty; |
2211 bool _par; | 2211 bool _par; |
2212 bool _use_prev_marking; | 2212 bool _use_prev_marking; |
2213 bool _failures; | |
2213 public: | 2214 public: |
2214 // use_prev_marking == true -> use "prev" marking information, | 2215 // use_prev_marking == true -> use "prev" marking information, |
2215 // use_prev_marking == false -> use "next" marking information | 2216 // use_prev_marking == false -> use "next" marking information |
2216 VerifyRegionClosure(bool allow_dirty, bool par, bool use_prev_marking) | 2217 VerifyRegionClosure(bool allow_dirty, bool par, bool use_prev_marking) |
2217 : _allow_dirty(allow_dirty), | 2218 : _allow_dirty(allow_dirty), |
2218 _par(par), | 2219 _par(par), |
2219 _use_prev_marking(use_prev_marking) {} | 2220 _use_prev_marking(use_prev_marking), |
2221 _failures(false) {} | |
2222 | |
2223 bool failures() { | |
2224 return _failures; | |
2225 } | |
2220 | 2226 |
2221 bool doHeapRegion(HeapRegion* r) { | 2227 bool doHeapRegion(HeapRegion* r) { |
2222 guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue, | 2228 guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue, |
2223 "Should be unclaimed at verify points."); | 2229 "Should be unclaimed at verify points."); |
2224 if (!r->continuesHumongous()) { | 2230 if (!r->continuesHumongous()) { |
2225 VerifyObjsInRegionClosure not_dead_yet_cl(r, _use_prev_marking); | 2231 bool failures = false; |
2226 r->verify(_allow_dirty, _use_prev_marking); | 2232 r->verify(_allow_dirty, _use_prev_marking, &failures); |
2227 r->object_iterate(¬_dead_yet_cl); | 2233 if (failures) { |
2228 guarantee(r->max_live_bytes() >= not_dead_yet_cl.live_bytes(), | 2234 _failures = true; |
2229 "More live objects than counted in last complete marking."); | 2235 } else { |
2230 } | 2236 VerifyObjsInRegionClosure not_dead_yet_cl(r, _use_prev_marking); |
2231 return false; | 2237 r->object_iterate(¬_dead_yet_cl); |
2238 if (r->max_live_bytes() < not_dead_yet_cl.live_bytes()) { | |
2239 gclog_or_tty->print_cr("["PTR_FORMAT","PTR_FORMAT"] " | |
2240 "max_live_bytes "SIZE_FORMAT" " | |
2241 "< calculated "SIZE_FORMAT, | |
2242 r->bottom(), r->end(), | |
2243 r->max_live_bytes(), | |
2244 not_dead_yet_cl.live_bytes()); | |
2245 _failures = true; | |
2246 } | |
2247 } | |
2248 } | |
2249 return false; // stop the region iteration if we hit a failure | |
2232 } | 2250 } |
2233 }; | 2251 }; |
2234 | 2252 |
2235 class VerifyRootsClosure: public OopsInGenClosure { | 2253 class VerifyRootsClosure: public OopsInGenClosure { |
2236 private: | 2254 private: |
2237 G1CollectedHeap* _g1h; | 2255 G1CollectedHeap* _g1h; |
2256 bool _use_prev_marking; | |
2238 bool _failures; | 2257 bool _failures; |
2239 bool _use_prev_marking; | |
2240 public: | 2258 public: |
2241 // use_prev_marking == true -> use "prev" marking information, | 2259 // use_prev_marking == true -> use "prev" marking information, |
2242 // use_prev_marking == false -> use "next" marking information | 2260 // use_prev_marking == false -> use "next" marking information |
2243 VerifyRootsClosure(bool use_prev_marking) : | 2261 VerifyRootsClosure(bool use_prev_marking) : |
2244 _g1h(G1CollectedHeap::heap()), | 2262 _g1h(G1CollectedHeap::heap()), |
2245 _failures(false), | 2263 _use_prev_marking(use_prev_marking), |
2246 _use_prev_marking(use_prev_marking) { } | 2264 _failures(false) { } |
2247 | 2265 |
2248 bool failures() { return _failures; } | 2266 bool failures() { return _failures; } |
2249 | 2267 |
2250 template <class T> void do_oop_nv(T* p) { | 2268 template <class T> void do_oop_nv(T* p) { |
2251 T heap_oop = oopDesc::load_heap_oop(p); | 2269 T heap_oop = oopDesc::load_heap_oop(p); |
2252 if (!oopDesc::is_null(heap_oop)) { | 2270 if (!oopDesc::is_null(heap_oop)) { |
2253 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); | 2271 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); |
2254 if (_g1h->is_obj_dead_cond(obj, _use_prev_marking)) { | 2272 if (_g1h->is_obj_dead_cond(obj, _use_prev_marking)) { |
2255 gclog_or_tty->print_cr("Root location "PTR_FORMAT" " | 2273 gclog_or_tty->print_cr("Root location "PTR_FORMAT" " |
2256 "points to dead obj "PTR_FORMAT, p, (void*) obj); | 2274 "points to dead obj "PTR_FORMAT, p, (void*) obj); |
2257 obj->print_on(gclog_or_tty); | 2275 obj->print_on(gclog_or_tty); |
2258 _failures = true; | 2276 _failures = true; |
2259 } | 2277 } |
2260 } | 2278 } |
2261 } | 2279 } |
2269 class G1ParVerifyTask: public AbstractGangTask { | 2287 class G1ParVerifyTask: public AbstractGangTask { |
2270 private: | 2288 private: |
2271 G1CollectedHeap* _g1h; | 2289 G1CollectedHeap* _g1h; |
2272 bool _allow_dirty; | 2290 bool _allow_dirty; |
2273 bool _use_prev_marking; | 2291 bool _use_prev_marking; |
2292 bool _failures; | |
2274 | 2293 |
2275 public: | 2294 public: |
2276 // use_prev_marking == true -> use "prev" marking information, | 2295 // use_prev_marking == true -> use "prev" marking information, |
2277 // use_prev_marking == false -> use "next" marking information | 2296 // use_prev_marking == false -> use "next" marking information |
2278 G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty, | 2297 G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty, |
2279 bool use_prev_marking) : | 2298 bool use_prev_marking) : |
2280 AbstractGangTask("Parallel verify task"), | 2299 AbstractGangTask("Parallel verify task"), |
2281 _g1h(g1h), | 2300 _g1h(g1h), |
2282 _allow_dirty(allow_dirty), | 2301 _allow_dirty(allow_dirty), |
2283 _use_prev_marking(use_prev_marking) { } | 2302 _use_prev_marking(use_prev_marking), |
2303 _failures(false) { } | |
2304 | |
2305 bool failures() { | |
2306 return _failures; | |
2307 } | |
2284 | 2308 |
2285 void work(int worker_i) { | 2309 void work(int worker_i) { |
2286 HandleMark hm; | 2310 HandleMark hm; |
2287 VerifyRegionClosure blk(_allow_dirty, true, _use_prev_marking); | 2311 VerifyRegionClosure blk(_allow_dirty, true, _use_prev_marking); |
2288 _g1h->heap_region_par_iterate_chunked(&blk, worker_i, | 2312 _g1h->heap_region_par_iterate_chunked(&blk, worker_i, |
2289 HeapRegion::ParVerifyClaimValue); | 2313 HeapRegion::ParVerifyClaimValue); |
2314 if (blk.failures()) { | |
2315 _failures = true; | |
2316 } | |
2290 } | 2317 } |
2291 }; | 2318 }; |
2292 | 2319 |
2293 void G1CollectedHeap::verify(bool allow_dirty, bool silent) { | 2320 void G1CollectedHeap::verify(bool allow_dirty, bool silent) { |
2294 verify(allow_dirty, silent, /* use_prev_marking */ true); | 2321 verify(allow_dirty, silent, /* use_prev_marking */ true); |
2305 false, | 2332 false, |
2306 SharedHeap::SO_AllClasses, | 2333 SharedHeap::SO_AllClasses, |
2307 &rootsCl, | 2334 &rootsCl, |
2308 &blobsCl, | 2335 &blobsCl, |
2309 &rootsCl); | 2336 &rootsCl); |
2337 bool failures = rootsCl.failures(); | |
2310 rem_set()->invalidate(perm_gen()->used_region(), false); | 2338 rem_set()->invalidate(perm_gen()->used_region(), false); |
2311 if (!silent) { gclog_or_tty->print("heapRegions "); } | 2339 if (!silent) { gclog_or_tty->print("heapRegions "); } |
2312 if (GCParallelVerificationEnabled && ParallelGCThreads > 1) { | 2340 if (GCParallelVerificationEnabled && ParallelGCThreads > 1) { |
2313 assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), | 2341 assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), |
2314 "sanity check"); | 2342 "sanity check"); |
2316 G1ParVerifyTask task(this, allow_dirty, use_prev_marking); | 2344 G1ParVerifyTask task(this, allow_dirty, use_prev_marking); |
2317 int n_workers = workers()->total_workers(); | 2345 int n_workers = workers()->total_workers(); |
2318 set_par_threads(n_workers); | 2346 set_par_threads(n_workers); |
2319 workers()->run_task(&task); | 2347 workers()->run_task(&task); |
2320 set_par_threads(0); | 2348 set_par_threads(0); |
2349 if (task.failures()) { | |
2350 failures = true; | |
2351 } | |
2321 | 2352 |
2322 assert(check_heap_region_claim_values(HeapRegion::ParVerifyClaimValue), | 2353 assert(check_heap_region_claim_values(HeapRegion::ParVerifyClaimValue), |
2323 "sanity check"); | 2354 "sanity check"); |
2324 | 2355 |
2325 reset_heap_region_claim_values(); | 2356 reset_heap_region_claim_values(); |
2327 assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), | 2358 assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), |
2328 "sanity check"); | 2359 "sanity check"); |
2329 } else { | 2360 } else { |
2330 VerifyRegionClosure blk(allow_dirty, false, use_prev_marking); | 2361 VerifyRegionClosure blk(allow_dirty, false, use_prev_marking); |
2331 _hrs->iterate(&blk); | 2362 _hrs->iterate(&blk); |
2363 if (blk.failures()) { | |
2364 failures = true; | |
2365 } | |
2332 } | 2366 } |
2333 if (!silent) gclog_or_tty->print("remset "); | 2367 if (!silent) gclog_or_tty->print("remset "); |
2334 rem_set()->verify(); | 2368 rem_set()->verify(); |
2335 guarantee(!rootsCl.failures(), "should not have had failures"); | 2369 |
2370 if (failures) { | |
2371 gclog_or_tty->print_cr("Heap:"); | |
2372 print_on(gclog_or_tty, true /* extended */); | |
2373 gclog_or_tty->print_cr(""); | |
2374 if (VerifyDuringGC && G1VerifyConcMarkPrintReachable) { | |
2375 concurrent_mark()->print_prev_bitmap_reachable(); | |
2376 } | |
2377 gclog_or_tty->flush(); | |
2378 } | |
2379 guarantee(!failures, "there should not have been any failures"); | |
2336 } else { | 2380 } else { |
2337 if (!silent) gclog_or_tty->print("(SKIPPING roots, heapRegions, remset) "); | 2381 if (!silent) gclog_or_tty->print("(SKIPPING roots, heapRegions, remset) "); |
2338 } | 2382 } |
2339 } | 2383 } |
2340 | 2384 |
2372 st->print(SIZE_FORMAT " survivors (" SIZE_FORMAT "K)", | 2416 st->print(SIZE_FORMAT " survivors (" SIZE_FORMAT "K)", |
2373 survivor_regions, survivor_regions * HeapRegion::GrainBytes / K); | 2417 survivor_regions, survivor_regions * HeapRegion::GrainBytes / K); |
2374 st->cr(); | 2418 st->cr(); |
2375 perm()->as_gen()->print_on(st); | 2419 perm()->as_gen()->print_on(st); |
2376 if (extended) { | 2420 if (extended) { |
2421 st->cr(); | |
2377 print_on_extended(st); | 2422 print_on_extended(st); |
2378 } | 2423 } |
2379 } | 2424 } |
2380 | 2425 |
2381 void G1CollectedHeap::print_on_extended(outputStream* st) const { | 2426 void G1CollectedHeap::print_on_extended(outputStream* st) const { |