Skip to content

Commit a49118a

Browse files
committed
Do not copy or age young objects in a full GC immediately following an incremental GC.
1 parent 1b30367 commit a49118a

File tree

3 files changed

+37
-22
lines changed

3 files changed

+37
-22
lines changed

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -231,31 +231,30 @@ private boolean collectImpl(GCCause cause, boolean forceFullGC) {
231231
private boolean doCollectImpl(GCCause cause, boolean forceFullGC) {
232232
CommittedMemoryProvider.get().beforeGarbageCollection();
233233

234-
completeCollection = forceFullGC || policy.shouldCollectCompletely(false);
235-
boolean outOfMemory = doCollectOnce(cause);
236-
if (!completeCollection && (outOfMemory || policy.shouldCollectCompletely(true))) {
237-
completeCollection = true;
238-
outOfMemory = doCollectOnce(cause);
234+
boolean incremental = HeapParameters.Options.CollectYoungGenerationSeparately.getValue() ||
235+
(!forceFullGC && !policy.shouldCollectCompletely(false));
236+
boolean outOfMemory = false;
237+
if (incremental) {
238+
outOfMemory = doCollectOnce(cause, false, false);
239+
}
240+
if (!incremental || outOfMemory || forceFullGC || policy.shouldCollectCompletely(true)) {
241+
outOfMemory = doCollectOnce(cause, true, incremental);
239242
}
240243

241-
CommittedMemoryProvider.get().afterGarbageCollection(completeCollection);
244+
CommittedMemoryProvider.get().afterGarbageCollection();
242245
return outOfMemory;
243246
}
244247

245-
private boolean doCollectOnce(GCCause cause) {
248+
private boolean doCollectOnce(GCCause cause, boolean complete, boolean followsIncremental) {
249+
assert !followsIncremental || complete : "An incremental collection cannot be followed by another incremental collection";
250+
completeCollection = complete;
251+
246252
accounting.beforeCollection();
247253
policy.onCollectionBegin(completeCollection);
248254

249255
Timer collectionTimer = timers.collection.open();
250256
try {
251-
if (completeCollection) {
252-
if (HeapParameters.Options.CollectYoungGenerationSeparately.getValue()) {
253-
scavenge(true);
254-
}
255-
scavenge(false);
256-
} else {
257-
scavenge(true);
258-
}
257+
scavenge(!complete, followsIncremental);
259258
} finally {
260259
collectionTimer.close();
261260
}
@@ -487,15 +486,15 @@ public boolean isCompleteCollection() {
487486
}
488487

489488
/** Scavenge, either from dirty roots or from all roots, and process discovered references. */
490-
private void scavenge(boolean fromDirtyRoots) {
489+
private void scavenge(boolean incremental, boolean followingIncremental) {
491490
GreyToBlackObjRefVisitor.Counters counters = greyToBlackObjRefVisitor.openCounters();
492491
try {
493492
Timer rootScanTimer = timers.rootScan.open();
494493
try {
495-
if (fromDirtyRoots) {
494+
if (incremental) {
496495
cheneyScanFromDirtyRoots();
497496
} else {
498-
cheneyScanFromRoots();
497+
cheneyScanFromRoots(followingIncremental);
499498
}
500499
} finally {
501500
rootScanTimer.close();
@@ -561,7 +560,7 @@ private void cleanRuntimeCodeCache() {
561560
}
562561
}
563562

564-
private void cheneyScanFromRoots() {
563+
private void cheneyScanFromRoots(boolean followingIncremental) {
565564
Timer cheneyScanFromRootsTimer = timers.cheneyScanFromRoots.open();
566565
try {
567566
/* Take a snapshot of the heap so that I can visit all the promoted Objects. */
@@ -572,6 +571,15 @@ private void cheneyScanFromRoots() {
572571
*/
573572
prepareForPromotion();
574573

574+
if (followingIncremental) {
575+
/*
576+
* We just finished an incremental collection, so we will not be able to reclaim any
577+
* young objects and do not need to copy them (and do not want to age or tenure them
578+
* in the process). We still need to scan them for roots into the old generation.
579+
*/
580+
HeapImpl.getHeapImpl().getYoungGeneration().emptyFromSpacesIntoToSpaces();
581+
}
582+
575583
/*
576584
* Make sure all chunks with pinned objects are in toSpace, and any formerly pinned
577585
* objects are in fromSpace.

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGeneration.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ void swapSpaces() {
148148
assert survivorsToSpacesAccounting.getChunkBytes().equal(0);
149149
}
150150

151+
void emptyFromSpacesIntoToSpaces() {
152+
assert getEden().isEmpty() && getEden().getChunkBytes().equal(0) : "Eden must be empty.";
153+
assert survivorsToSpacesAccounting.getChunkBytes().equal(0) : "Survivor to-spaces must be empty";
154+
for (int i = 0; i < maxSurvivorSpaces; i++) {
155+
assert getSurvivorToSpaceAt(i).isEmpty() && getSurvivorToSpaceAt(i).getChunkBytes().equal(0) : "Survivor to-space must be empty.";
156+
getSurvivorToSpaceAt(i).absorb(getSurvivorFromSpaceAt(i));
157+
}
158+
}
159+
151160
boolean walkHeapChunks(MemoryWalker.Visitor visitor) {
152161
if (getEden().walkHeapChunks(visitor)) {
153162
for (int i = 0; i < maxSurvivorSpaces; i++) {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/CommittedMemoryProvider.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,8 @@ default void beforeGarbageCollection() {
124124
/**
125125
* Called by the garbage collector after a collection has ended, as an opportunity to perform
126126
* lazy operations, sanity checks or clean-ups.
127-
*
128-
* @param completeCollection Whether the garbage collector has performed a full collection.
129127
*/
130-
default void afterGarbageCollection(boolean completeCollection) {
128+
default void afterGarbageCollection() {
131129
}
132130

133131
enum Access {

0 commit comments

Comments
 (0)