@@ -1732,6 +1732,66 @@ static bool gc_counter_less_than(uint x, uint y) {
1732
1732
#define LOG_COLLECT_CONCURRENTLY_COMPLETE (cause, result ) \
1733
1733
LOG_COLLECT_CONCURRENTLY (cause, " complete %s" , BOOL_TO_STR(result))
1734
1734
1735
+ bool G1CollectedHeap::wait_full_mark_finished(GCCause::Cause cause,
1736
+ uint old_marking_started_before,
1737
+ uint old_marking_started_after,
1738
+ uint old_marking_completed_after) {
1739
+ // Request is finished if a full collection (concurrent or stw)
1740
+ // was started after this request and has completed, e.g.
1741
+ // started_before < completed_after.
1742
+ if (gc_counter_less_than (old_marking_started_before,
1743
+ old_marking_completed_after)) {
1744
+ LOG_COLLECT_CONCURRENTLY_COMPLETE (cause, true );
1745
+ return true ;
1746
+ }
1747
+
1748
+ if (old_marking_started_after != old_marking_completed_after) {
1749
+ // If there is an in-progress cycle (possibly started by us), then
1750
+ // wait for that cycle to complete, e.g.
1751
+ // while completed_now < started_after.
1752
+ LOG_COLLECT_CONCURRENTLY (cause, " wait" );
1753
+ MonitorLocker ml (G1OldGCCount_lock);
1754
+ while (gc_counter_less_than (_old_marking_cycles_completed,
1755
+ old_marking_started_after)) {
1756
+ ml.wait ();
1757
+ }
1758
+ // Request is finished if the collection we just waited for was
1759
+ // started after this request.
1760
+ if (old_marking_started_before != old_marking_started_after) {
1761
+ LOG_COLLECT_CONCURRENTLY (cause, " complete after wait" );
1762
+ return true ;
1763
+ }
1764
+ }
1765
+ return false ;
1766
+ }
1767
+
1768
+ // After calling wait_full_mark_finished(), this method determines whether we
1769
+ // previously failed for ordinary reasons (concurrent cycle in progress, whitebox
1770
+ // has control). Returns if this has been such an ordinary reason.
1771
+ static bool should_retry_vm_op (GCCause::Cause cause,
1772
+ VM_G1TryInitiateConcMark* op) {
1773
+ if (op->cycle_already_in_progress ()) {
1774
+ // If VMOp failed because a cycle was already in progress, it
1775
+ // is now complete. But it didn't finish this user-requested
1776
+ // GC, so try again.
1777
+ LOG_COLLECT_CONCURRENTLY (cause, " retry after in-progress" );
1778
+ return true ;
1779
+ } else if (op->whitebox_attached ()) {
1780
+ // If WhiteBox wants control, wait for notification of a state
1781
+ // change in the controller, then try again. Don't wait for
1782
+ // release of control, since collections may complete while in
1783
+ // control. Note: This won't recognize a STW full collection
1784
+ // while waiting; we can't wait on multiple monitors.
1785
+ LOG_COLLECT_CONCURRENTLY (cause, " whitebox control stall" );
1786
+ MonitorLocker ml (ConcurrentGCBreakpoints::monitor ());
1787
+ if (ConcurrentGCBreakpoints::is_controlled ()) {
1788
+ ml.wait ();
1789
+ }
1790
+ return true ;
1791
+ }
1792
+ return false ;
1793
+ }
1794
+
1735
1795
bool G1CollectedHeap::try_collect_concurrently (GCCause::Cause cause,
1736
1796
uint gc_counter,
1737
1797
uint old_marking_started_before) {
@@ -1792,7 +1852,45 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause,
1792
1852
LOG_COLLECT_CONCURRENTLY (cause, " ignoring STW full GC" );
1793
1853
old_marking_started_before = old_marking_started_after;
1794
1854
}
1855
+ } else if (GCCause::is_codecache_requested_gc (cause)) {
1856
+ // For a CodeCache requested GC, before marking, progress is ensured as the
1857
+ // following Remark pause unloads code (and signals the requester such).
1858
+ // Otherwise we must ensure that it is restarted.
1859
+ //
1860
+ // For a CodeCache requested GC, a successful GC operation means that
1861
+ // (1) marking is in progress. I.e. the VMOp started the marking or a
1862
+ // Remark pause is pending from a different VM op; we will potentially
1863
+ // abort a mixed phase if needed.
1864
+ // (2) a new cycle was started (by this thread or some other), or
1865
+ // (3) a Full GC was performed.
1866
+ //
1867
+ // Cases (2) and (3) are detected together by a change to
1868
+ // _old_marking_cycles_started.
1869
+ //
1870
+ // Compared to other "automatic" GCs (see below), we do not consider being
1871
+ // in whitebox as sufficient too because we might be anywhere within that
1872
+ // cycle and we need to make progress.
1873
+ if (op.mark_in_progress () ||
1874
+ (old_marking_started_before != old_marking_started_after)) {
1875
+ LOG_COLLECT_CONCURRENTLY_COMPLETE (cause, true );
1876
+ return true ;
1877
+ }
1878
+
1879
+ if (wait_full_mark_finished (cause,
1880
+ old_marking_started_before,
1881
+ old_marking_started_after,
1882
+ old_marking_completed_after)) {
1883
+ return true ;
1884
+ }
1885
+
1886
+ if (should_retry_vm_op (cause, &op)) {
1887
+ continue ;
1888
+ }
1795
1889
} else if (!GCCause::is_user_requested_gc (cause)) {
1890
+ assert (cause == GCCause::_g1_humongous_allocation ||
1891
+ cause == GCCause::_g1_periodic_collection,
1892
+ " Unsupported cause %s" , GCCause::to_string (cause));
1893
+
1796
1894
// For an "automatic" (not user-requested) collection, we just need to
1797
1895
// ensure that progress is made.
1798
1896
//
@@ -1804,11 +1902,6 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause,
1804
1902
// (5) a Full GC was performed.
1805
1903
// Cases (4) and (5) are detected together by a change to
1806
1904
// _old_marking_cycles_started.
1807
- //
1808
- // Note that (1) does not imply (4). If we're still in the mixed
1809
- // phase of an earlier concurrent collection, the request to make the
1810
- // collection a concurrent start won't be honored. If we don't check for
1811
- // both conditions we'll spin doing back-to-back collections.
1812
1905
if (op.gc_succeeded () ||
1813
1906
op.cycle_already_in_progress () ||
1814
1907
op.whitebox_attached () ||
@@ -1832,56 +1925,20 @@ bool G1CollectedHeap::try_collect_concurrently(GCCause::Cause cause,
1832
1925
BOOL_TO_STR (op.gc_succeeded ()),
1833
1926
old_marking_started_before, old_marking_started_after);
1834
1927
1835
- // Request is finished if a full collection (concurrent or stw)
1836
- // was started after this request and has completed, e.g.
1837
- // started_before < completed_after.
1838
- if (gc_counter_less_than (old_marking_started_before,
1839
- old_marking_completed_after)) {
1840
- LOG_COLLECT_CONCURRENTLY_COMPLETE (cause, true );
1928
+ if (wait_full_mark_finished (cause,
1929
+ old_marking_started_before,
1930
+ old_marking_started_after,
1931
+ old_marking_completed_after)) {
1841
1932
return true ;
1842
1933
}
1843
1934
1844
- if (old_marking_started_after != old_marking_completed_after) {
1845
- // If there is an in-progress cycle (possibly started by us), then
1846
- // wait for that cycle to complete, e.g.
1847
- // while completed_now < started_after.
1848
- LOG_COLLECT_CONCURRENTLY (cause, " wait" );
1849
- MonitorLocker ml (G1OldGCCount_lock);
1850
- while (gc_counter_less_than (_old_marking_cycles_completed,
1851
- old_marking_started_after)) {
1852
- ml.wait ();
1853
- }
1854
- // Request is finished if the collection we just waited for was
1855
- // started after this request.
1856
- if (old_marking_started_before != old_marking_started_after) {
1857
- LOG_COLLECT_CONCURRENTLY (cause, " complete after wait" );
1858
- return true ;
1859
- }
1860
- }
1861
-
1862
1935
// If VMOp was successful then it started a new cycle that the above
1863
1936
// wait &etc should have recognized as finishing this request. This
1864
1937
// differs from a non-user-request, where gc_succeeded does not imply
1865
1938
// a new cycle was started.
1866
1939
assert (!op.gc_succeeded (), " invariant" );
1867
1940
1868
- if (op.cycle_already_in_progress ()) {
1869
- // If VMOp failed because a cycle was already in progress, it
1870
- // is now complete. But it didn't finish this user-requested
1871
- // GC, so try again.
1872
- LOG_COLLECT_CONCURRENTLY (cause, " retry after in-progress" );
1873
- continue ;
1874
- } else if (op.whitebox_attached ()) {
1875
- // If WhiteBox wants control, wait for notification of a state
1876
- // change in the controller, then try again. Don't wait for
1877
- // release of control, since collections may complete while in
1878
- // control. Note: This won't recognize a STW full collection
1879
- // while waiting; we can't wait on multiple monitors.
1880
- LOG_COLLECT_CONCURRENTLY (cause, " whitebox control stall" );
1881
- MonitorLocker ml (ConcurrentGCBreakpoints::monitor ());
1882
- if (ConcurrentGCBreakpoints::is_controlled ()) {
1883
- ml.wait ();
1884
- }
1941
+ if (should_retry_vm_op (cause, &op)) {
1885
1942
continue ;
1886
1943
}
1887
1944
}
0 commit comments