Skip to content

Commit 762ce84

Browse files
committed
Populate first object table during planning.
1 parent 05ac3b3 commit 762ce84

File tree

5 files changed

+64
-36
lines changed

5 files changed

+64
-36
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ private void compact(Timers timers) {
407407
* chunk during compaction. The remembered set bits are already set after planning.
408408
*/
409409
if (!AlignedHeapChunk.isEmpty(chunk)) {
410-
RememberedSet.get().enableRememberedSetForChunk(chunk);
410+
RememberedSet.get().clearRememberedSet(chunk);
411411
} // empty chunks will be freed or reset before reuse, no need to reinitialize here
412412

413413
chunk = HeapChunk.getNext(chunk);

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ private Object copyAlignedObject(Object originalObj) {
449449
if (SerialGCOptions.useCompactingOldGen() && GCImpl.getGCImpl().isCompleteCollection()) {
450450
/*
451451
* In a compacting complete collection, the remembered set bit is set already during
452-
* marking and the first object table is built later during compaction.
452+
* marking and the first object table is built during planning.
453453
*/
454454
} else {
455455
/*

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/compacting/PlanningVisitor.java

+46-19
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
import com.oracle.svm.core.genscavenge.HeapChunk;
3535
import com.oracle.svm.core.genscavenge.ObjectHeaderImpl;
3636
import com.oracle.svm.core.genscavenge.Space;
37+
import com.oracle.svm.core.genscavenge.remset.AlignedChunkRememberedSet;
3738
import com.oracle.svm.core.genscavenge.remset.BrickTable;
39+
import com.oracle.svm.core.genscavenge.remset.FirstObjectTable;
3840
import com.oracle.svm.core.hub.LayoutEncoding;
3941

4042
import jdk.graal.compiler.word.Word;
@@ -56,6 +58,9 @@ public PlanningVisitor() {
5658
public void init(Space space) {
5759
allocChunk = space.getFirstAlignedHeapChunk();
5860
allocPointer = AlignedHeapChunk.getObjectsStart(allocChunk);
61+
if (!allocChunk.getShouldSweepInsteadOfCompact()) {
62+
FirstObjectTable.initializeTable(AlignedChunkRememberedSet.getFirstObjectTableStart(allocChunk), AlignedChunkRememberedSet.getFirstObjectTableSize());
63+
}
5964
}
6065

6166
@Override
@@ -69,7 +74,7 @@ public boolean visitChunk(AlignedHeapChunk.AlignedHeader chunk) {
6974
UnsignedWord brickIndex = Word.zero();
7075

7176
/* Initialize the move info structure at the chunk's object start location. */
72-
ObjectMoveInfo.setNewAddress(objSeq, allocPointer);
77+
ObjectMoveInfo.setNewAddress(objSeq, objSeq);
7378
ObjectMoveInfo.setObjectSeqSize(objSeq, Word.zero());
7479
ObjectMoveInfo.setNextObjectSeqOffset(objSeq, Word.zero());
7580

@@ -115,12 +120,43 @@ public boolean visitChunk(AlignedHeapChunk.AlignedHeader chunk) {
115120
}
116121

117122
objSeqSize = objSeqSize.add(objSize);
123+
if (!sweeping) {
124+
if (allocPointer.add(objSeqSize).aboveThan(AlignedHeapChunk.getObjectsEnd(allocChunk))) {
125+
/* Out of space, move to the start of the next chunk. */
126+
allocChunk = HeapChunk.getNext(allocChunk);
127+
assert allocChunk.isNonNull();
128+
assert !allocChunk.getShouldSweepInsteadOfCompact();
129+
allocPointer = AlignedHeapChunk.getObjectsStart(allocChunk);
130+
131+
/*
132+
* TODO: we should reset the FOT entries we already wrote in the last chunk
133+
* (but they should not be accessed, not even by heap verification)
134+
*/
135+
136+
/* Visit previous objects in sequence again to write new FOT entries. */
137+
FirstObjectTable.initializeTable(AlignedChunkRememberedSet.getFirstObjectTableStart(allocChunk), AlignedChunkRememberedSet.getFirstObjectTableSize());
138+
Pointer q = objSeq;
139+
while (q.notEqual(p)) {
140+
UnsignedWord offset = q.subtract(objSeq);
141+
UnsignedWord size = LayoutEncoding.getSizeFromObjectInlineInGC(q.toObject());
142+
FirstObjectTable.setTableForObject(AlignedChunkRememberedSet.getFirstObjectTableStart(allocChunk), offset, offset.add(size));
143+
q = q.add(size);
144+
}
145+
}
146+
147+
Pointer allocEndOffset = allocPointer.add(objSeqSize).subtract(AlignedHeapChunk.getObjectsStart(allocChunk));
148+
FirstObjectTable.setTableForObject(AlignedChunkRememberedSet.getFirstObjectTableStart(allocChunk), allocEndOffset.subtract(objSize), allocEndOffset);
149+
}
118150

119151
} else { // not marked, i.e. not alive and start of a gap of yet unknown size
120152
if (objSeqSize.notEqual(0)) { // end of an object sequence
121-
Pointer newAddress = sweeping ? objSeq : allocate(objSeqSize);
122-
ObjectMoveInfo.setNewAddress(objSeq, newAddress);
123153
ObjectMoveInfo.setObjectSeqSize(objSeq, objSeqSize);
154+
if (sweeping) {
155+
ObjectMoveInfo.setNewAddress(objSeq, objSeq);
156+
} else {
157+
ObjectMoveInfo.setNewAddress(objSeq, allocPointer);
158+
allocPointer = allocPointer.add(objSeqSize); // ensured enough memory above
159+
}
124160

125161
objSeqSize = Word.zero();
126162

@@ -139,10 +175,15 @@ public boolean visitChunk(AlignedHeapChunk.AlignedHeader chunk) {
139175

140176
if (gapSize.notEqual(0)) { // truncate gap at chunk end
141177
chunk.setTopOffset(chunk.getTopOffset().subtract(gapSize));
178+
142179
} else if (objSeqSize.notEqual(0)) {
143-
Pointer newAddress = sweeping ? objSeq : allocate(objSeqSize);
144-
ObjectMoveInfo.setNewAddress(objSeq, newAddress);
145180
ObjectMoveInfo.setObjectSeqSize(objSeq, objSeqSize);
181+
if (sweeping) {
182+
ObjectMoveInfo.setNewAddress(objSeq, objSeq);
183+
} else {
184+
ObjectMoveInfo.setNewAddress(objSeq, allocPointer);
185+
allocPointer = allocPointer.add(objSeqSize); // ensured enough memory above
186+
}
146187
}
147188

148189
if (sweeping) {
@@ -168,18 +209,4 @@ public boolean visitChunk(AlignedHeapChunk.AlignedHeader chunk) {
168209

169210
return true;
170211
}
171-
172-
private Pointer allocate(UnsignedWord size) {
173-
Pointer p = allocPointer;
174-
allocPointer = allocPointer.add(size);
175-
if (allocPointer.aboveThan(AlignedHeapChunk.getObjectsEnd(allocChunk))) {
176-
allocChunk = HeapChunk.getNext(allocChunk);
177-
assert allocChunk.isNonNull();
178-
assert !allocChunk.getShouldSweepInsteadOfCompact();
179-
180-
p = AlignedHeapChunk.getObjectsStart(allocChunk);
181-
allocPointer = p.add(size);
182-
}
183-
return p;
184-
}
185212
}

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/AlignedChunkRememberedSet.java

+11-11
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
import jdk.graal.compiler.replacements.nodes.AssertionNode;
5454
import jdk.graal.compiler.word.Word;
5555

56-
final class AlignedChunkRememberedSet {
56+
public final class AlignedChunkRememberedSet {
5757
private AlignedChunkRememberedSet() {
5858
}
5959

@@ -63,7 +63,7 @@ public static int wordSize() {
6363
}
6464

6565
@Fold
66-
public static UnsignedWord getHeaderSize() {
66+
static UnsignedWord getHeaderSize() {
6767
UnsignedWord headerSize = getFirstObjectTableLimitOffset();
6868
if (SerialGCOptions.useCompactingOldGen()) {
6969
// Compaction needs room for a ObjectMoveInfo structure before the first object.
@@ -74,7 +74,7 @@ public static UnsignedWord getHeaderSize() {
7474
}
7575

7676
@Platforms(Platform.HOSTED_ONLY.class)
77-
public static void enableRememberedSet(HostedByteBufferPointer chunk, int chunkPosition, List<ImageHeapObject> objects) {
77+
static void enableRememberedSet(HostedByteBufferPointer chunk, int chunkPosition, List<ImageHeapObject> objects) {
7878
// Completely clean the card table and the first object table.
7979
CardTable.cleanTable(getCardTableStart(chunk), getCardTableSize());
8080
FirstObjectTable.initializeTable(getFirstObjectTableStart(chunk), getFirstObjectTableSize());
@@ -94,7 +94,7 @@ public static void enableRememberedSet(HostedByteBufferPointer chunk, int chunkP
9494

9595
@AlwaysInline("GC performance")
9696
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
97-
public static void enableRememberedSetForObject(AlignedHeader chunk, Object obj, UnsignedWord objSize) {
97+
static void enableRememberedSetForObject(AlignedHeader chunk, Object obj, UnsignedWord objSize) {
9898
Pointer fotStart = getFirstObjectTableStart(chunk);
9999
Pointer objectsStart = AlignedHeapChunk.getObjectsStart(chunk);
100100

@@ -107,7 +107,7 @@ public static void enableRememberedSetForObject(AlignedHeader chunk, Object obj,
107107
}
108108

109109
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
110-
public static void enableRememberedSet(AlignedHeader chunk) {
110+
static void enableRememberedSet(AlignedHeader chunk) {
111111
// Completely clean the card table and the first object table as further objects may be
112112
// added later on to this chunk.
113113
CardTable.cleanTable(getCardTableStart(chunk), getCardTableSize());
@@ -124,7 +124,7 @@ public static void enableRememberedSet(AlignedHeader chunk) {
124124
}
125125

126126
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
127-
public static void clearRememberedSet(AlignedHeader chunk) {
127+
static void clearRememberedSet(AlignedHeader chunk) {
128128
CardTable.cleanTable(getCardTableStart(chunk), getCardTableSize());
129129
}
130130

@@ -133,7 +133,7 @@ public static void clearRememberedSet(AlignedHeader chunk) {
133133
* the post-write barrier.
134134
*/
135135
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
136-
public static void dirtyCardForObject(Object object, boolean verifyOnly) {
136+
static void dirtyCardForObject(Object object, boolean verifyOnly) {
137137
Pointer objectPointer = Word.objectToUntrackedPointer(object);
138138
AlignedHeader chunk = AlignedHeapChunk.getEnclosingChunkFromObjectPointer(objectPointer);
139139
Pointer cardTableStart = getCardTableStart(chunk);
@@ -146,7 +146,7 @@ public static void dirtyCardForObject(Object object, boolean verifyOnly) {
146146
}
147147

148148
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
149-
public static void walkDirtyObjects(AlignedHeader chunk, UninterruptibleObjectVisitor visitor, boolean clean) {
149+
static void walkDirtyObjects(AlignedHeader chunk, UninterruptibleObjectVisitor visitor, boolean clean) {
150150
Pointer objectsStart = AlignedHeapChunk.getObjectsStart(chunk);
151151
Pointer objectsLimit = HeapChunk.getTopPointer(chunk);
152152
UnsignedWord memorySize = objectsLimit.subtract(objectsStart);
@@ -212,7 +212,7 @@ private static void walkObjects(AlignedHeader chunk, Pointer start, Pointer end,
212212
}
213213
}
214214

215-
public static boolean verify(AlignedHeader chunk) {
215+
static boolean verify(AlignedHeader chunk) {
216216
boolean success = true;
217217
success &= CardTable.verify(getCardTableStart(chunk), getCardTableEnd(chunk), AlignedHeapChunk.getObjectsStart(chunk), HeapChunk.getTopPointer(chunk));
218218
success &= FirstObjectTable.verify(getFirstObjectTableStart(chunk), AlignedHeapChunk.getObjectsStart(chunk), HeapChunk.getTopPointer(chunk));
@@ -242,7 +242,7 @@ static UnsignedWord getCardTableSize() {
242242
}
243243

244244
@Fold
245-
static UnsignedWord getFirstObjectTableSize() {
245+
public static UnsignedWord getFirstObjectTableSize() {
246246
return getCardTableSize();
247247
}
248248

@@ -294,7 +294,7 @@ private static Pointer getCardTableEnd(AlignedHeader chunk) {
294294
}
295295

296296
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
297-
private static Pointer getFirstObjectTableStart(AlignedHeader chunk) {
297+
public static Pointer getFirstObjectTableStart(AlignedHeader chunk) {
298298
return getFirstObjectTableStart(HeapChunk.asPointer(chunk));
299299
}
300300

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/FirstObjectTable.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
*/
2525
package com.oracle.svm.core.genscavenge.remset;
2626

27-
import jdk.graal.compiler.word.Word;
2827
import org.graalvm.word.Pointer;
2928
import org.graalvm.word.UnsignedWord;
3029

@@ -37,6 +36,8 @@
3736
import com.oracle.svm.core.log.Log;
3837
import com.oracle.svm.core.util.UnsignedUtils;
3938

39+
import jdk.graal.compiler.word.Word;
40+
4041
/**
4142
* A "first object table" to tell me the start of the first object that crosses onto a card
4243
* remembered set memory region.
@@ -109,7 +110,7 @@
109110
* <p>
110111
* Implementation note: Table entries are bytes but converted to and from ints with bounds checks.
111112
*/
112-
final class FirstObjectTable {
113+
public final class FirstObjectTable {
113114
/**
114115
* The number of bytes of memory covered by an entry. Since the indexes into the CardTable are
115116
* used to index into the FirstObjectTable, these need to have the same value.
@@ -237,7 +238,7 @@ public static void setTableForObject(Pointer table, UnsignedWord startOffset, Un
237238
*/
238239
@AlwaysInline("GC performance")
239240
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
240-
public static Pointer getFirstObjectImprecise(Pointer tableStart, Pointer objectsStart, UnsignedWord index) {
241+
static Pointer getFirstObjectImprecise(Pointer tableStart, Pointer objectsStart, UnsignedWord index) {
241242
Pointer result;
242243
Pointer firstObject = getFirstObject(tableStart, objectsStart, index);
243244
Pointer indexedMemoryStart = objectsStart.add(indexToMemoryOffset(index));
@@ -295,7 +296,7 @@ private static UnsignedWord entryToMemoryOffset(UnsignedWord index, int entry) {
295296
return indexOffset.subtract(entryOffset);
296297
}
297298

298-
public static boolean verify(Pointer tableStart, Pointer objectsStart, Pointer objectsLimit) {
299+
static boolean verify(Pointer tableStart, Pointer objectsStart, Pointer objectsLimit) {
299300
UnsignedWord indexLimit = getTableSizeForMemoryRange(objectsStart, objectsLimit);
300301
for (UnsignedWord index = Word.unsigned(0); index.belowThan(indexLimit); index = index.add(1)) {
301302
Pointer objStart = getFirstObject(tableStart, objectsStart, index);

0 commit comments

Comments
 (0)