@@ -1690,6 +1690,66 @@ static bool gc_counter_less_than(uint x, uint y) {
16901690#define LOG_COLLECT_CONCURRENTLY_COMPLETE (cause, result ) \
16911691 LOG_COLLECT_CONCURRENTLY (cause, " complete %s" , BOOL_TO_STR(result))
16921692
1693+ bool G1CollectedHeap::wait_full_mark_finished(GCCause::Cause cause,
1694+ uint old_marking_started_before,
1695+ uint old_marking_started_after,
1696+ uint old_marking_completed_after) {
1697+ // Request is finished if a full collection (concurrent or stw)
1698+ // was started after this request and has completed, e.g.
1699+ // started_before < completed_after.
1700+ if (gc_counter_less_than (old_marking_started_before,
1701+ old_marking_completed_after)) {
1702+ LOG_COLLECT_CONCURRENTLY_COMPLETE (cause, true );
1703+ return true ;
1704+ }
1705+
1706+ if (old_marking_started_after != old_marking_completed_after) {
1707+ // If there is an in-progress cycle (possibly started by us), then
1708+ // wait for that cycle to complete, e.g.
1709+ // while completed_now < started_after.
1710+ LOG_COLLECT_CONCURRENTLY (cause, " wait" );
1711+ MonitorLocker ml (G1OldGCCount_lock);
1712+ while (gc_counter_less_than (_old_marking_cycles_completed,
1713+ old_marking_started_after)) {
1714+ ml.wait ();
1715+ }
1716+ // Request is finished if the collection we just waited for was
1717+ // started after this request.
1718+ if (old_marking_started_before != old_marking_started_after) {
1719+ LOG_COLLECT_CONCURRENTLY (cause, " complete after wait" );
1720+ return true ;
1721+ }
1722+ }
1723+ return false ;
1724+ }
1725+
1726+ // After calling wait_full_mark_finished(), this method determines whether we
1727+ // previously failed for ordinary reasons (concurrent cycle in progress, whitebox
1728+ // has control). Returns if this has been such an ordinary reason.
1729+ static bool should_retry_vm_op (GCCause::Cause cause,
1730+ VM_G1TryInitiateConcMark* op) {
1731+ if (op->cycle_already_in_progress ()) {
1732+ // If VMOp failed because a cycle was already in progress, it
1733+ // is now complete. But it didn't finish this user-requested
1734+ // GC, so try again.
1735+ LOG_COLLECT_CONCURRENTLY (cause, " retry after in-progress" );
1736+ return true ;
1737+ } else if (op->whitebox_attached ()) {
1738+ // If WhiteBox wants control, wait for notification of a state
1739+ // change in the controller, then try again. Don't wait for
1740+ // release of control, since collections may complete while in
1741+ // control. Note: This won't recognize a STW full collection
1742+ // while waiting; we can't wait on multiple monitors.
1743+ LOG_COLLECT_CONCURRENTLY (cause, " whitebox control stall" );
1744+ MonitorLocker ml (ConcurrentGCBreakpoints::monitor ());
1745+ if (ConcurrentGCBreakpoints::is_controlled ()) {
1746+ ml.wait ();
1747+ }
1748+ return true ;
1749+ }
1750+ return false ;
1751+ }
1752+
16931753bool G1CollectedHeap::try_collect_concurrently (GCCause::Cause cause,
16941754 uint gc_counter,
16951755 uint old_marking_started_before) {
@@ -1750,7 +1810,45 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause,
17501810 LOG_COLLECT_CONCURRENTLY (cause, " ignoring STW full GC" );
17511811 old_marking_started_before = old_marking_started_after;
17521812 }
1813+ } else if (GCCause::is_codecache_requested_gc (cause)) {
1814+ // For a CodeCache requested GC, before marking, progress is ensured as the
1815+ // following Remark pause unloads code (and signals the requester such).
1816+ // Otherwise we must ensure that it is restarted.
1817+ //
1818+ // For a CodeCache requested GC, a successful GC operation means that
1819+ // (1) marking is in progress. I.e. the VMOp started the marking or a
1820+ // Remark pause is pending from a different VM op; we will potentially
1821+ // abort a mixed phase if needed.
1822+ // (2) a new cycle was started (by this thread or some other), or
1823+ // (3) a Full GC was performed.
1824+ //
1825+ // Cases (2) and (3) are detected together by a change to
1826+ // _old_marking_cycles_started.
1827+ //
1828+ // Compared to other "automatic" GCs (see below), we do not consider being
1829+ // in whitebox as sufficient too because we might be anywhere within that
1830+ // cycle and we need to make progress.
1831+ if (op.mark_in_progress () ||
1832+ (old_marking_started_before != old_marking_started_after)) {
1833+ LOG_COLLECT_CONCURRENTLY_COMPLETE (cause, true );
1834+ return true ;
1835+ }
1836+
1837+ if (wait_full_mark_finished (cause,
1838+ old_marking_started_before,
1839+ old_marking_started_after,
1840+ old_marking_completed_after)) {
1841+ return true ;
1842+ }
1843+
1844+ if (should_retry_vm_op (cause, &op)) {
1845+ continue ;
1846+ }
17531847 } else if (!GCCause::is_user_requested_gc (cause)) {
1848+ assert (cause == GCCause::_g1_humongous_allocation ||
1849+ cause == GCCause::_g1_periodic_collection,
1850+ " Unsupported cause %s" , GCCause::to_string (cause));
1851+
17541852 // For an "automatic" (not user-requested) collection, we just need to
17551853 // ensure that progress is made.
17561854 //
@@ -1762,11 +1860,6 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause,
17621860 // (5) a Full GC was performed.
17631861 // Cases (4) and (5) are detected together by a change to
17641862 // _old_marking_cycles_started.
1765- //
1766- // Note that (1) does not imply (4). If we're still in the mixed
1767- // phase of an earlier concurrent collection, the request to make the
1768- // collection a concurrent start won't be honored. If we don't check for
1769- // both conditions we'll spin doing back-to-back collections.
17701863 if (op.gc_succeeded () ||
17711864 op.cycle_already_in_progress () ||
17721865 op.whitebox_attached () ||
@@ -1790,56 +1883,20 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause,
17901883 BOOL_TO_STR (op.gc_succeeded ()),
17911884 old_marking_started_before, old_marking_started_after);
17921885
1793- // Request is finished if a full collection (concurrent or stw)
1794- // was started after this request and has completed, e.g.
1795- // started_before < completed_after.
1796- if (gc_counter_less_than (old_marking_started_before,
1797- old_marking_completed_after)) {
1798- LOG_COLLECT_CONCURRENTLY_COMPLETE (cause, true );
1886+ if (wait_full_mark_finished (cause,
1887+ old_marking_started_before,
1888+ old_marking_started_after,
1889+ old_marking_completed_after)) {
17991890 return true ;
18001891 }
18011892
1802- if (old_marking_started_after != old_marking_completed_after) {
1803- // If there is an in-progress cycle (possibly started by us), then
1804- // wait for that cycle to complete, e.g.
1805- // while completed_now < started_after.
1806- LOG_COLLECT_CONCURRENTLY (cause, " wait" );
1807- MonitorLocker ml (G1OldGCCount_lock);
1808- while (gc_counter_less_than (_old_marking_cycles_completed,
1809- old_marking_started_after)) {
1810- ml.wait ();
1811- }
1812- // Request is finished if the collection we just waited for was
1813- // started after this request.
1814- if (old_marking_started_before != old_marking_started_after) {
1815- LOG_COLLECT_CONCURRENTLY (cause, " complete after wait" );
1816- return true ;
1817- }
1818- }
1819-
18201893 // If VMOp was successful then it started a new cycle that the above
18211894 // wait &etc should have recognized as finishing this request. This
18221895 // differs from a non-user-request, where gc_succeeded does not imply
18231896 // a new cycle was started.
18241897 assert (!op.gc_succeeded (), " invariant" );
18251898
1826- if (op.cycle_already_in_progress ()) {
1827- // If VMOp failed because a cycle was already in progress, it
1828- // is now complete. But it didn't finish this user-requested
1829- // GC, so try again.
1830- LOG_COLLECT_CONCURRENTLY (cause, " retry after in-progress" );
1831- continue ;
1832- } else if (op.whitebox_attached ()) {
1833- // If WhiteBox wants control, wait for notification of a state
1834- // change in the controller, then try again. Don't wait for
1835- // release of control, since collections may complete while in
1836- // control. Note: This won't recognize a STW full collection
1837- // while waiting; we can't wait on multiple monitors.
1838- LOG_COLLECT_CONCURRENTLY (cause, " whitebox control stall" );
1839- MonitorLocker ml (ConcurrentGCBreakpoints::monitor ());
1840- if (ConcurrentGCBreakpoints::is_controlled ()) {
1841- ml.wait ();
1842- }
1899+ if (should_retry_vm_op (cause, &op)) {
18431900 continue ;
18441901 }
18451902 }
0 commit comments