comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 6120:37552638d24a

7172388: G1: _total_full_collections should not be incremented for concurrent cycles Reviewed-by: azeemj, jmasa
author brutisso
date Tue, 05 Jun 2012 22:30:24 +0200
parents bbc900c2482a
children b9442ac22f59
comparison
equal deleted inserted replaced
6119:a297b0e14605 6120:37552638d24a
1297 _cm->root_regions()->wait_until_scan_finished(); 1297 _cm->root_regions()->wait_until_scan_finished();
1298 append_secondary_free_list_if_not_empty_with_lock(); 1298 append_secondary_free_list_if_not_empty_with_lock();
1299 1299
1300 gc_prologue(true); 1300 gc_prologue(true);
1301 increment_total_collections(true /* full gc */); 1301 increment_total_collections(true /* full gc */);
1302 increment_old_marking_cycles_started();
1302 1303
1303 size_t g1h_prev_used = used(); 1304 size_t g1h_prev_used = used();
1304 assert(used() == recalculate_used(), "Should be equal"); 1305 assert(used() == recalculate_used(), "Should be equal");
1305 1306
1306 if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) { 1307 if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) {
1499 // entire heap tagged as young. 1500 // entire heap tagged as young.
1500 assert( check_young_list_empty(true /* check_heap */), 1501 assert( check_young_list_empty(true /* check_heap */),
1501 "young list should be empty at this point"); 1502 "young list should be empty at this point");
1502 1503
1503 // Update the number of full collections that have been completed. 1504 // Update the number of full collections that have been completed.
1504 increment_full_collections_completed(false /* concurrent */); 1505 increment_old_marking_cycles_completed(false /* concurrent */);
1505 1506
1506 _hrs.verify_optional(); 1507 _hrs.verify_optional();
1507 verify_region_sets_optional(); 1508 verify_region_sets_optional();
1508 1509
1509 print_heap_after_gc(); 1510 print_heap_after_gc();
1886 _young_list(new YoungList(this)), 1887 _young_list(new YoungList(this)),
1887 _gc_time_stamp(0), 1888 _gc_time_stamp(0),
1888 _retained_old_gc_alloc_region(NULL), 1889 _retained_old_gc_alloc_region(NULL),
1889 _expand_heap_after_alloc_failure(true), 1890 _expand_heap_after_alloc_failure(true),
1890 _surviving_young_words(NULL), 1891 _surviving_young_words(NULL),
1891 _full_collections_completed(0), 1892 _old_marking_cycles_started(0),
1893 _old_marking_cycles_completed(0),
1892 _in_cset_fast_test(NULL), 1894 _in_cset_fast_test(NULL),
1893 _in_cset_fast_test_base(NULL), 1895 _in_cset_fast_test_base(NULL),
1894 _dirty_cards_region_list(NULL), 1896 _dirty_cards_region_list(NULL),
1895 _worker_cset_start_region(NULL), 1897 _worker_cset_start_region(NULL),
1896 _worker_cset_start_region_time_stamp(NULL) { 1898 _worker_cset_start_region_time_stamp(NULL) {
2358 } 2360 }
2359 } 2361 }
2360 } 2362 }
2361 #endif // !PRODUCT 2363 #endif // !PRODUCT
2362 2364
2363 void G1CollectedHeap::increment_full_collections_completed(bool concurrent) { 2365 void G1CollectedHeap::increment_old_marking_cycles_started() {
2366 assert(_old_marking_cycles_started == _old_marking_cycles_completed ||
2367 _old_marking_cycles_started == _old_marking_cycles_completed + 1,
2368 err_msg("Wrong marking cycle count (started: %d, completed: %d)",
2369 _old_marking_cycles_started, _old_marking_cycles_completed));
2370
2371 _old_marking_cycles_started++;
2372 }
2373
2374 void G1CollectedHeap::increment_old_marking_cycles_completed(bool concurrent) {
2364 MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); 2375 MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
2365 2376
2366 // We assume that if concurrent == true, then the caller is a 2377 // We assume that if concurrent == true, then the caller is a
2367 // concurrent thread that was joined the Suspendible Thread 2378 // concurrent thread that was joined the Suspendible Thread
2368 // Set. If there's ever a cheap way to check this, we should add an 2379 // Set. If there's ever a cheap way to check this, we should add an
2369 // assert here. 2380 // assert here.
2370
2371 // We have already incremented _total_full_collections at the start
2372 // of the GC, so total_full_collections() represents how many full
2373 // collections have been started.
2374 unsigned int full_collections_started = total_full_collections();
2375 2381
2376 // Given that this method is called at the end of a Full GC or of a 2382 // Given that this method is called at the end of a Full GC or of a
2377 // concurrent cycle, and those can be nested (i.e., a Full GC can 2383 // concurrent cycle, and those can be nested (i.e., a Full GC can
2378 // interrupt a concurrent cycle), the number of full collections 2384 // interrupt a concurrent cycle), the number of full collections
2379 // completed should be either one (in the case where there was no 2385 // completed should be either one (in the case where there was no
2380 // nesting) or two (when a Full GC interrupted a concurrent cycle) 2386 // nesting) or two (when a Full GC interrupted a concurrent cycle)
2381 // behind the number of full collections started. 2387 // behind the number of full collections started.
2382 2388
2383 // This is the case for the inner caller, i.e. a Full GC. 2389 // This is the case for the inner caller, i.e. a Full GC.
2384 assert(concurrent || 2390 assert(concurrent ||
2385 (full_collections_started == _full_collections_completed + 1) || 2391 (_old_marking_cycles_started == _old_marking_cycles_completed + 1) ||
2386 (full_collections_started == _full_collections_completed + 2), 2392 (_old_marking_cycles_started == _old_marking_cycles_completed + 2),
2387 err_msg("for inner caller (Full GC): full_collections_started = %u " 2393 err_msg("for inner caller (Full GC): _old_marking_cycles_started = %u "
2388 "is inconsistent with _full_collections_completed = %u", 2394 "is inconsistent with _old_marking_cycles_completed = %u",
2389 full_collections_started, _full_collections_completed)); 2395 _old_marking_cycles_started, _old_marking_cycles_completed));
2390 2396
2391 // This is the case for the outer caller, i.e. the concurrent cycle. 2397 // This is the case for the outer caller, i.e. the concurrent cycle.
2392 assert(!concurrent || 2398 assert(!concurrent ||
2393 (full_collections_started == _full_collections_completed + 1), 2399 (_old_marking_cycles_started == _old_marking_cycles_completed + 1),
2394 err_msg("for outer caller (concurrent cycle): " 2400 err_msg("for outer caller (concurrent cycle): "
2395 "full_collections_started = %u " 2401 "_old_marking_cycles_started = %u "
2396 "is inconsistent with _full_collections_completed = %u", 2402 "is inconsistent with _old_marking_cycles_completed = %u",
2397 full_collections_started, _full_collections_completed)); 2403 _old_marking_cycles_started, _old_marking_cycles_completed));
2398 2404
2399 _full_collections_completed += 1; 2405 _old_marking_cycles_completed += 1;
2400 2406
2401 // We need to clear the "in_progress" flag in the CM thread before 2407 // We need to clear the "in_progress" flag in the CM thread before
2402 // we wake up any waiters (especially when ExplicitInvokesConcurrent 2408 // we wake up any waiters (especially when ExplicitInvokesConcurrent
2403 // is set) so that if a waiter requests another System.gc() it doesn't 2409 // is set) so that if a waiter requests another System.gc() it doesn't
2404 // incorrectly see that a marking cyle is still in progress. 2410 // incorrectly see that a marking cyle is still in progress.
2430 2436
2431 void G1CollectedHeap::collect(GCCause::Cause cause) { 2437 void G1CollectedHeap::collect(GCCause::Cause cause) {
2432 assert_heap_not_locked(); 2438 assert_heap_not_locked();
2433 2439
2434 unsigned int gc_count_before; 2440 unsigned int gc_count_before;
2435 unsigned int full_gc_count_before; 2441 unsigned int old_marking_count_before;
2436 bool retry_gc; 2442 bool retry_gc;
2437 2443
2438 do { 2444 do {
2439 retry_gc = false; 2445 retry_gc = false;
2440 2446
2441 { 2447 {
2442 MutexLocker ml(Heap_lock); 2448 MutexLocker ml(Heap_lock);
2443 2449
2444 // Read the GC count while holding the Heap_lock 2450 // Read the GC count while holding the Heap_lock
2445 gc_count_before = total_collections(); 2451 gc_count_before = total_collections();
2446 full_gc_count_before = total_full_collections(); 2452 old_marking_count_before = _old_marking_cycles_started;
2447 } 2453 }
2448 2454
2449 if (should_do_concurrent_full_gc(cause)) { 2455 if (should_do_concurrent_full_gc(cause)) {
2450 // Schedule an initial-mark evacuation pause that will start a 2456 // Schedule an initial-mark evacuation pause that will start a
2451 // concurrent cycle. We're setting word_size to 0 which means that 2457 // concurrent cycle. We're setting word_size to 0 which means that
2456 g1_policy()->max_pause_time_ms(), 2462 g1_policy()->max_pause_time_ms(),
2457 cause); 2463 cause);
2458 2464
2459 VMThread::execute(&op); 2465 VMThread::execute(&op);
2460 if (!op.pause_succeeded()) { 2466 if (!op.pause_succeeded()) {
2461 if (full_gc_count_before == total_full_collections()) { 2467 if (old_marking_count_before == _old_marking_cycles_started) {
2462 retry_gc = op.should_retry_gc(); 2468 retry_gc = op.should_retry_gc();
2463 } else { 2469 } else {
2464 // A Full GC happened while we were trying to schedule the 2470 // A Full GC happened while we were trying to schedule the
2465 // initial-mark GC. No point in starting a new cycle given 2471 // initial-mark GC. No point in starting a new cycle given
2466 // that the whole heap was collected anyway. 2472 // that the whole heap was collected anyway.
2484 g1_policy()->max_pause_time_ms(), 2490 g1_policy()->max_pause_time_ms(),
2485 cause); 2491 cause);
2486 VMThread::execute(&op); 2492 VMThread::execute(&op);
2487 } else { 2493 } else {
2488 // Schedule a Full GC. 2494 // Schedule a Full GC.
2489 VM_G1CollectFull op(gc_count_before, full_gc_count_before, cause); 2495 VM_G1CollectFull op(gc_count_before, old_marking_count_before, cause);
2490 VMThread::execute(&op); 2496 VMThread::execute(&op);
2491 } 2497 }
2492 } 2498 }
2493 } while (retry_gc); 2499 } while (retry_gc);
2494 } 2500 }
3611 // Inner scope for scope based logging, timers, and stats collection 3617 // Inner scope for scope based logging, timers, and stats collection
3612 { 3618 {
3613 if (g1_policy()->during_initial_mark_pause()) { 3619 if (g1_policy()->during_initial_mark_pause()) {
3614 // We are about to start a marking cycle, so we increment the 3620 // We are about to start a marking cycle, so we increment the
3615 // full collection counter. 3621 // full collection counter.
3616 increment_total_full_collections(); 3622 increment_old_marking_cycles_started();
3617 } 3623 }
3618 // if the log level is "finer" is on, we'll print long statistics information 3624 // if the log level is "finer" is on, we'll print long statistics information
3619 // in the collector policy code, so let's not print this as the output 3625 // in the collector policy code, so let's not print this as the output
3620 // is messy if we do. 3626 // is messy if we do.
3621 gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps); 3627 gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);