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(&not_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(&not_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 {