Skip to content

Commit 8f76090

Browse files
author
Thomas Schrott
committed
[GR-34010] Use precise write barriers for Object arrays.
PullRequest: graal/19959
2 parents 02bddd8 + f730ca3 commit 8f76090

28 files changed

+830
-204
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/gc/WriteBarrierSnippets.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ protected static void verifyNotArray(Object object) {
6262
}
6363
}
6464

65-
protected static Word getPointerToFirstArrayElement(Word address, long length, int elementStride) {
65+
public static Word getPointerToFirstArrayElement(Word address, long length, int elementStride) {
6666
long result = address.rawValue();
6767
if (probability(NOT_LIKELY_PROBABILITY, elementStride < 0)) {
6868
// the address points to the place after the last array element
@@ -71,7 +71,7 @@ protected static Word getPointerToFirstArrayElement(Word address, long length, i
7171
return Word.unsigned(result);
7272
}
7373

74-
protected static Word getPointerToLastArrayElement(Word address, long length, int elementStride) {
74+
public static Word getPointerToLastArrayElement(Word address, long length, int elementStride) {
7575
long result = address.rawValue();
7676
if (probability(NOT_LIKELY_PROBABILITY, elementStride < 0)) {
7777
// the address points to the place after the last array element

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
import java.util.ArrayList;
2828
import java.util.List;
2929

30-
import org.graalvm.word.UnsignedWord;
31-
3230
import com.oracle.svm.core.config.ConfigurationValues;
3331
import com.oracle.svm.core.image.ImageHeap;
3432
import com.oracle.svm.core.image.ImageHeapObject;
@@ -78,14 +76,21 @@ public boolean isWritable() {
7876
}
7977

8078
static final class UnalignedChunk extends Chunk {
81-
UnalignedChunk(long begin, long endOffset, boolean writable) {
79+
private final long objectSize;
80+
81+
UnalignedChunk(long begin, long endOffset, boolean writable, long objectSize) {
8282
super(begin, endOffset, writable);
83+
this.objectSize = objectSize;
8384
}
8485

8586
@Override
8687
public long getTopOffset() {
8788
return getEndOffset();
8889
}
90+
91+
public long getObjectSize() {
92+
return objectSize;
93+
}
8994
}
9095

9196
final class AlignedChunk extends Chunk {
@@ -162,7 +167,6 @@ public long getUnallocatedBytes() {
162167
private final int alignedChunkSize;
163168
private final int alignedChunkAlignment;
164169
private final int alignedChunkObjectsOffset;
165-
private final int unalignedChunkObjectsOffset;
166170

167171
private long position;
168172

@@ -177,7 +181,6 @@ public long getUnallocatedBytes() {
177181
this.alignedChunkSize = UnsignedUtils.safeToInt(HeapParameters.getAlignedHeapChunkSize());
178182
this.alignedChunkAlignment = UnsignedUtils.safeToInt(HeapParameters.getAlignedHeapChunkAlignment());
179183
this.alignedChunkObjectsOffset = UnsignedUtils.safeToInt(AlignedHeapChunk.getObjectsStartOffset());
180-
this.unalignedChunkObjectsOffset = UnsignedUtils.safeToInt(UnalignedHeapChunk.getObjectStartOffset());
181184

182185
this.position = position;
183186

@@ -196,11 +199,11 @@ public void alignBetweenChunks(int multiple) {
196199

197200
public long allocateUnalignedChunkForObject(ImageHeapObject obj, boolean writable) {
198201
assert currentAlignedChunk == null;
199-
UnsignedWord objSize = Word.unsigned(obj.getSize());
200-
long chunkSize = UnalignedHeapChunk.getChunkSizeForObject(objSize).rawValue();
202+
long objSize = obj.getSize();
203+
long chunkSize = UnalignedHeapChunk.getChunkSizeForObject(Word.unsigned(objSize)).rawValue();
201204
long chunkBegin = allocateRaw(chunkSize);
202-
unalignedChunks.add(new UnalignedChunk(chunkBegin, chunkSize, writable));
203-
return chunkBegin + unalignedChunkObjectsOffset;
205+
unalignedChunks.add(new UnalignedChunk(chunkBegin, chunkSize, writable, objSize));
206+
return chunkBegin + UnsignedUtils.safeToInt(UnalignedHeapChunk.calculateObjectStartOffset(Word.unsigned(objSize)));
204207
}
205208

206209
public void maybeStartAlignedChunk() {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,9 @@ private static void writeHeader(ImageHeapChunkWriter writer, Chunk previous, Chu
243243
writer.initializeAlignedChunk(chunkPosition, current.getTopOffset(), current.getEndOffset(), offsetToPrevious, offsetToNext);
244244
writer.enableRememberedSetForAlignedChunk(chunkPosition, aligned.getObjects());
245245
} else {
246-
assert current instanceof UnalignedChunk;
247-
writer.initializeUnalignedChunk(chunkPosition, current.getTopOffset(), current.getEndOffset(), offsetToPrevious, offsetToNext);
248-
writer.enableRememberedSetForUnalignedChunk(chunkPosition);
246+
UnalignedChunk unalignedChunk = (UnalignedChunk) current;
247+
writer.initializeUnalignedChunk(chunkPosition, current.getTopOffset(), current.getEndOffset(), offsetToPrevious, offsetToNext, unalignedChunk.getObjectSize());
248+
writer.enableRememberedSetForUnalignedChunk(chunkPosition, unalignedChunk.getObjectSize());
249249
}
250250
}
251251
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ void appendChunk(AlignedHeapChunk.AlignedHeader hdr) {
148148

149149
@Override
150150
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
151-
void blackenDirtyCardRoots(GreyToBlackObjectVisitor visitor) {
152-
RememberedSet.get().walkDirtyObjects(space.getFirstAlignedHeapChunk(), space.getFirstUnalignedHeapChunk(), Word.nullPointer(), visitor, true);
151+
void blackenDirtyCardRoots(GreyToBlackObjectVisitor visitor, GreyToBlackObjRefVisitor refVisitor) {
152+
RememberedSet.get().walkDirtyObjects(space.getFirstAlignedHeapChunk(), space.getFirstUnalignedHeapChunk(), Word.nullPointer(), visitor, refVisitor, true);
153153
}
154154

155155
@Override
@@ -350,7 +350,7 @@ private void fixupReferencesBeforeCompaction(ChunkReleaser chunkReleaser, Timers
350350
private void fixupImageHeapRoots(ImageHeapInfo info) {
351351
if (HeapImpl.usesImageHeapCardMarking()) {
352352
// Note that cards have already been cleaned and roots re-marked during the initial scan
353-
GCImpl.walkDirtyImageHeapChunkRoots(info, fixupVisitor, false);
353+
GCImpl.walkDirtyImageHeapChunkRoots(info, fixupVisitor, refFixupVisitor, false);
354354
} else {
355355
GCImpl.walkImageHeapRoots(info, fixupVisitor);
356356
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ void swapSpaces() {
159159

160160
@Override
161161
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
162-
void blackenDirtyCardRoots(GreyToBlackObjectVisitor visitor) {
163-
RememberedSet.get().walkDirtyObjects(toSpace.getFirstAlignedHeapChunk(), toSpace.getFirstUnalignedHeapChunk(), Word.nullPointer(), visitor, true);
162+
void blackenDirtyCardRoots(GreyToBlackObjectVisitor visitor, GreyToBlackObjRefVisitor refVisitor) {
163+
RememberedSet.get().walkDirtyObjects(toSpace.getFirstAlignedHeapChunk(), toSpace.getFirstUnalignedHeapChunk(), Word.nullPointer(), visitor, refVisitor, true);
164164
}
165165

166166
@Override

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import com.oracle.svm.core.heap.RestrictHeapAccess;
8484
import com.oracle.svm.core.heap.RuntimeCodeCacheCleaner;
8585
import com.oracle.svm.core.heap.SuspendSerialGCMaxHeapSize;
86+
import com.oracle.svm.core.heap.UninterruptibleObjectReferenceVisitor;
8687
import com.oracle.svm.core.heap.UninterruptibleObjectVisitor;
8788
import com.oracle.svm.core.heap.VMOperationInfos;
8889
import com.oracle.svm.core.interpreter.InterpreterSupport;
@@ -909,12 +910,12 @@ private void blackenDirtyImageHeapChunkRoots(ImageHeapInfo info) {
909910
* difference after references to the runtime heap were nulled, which is assumed to be rare.
910911
*/
911912
boolean clean = completeCollection;
912-
walkDirtyImageHeapChunkRoots(info, greyToBlackObjectVisitor, clean);
913+
walkDirtyImageHeapChunkRoots(info, greyToBlackObjectVisitor, greyToBlackObjRefVisitor, clean);
913914
}
914915

915916
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
916-
static void walkDirtyImageHeapChunkRoots(ImageHeapInfo info, UninterruptibleObjectVisitor visitor, boolean clean) {
917-
RememberedSet.get().walkDirtyObjects(info.getFirstWritableAlignedChunk(), info.getFirstWritableUnalignedChunk(), info.getLastWritableUnalignedChunk(), visitor, clean);
917+
static void walkDirtyImageHeapChunkRoots(ImageHeapInfo info, UninterruptibleObjectVisitor visitor, UninterruptibleObjectReferenceVisitor refVisitor, boolean clean) {
918+
RememberedSet.get().walkDirtyObjects(info.getFirstWritableAlignedChunk(), info.getFirstWritableUnalignedChunk(), info.getLastWritableUnalignedChunk(), visitor, refVisitor, clean);
918919
}
919920

920921
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
@@ -963,7 +964,7 @@ private void blackenDirtyCardRoots() {
963964
* Walk old generation looking for dirty cards, and within those for old-to-young
964965
* pointers. Promote any referenced young objects.
965966
*/
966-
HeapImpl.getHeapImpl().getOldGeneration().blackenDirtyCardRoots(greyToBlackObjectVisitor);
967+
HeapImpl.getHeapImpl().getOldGeneration().blackenDirtyCardRoots(greyToBlackObjectVisitor, greyToBlackObjRefVisitor);
967968
} finally {
968969
blackenDirtyCardRootsTimer.stop();
969970
}

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@
2424
*/
2525
package com.oracle.svm.core.genscavenge;
2626

27+
import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
28+
2729
import org.graalvm.nativeimage.Platform;
2830
import org.graalvm.nativeimage.Platforms;
2931
import org.graalvm.word.Pointer;
3032

3133
import com.oracle.svm.core.AlwaysInline;
3234
import com.oracle.svm.core.Uninterruptible;
3335
import com.oracle.svm.core.genscavenge.remset.RememberedSet;
34-
import com.oracle.svm.core.heap.ObjectReferenceVisitor;
3536
import com.oracle.svm.core.heap.ReferenceAccess;
37+
import com.oracle.svm.core.heap.UninterruptibleObjectReferenceVisitor;
3638
import com.oracle.svm.core.log.Log;
3739

3840
import jdk.graal.compiler.word.Word;
@@ -46,7 +48,7 @@
4648
* Since this visitor is used during collection, one instance of it is constructed during native
4749
* image generation.
4850
*/
49-
final class GreyToBlackObjRefVisitor implements ObjectReferenceVisitor {
51+
public final class GreyToBlackObjRefVisitor implements UninterruptibleObjectReferenceVisitor {
5052
private final Counters counters;
5153

5254
@Platforms(Platform.HOSTED_ONLY.class)
@@ -60,7 +62,7 @@ final class GreyToBlackObjRefVisitor implements ObjectReferenceVisitor {
6062

6163
@Override
6264
@AlwaysInline("GC performance")
63-
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
65+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
6466
public void visitObjectReferences(Pointer firstObjRef, boolean compressed, int referenceSize, Object holderObject, int count) {
6567
Pointer pos = firstObjRef;
6668
Pointer end = firstObjRef.add(Word.unsigned(count).multiply(referenceSize));
@@ -71,7 +73,7 @@ public void visitObjectReferences(Pointer firstObjRef, boolean compressed, int r
7173
}
7274

7375
@AlwaysInline("GC performance")
74-
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
76+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
7577
private void visitObjectReference(Pointer objRef, boolean compressed, Object holderObject) {
7678
assert !objRef.isNull();
7779
counters.noteObjRef();
@@ -98,13 +100,13 @@ private void visitObjectReference(Pointer objRef, boolean compressed, Object hol
98100
// Update the reference to point to the forwarded Object.
99101
Object obj = ohi.getForwardedObject(p, header);
100102
ReferenceAccess.singleton().writeObjectAt(objRef, obj, compressed);
101-
RememberedSet.get().dirtyCardIfNecessary(holderObject, obj);
103+
RememberedSet.get().dirtyCardIfNecessary(holderObject, obj, objRef);
102104
return;
103105
}
104106

105107
Object obj = p.toObjectNonNull();
106108
if (SerialGCOptions.useCompactingOldGen() && ObjectHeaderImpl.isMarkedHeader(header)) {
107-
RememberedSet.get().dirtyCardIfNecessary(holderObject, obj);
109+
RememberedSet.get().dirtyCardIfNecessary(holderObject, obj, objRef);
108110
return;
109111
}
110112

@@ -120,7 +122,7 @@ private void visitObjectReference(Pointer objRef, boolean compressed, Object hol
120122

121123
// The reference will not be updated if a whole chunk is promoted. However, we still
122124
// might have to dirty the card.
123-
RememberedSet.get().dirtyCardIfNecessary(holderObject, copy);
125+
RememberedSet.get().dirtyCardIfNecessary(holderObject, copy, objRef);
124126
}
125127
}
126128

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ UnalignedHeader produceUnalignedChunk(UnsignedWord objectSize) {
233233
UnsignedWord chunkSize = UnalignedHeapChunk.getChunkSizeForObject(objectSize);
234234

235235
UnalignedHeader result = (UnalignedHeader) ChunkBasedCommittedMemoryProvider.get().allocateUnalignedChunk(chunkSize);
236-
UnalignedHeapChunk.initialize(result, chunkSize);
236+
UnalignedHeapChunk.initialize(result, chunkSize, objectSize);
237237
assert objectSize.belowOrEqual(HeapChunk.availableObjectMemory(result)) : "UnalignedHeapChunk insufficient for requested object";
238238

239239
/* Avoid zapping if unaligned chunks are pre-zeroed. */

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.nio.ByteBuffer;
2828
import java.util.List;
2929

30-
import jdk.graal.compiler.core.common.NumUtil;
3130
import org.graalvm.nativeimage.Platform;
3231
import org.graalvm.nativeimage.Platforms;
3332
import org.graalvm.nativeimage.c.struct.SizeOf;
@@ -39,6 +38,9 @@
3938
import com.oracle.svm.core.util.HostedByteBufferPointer;
4039
import com.oracle.svm.core.util.VMError;
4140

41+
import jdk.graal.compiler.core.common.NumUtil;
42+
import jdk.graal.compiler.word.Word;
43+
4244
@Platforms(Platform.HOSTED_ONLY.class)
4345
final class HostedImageHeapChunkWriter implements ImageHeapChunkWriter {
4446
private final ByteBuffer buffer;
@@ -76,9 +78,10 @@ public void initializeAlignedChunk(int chunkPosition, long topOffset, long endOf
7678
}
7779

7880
@Override
79-
public void initializeUnalignedChunk(int chunkPosition, long topOffset, long endOffset, long offsetToPreviousChunk, long offsetToNextChunk) {
81+
public void initializeUnalignedChunk(int chunkPosition, long topOffset, long endOffset, long offsetToPreviousChunk, long offsetToNextChunk, long objectSize) {
8082
int chunkOffset = getChunkOffsetInBuffer(chunkPosition);
8183
writeHeader(chunkOffset, topOffset, endOffset, offsetToPreviousChunk, offsetToNextChunk);
84+
UnalignedHeapChunk.initialize(new HostedByteBufferPointer(buffer, chunkOffset), Word.unsigned(objectSize));
8285
}
8386

8487
private void writeHeader(int chunkOffset, long topOffset, long endOffset, long offsetToPreviousChunk, long offsetToNextChunk) {
@@ -99,9 +102,9 @@ public void enableRememberedSetForAlignedChunk(int chunkPosition, List<ImageHeap
99102
}
100103

101104
@Override
102-
public void enableRememberedSetForUnalignedChunk(int chunkPosition) {
105+
public void enableRememberedSetForUnalignedChunk(int chunkPosition, long objectSize) {
103106
int chunkOffset = getChunkOffsetInBuffer(chunkPosition);
104-
rememberedSet.enableRememberedSetForUnalignedChunk(new HostedByteBufferPointer(buffer, chunkOffset));
107+
rememberedSet.enableRememberedSetForUnalignedChunk(new HostedByteBufferPointer(buffer, chunkOffset), Word.unsigned(objectSize));
105108
}
106109

107110
static void putObjectReference(ByteBuffer buffer, int offset, long value) {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ interface ImageHeapChunkWriter {
3333

3434
void enableRememberedSetForAlignedChunk(int chunkPosition, List<ImageHeapObject> objects);
3535

36-
void initializeUnalignedChunk(int chunkPosition, long topOffset, long endOffset, long offsetToPreviousChunk, long offsetToNextChunk);
36+
void initializeUnalignedChunk(int chunkPosition, long topOffset, long endOffset, long offsetToPreviousChunk, long offsetToNextChunk, long objectSize);
3737

38-
void enableRememberedSetForUnalignedChunk(int chunkPosition);
38+
void enableRememberedSetForUnalignedChunk(int chunkPosition, long objectSize);
3939
}

0 commit comments

Comments
 (0)