Mercurial > hg > graal-jvmci-8
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); |