Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 2030:fb712ff22571
7000559: G1: assertion failure !outer || (full_collections_started == _full_collections_completed + 1)
Summary: The concurrent marking thread can complete its operation and increment the full GC counter during a Full GC. This causes the nesting of increments to the start and end of Full GCs that we are expecting to be wrong. the fix is for the marking thread to join the suspendible thread set before incrementing the counter so that it's blocked until the Full GC (or any other safepoint) is finished. The change also includes some minor code cleanup (I renamed a parameter).
Reviewed-by: brutisso, ysr
author | tonyp |
---|---|
date | Tue, 14 Dec 2010 16:19:44 -0500 |
parents | 8df09fb45352 |
children | b03260081e9b |
comparison
equal
deleted
inserted
replaced
1996:f0ef5f5a460f | 2030:fb712ff22571 |
---|---|
1387 assert( check_young_list_empty(true /* check_heap */), | 1387 assert( check_young_list_empty(true /* check_heap */), |
1388 "young list should be empty at this point"); | 1388 "young list should be empty at this point"); |
1389 } | 1389 } |
1390 | 1390 |
1391 // Update the number of full collections that have been completed. | 1391 // Update the number of full collections that have been completed. |
1392 increment_full_collections_completed(false /* outer */); | 1392 increment_full_collections_completed(false /* concurrent */); |
1393 | 1393 |
1394 if (PrintHeapAtGC) { | 1394 if (PrintHeapAtGC) { |
1395 Universe::print_heap_after_gc(); | 1395 Universe::print_heap_after_gc(); |
1396 } | 1396 } |
1397 | 1397 |
2174 return | 2174 return |
2175 ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || | 2175 ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || |
2176 (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)); | 2176 (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)); |
2177 } | 2177 } |
2178 | 2178 |
2179 void G1CollectedHeap::increment_full_collections_completed(bool outer) { | 2179 void G1CollectedHeap::increment_full_collections_completed(bool concurrent) { |
2180 MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); | 2180 MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); |
2181 | |
2182 // We assume that if concurrent == true, then the caller is a | |
2183 // concurrent thread that was joined the Suspendible Thread | |
2184 // Set. If there's ever a cheap way to check this, we should add an | |
2185 // assert here. | |
2181 | 2186 |
2182 // We have already incremented _total_full_collections at the start | 2187 // We have already incremented _total_full_collections at the start |
2183 // of the GC, so total_full_collections() represents how many full | 2188 // of the GC, so total_full_collections() represents how many full |
2184 // collections have been started. | 2189 // collections have been started. |
2185 unsigned int full_collections_started = total_full_collections(); | 2190 unsigned int full_collections_started = total_full_collections(); |
2190 // completed should be either one (in the case where there was no | 2195 // completed should be either one (in the case where there was no |
2191 // nesting) or two (when a Full GC interrupted a concurrent cycle) | 2196 // nesting) or two (when a Full GC interrupted a concurrent cycle) |
2192 // behind the number of full collections started. | 2197 // behind the number of full collections started. |
2193 | 2198 |
2194 // This is the case for the inner caller, i.e. a Full GC. | 2199 // This is the case for the inner caller, i.e. a Full GC. |
2195 assert(outer || | 2200 assert(concurrent || |
2196 (full_collections_started == _full_collections_completed + 1) || | 2201 (full_collections_started == _full_collections_completed + 1) || |
2197 (full_collections_started == _full_collections_completed + 2), | 2202 (full_collections_started == _full_collections_completed + 2), |
2198 err_msg("for inner caller: full_collections_started = %u " | 2203 err_msg("for inner caller (Full GC): full_collections_started = %u " |
2199 "is inconsistent with _full_collections_completed = %u", | 2204 "is inconsistent with _full_collections_completed = %u", |
2200 full_collections_started, _full_collections_completed)); | 2205 full_collections_started, _full_collections_completed)); |
2201 | 2206 |
2202 // This is the case for the outer caller, i.e. the concurrent cycle. | 2207 // This is the case for the outer caller, i.e. the concurrent cycle. |
2203 assert(!outer || | 2208 assert(!concurrent || |
2204 (full_collections_started == _full_collections_completed + 1), | 2209 (full_collections_started == _full_collections_completed + 1), |
2205 err_msg("for outer caller: full_collections_started = %u " | 2210 err_msg("for outer caller (concurrent cycle): " |
2211 "full_collections_started = %u " | |
2206 "is inconsistent with _full_collections_completed = %u", | 2212 "is inconsistent with _full_collections_completed = %u", |
2207 full_collections_started, _full_collections_completed)); | 2213 full_collections_started, _full_collections_completed)); |
2208 | 2214 |
2209 _full_collections_completed += 1; | 2215 _full_collections_completed += 1; |
2210 | 2216 |
2211 // We need to clear the "in_progress" flag in the CM thread before | 2217 // We need to clear the "in_progress" flag in the CM thread before |
2212 // we wake up any waiters (especially when ExplicitInvokesConcurrent | 2218 // we wake up any waiters (especially when ExplicitInvokesConcurrent |
2213 // is set) so that if a waiter requests another System.gc() it doesn't | 2219 // is set) so that if a waiter requests another System.gc() it doesn't |
2214 // incorrectly see that a marking cyle is still in progress. | 2220 // incorrectly see that a marking cyle is still in progress. |
2215 if (outer) { | 2221 if (concurrent) { |
2216 _cmThread->clear_in_progress(); | 2222 _cmThread->clear_in_progress(); |
2217 } | 2223 } |
2218 | 2224 |
2219 // This notify_all() will ensure that a thread that called | 2225 // This notify_all() will ensure that a thread that called |
2220 // System.gc() with (with ExplicitGCInvokesConcurrent set or not) | 2226 // System.gc() with (with ExplicitGCInvokesConcurrent set or not) |