Skip to content

Commit b7571b8

Browse files
[GR-64208] Reduce virtual calls to Object and reference visitors.
PullRequest: graal/20648
2 parents b871606 + 9feb32d commit b7571b8

File tree

57 files changed

+566
-1141
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+566
-1141
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,14 @@ public static UnsignedWord getObjectOffset(AlignedHeader that, Pointer objectPoi
144144
return objectPointer.subtract(objectsStart);
145145
}
146146

147-
static boolean walkObjects(AlignedHeader that, ObjectVisitor visitor) {
148-
return HeapChunk.walkObjectsFrom(that, getObjectsStart(that), visitor);
147+
static void walkObjects(AlignedHeader that, ObjectVisitor visitor) {
148+
HeapChunk.walkObjectsFrom(that, getObjectsStart(that), visitor);
149149
}
150150

151151
@AlwaysInline("GC performance")
152152
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
153-
static boolean walkObjectsFromInline(AlignedHeader that, Pointer start, ObjectVisitor visitor) {
154-
return HeapChunk.walkObjectsFromInline(that, start, visitor);
153+
static void walkObjectsFromInline(AlignedHeader that, Pointer start, GreyToBlackObjectVisitor visitor) {
154+
HeapChunk.walkObjectsFromInline(that, start, visitor);
155155
}
156156

157157
@Fold

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

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

27-
import jdk.graal.compiler.api.replacements.Fold;
2827
import org.graalvm.nativeimage.ImageSingletons;
2928
import org.graalvm.word.Pointer;
3029

3130
import com.oracle.svm.core.MemoryWalker;
3231
import com.oracle.svm.core.Uninterruptible;
3332
import com.oracle.svm.core.heap.ObjectVisitor;
3433

34+
import jdk.graal.compiler.api.replacements.Fold;
35+
3536
public interface AuxiliaryImageHeap {
3637
@Fold
3738
static boolean isPresent() {
@@ -46,10 +47,10 @@ static AuxiliaryImageHeap singleton() {
4647
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
4748
boolean containsObject(Pointer address);
4849

49-
boolean walkObjects(ObjectVisitor visitor);
50+
void walkObjects(ObjectVisitor visitor);
5051

5152
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
52-
boolean walkRegions(MemoryWalker.ImageHeapRegionVisitor visitor);
53+
void walkRegions(MemoryWalker.ImageHeapRegionVisitor visitor);
5354

5455
ImageHeapInfo getImageHeapInfo();
5556
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ boolean scanGreyObjects(boolean incrementalGc) {
166166
}
167167
GreyToBlackObjectVisitor visitor = GCImpl.getGCImpl().getGreyToBlackObjectVisitor();
168168
do {
169-
visitor.visitObjectInline(markStack.pop());
169+
visitor.visitObject(markStack.pop());
170170
} while (!markStack.isEmpty());
171171
}
172172
return true;
@@ -362,7 +362,7 @@ private void fixupUnalignedChunkReferences(ChunkReleaser chunkReleaser) {
362362
while (uChunk.isNonNull()) {
363363
UnalignedHeapChunk.UnalignedHeader next = HeapChunk.getNext(uChunk);
364364
Pointer objPointer = UnalignedHeapChunk.getObjectStart(uChunk);
365-
Object obj = objPointer.toObject();
365+
Object obj = objPointer.toObjectNonNull();
366366
if (ObjectHeaderImpl.isMarked(obj)) {
367367
ObjectHeaderImpl.unsetMarkedAndKeepRememberedSetBit(obj);
368368
RememberedSet.get().clearRememberedSet(uChunk);
@@ -447,8 +447,8 @@ boolean printLocationInfo(Log log, Pointer ptr) {
447447
}
448448

449449
@Override
450-
public boolean walkObjects(ObjectVisitor visitor) {
451-
return space.walkObjects(visitor);
450+
public void walkObjects(ObjectVisitor visitor) {
451+
space.walkObjects(visitor);
452452
}
453453

454454
@Override

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ void tearDown() {
6565
}
6666

6767
@Override
68-
public boolean walkObjects(ObjectVisitor visitor) {
69-
return getFromSpace().walkObjects(visitor) && getToSpace().walkObjects(visitor);
68+
public void walkObjects(ObjectVisitor visitor) {
69+
getFromSpace().walkObjects(visitor);
70+
getToSpace().walkObjects(visitor);
7071
}
7172

7273
/** Promote an Object to ToSpace if it is not already in ToSpace. */

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,7 @@ abstract class Generation {
4141
this.name = name;
4242
}
4343

44-
/**
45-
* Walk the Objects in this Space, passing each to a Visitor.
46-
*
47-
* @param visitor An ObjectVisitor.
48-
* @return True if all visits returned true, false otherwise.
49-
*/
50-
public abstract boolean walkObjects(ObjectVisitor visitor);
44+
public abstract void walkObjects(ObjectVisitor visitor);
5145

5246
public String getName() {
5347
return name;

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

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

27-
import jdk.graal.compiler.word.Word;
2827
import org.graalvm.nativeimage.Platform;
2928
import org.graalvm.nativeimage.Platforms;
3029
import org.graalvm.word.Pointer;
3130

3231
import com.oracle.svm.core.AlwaysInline;
3332
import com.oracle.svm.core.NeverInline;
3433
import com.oracle.svm.core.Uninterruptible;
35-
import com.oracle.svm.core.util.VMError;
34+
35+
import jdk.graal.compiler.word.Word;
3636

3737
/**
3838
* Apply an ObjectVisitor to all the new Objects in a Space since a snapshot.
@@ -103,9 +103,7 @@ private void walkAlignedGreyObjects() {
103103
AlignedHeapChunk.AlignedHeader lastChunk;
104104
do {
105105
lastChunk = aChunk;
106-
if (!AlignedHeapChunk.walkObjectsFromInline(aChunk, aStart, visitor)) {
107-
throw VMError.shouldNotReachHereAtRuntime();
108-
}
106+
AlignedHeapChunk.walkObjectsFromInline(aChunk, aStart, visitor);
109107
aChunk = HeapChunk.getNext(aChunk);
110108
aStart = (aChunk.isNonNull() ? AlignedHeapChunk.getObjectsStart(aChunk) : Word.nullPointer());
111109
} while (aChunk.isNonNull());
@@ -131,9 +129,7 @@ private void walkUnalignedGreyObjects() {
131129
UnalignedHeapChunk.UnalignedHeader lastChunk;
132130
do {
133131
lastChunk = uChunk;
134-
if (!UnalignedHeapChunk.walkObjectsInline(uChunk, visitor)) {
135-
throw VMError.shouldNotReachHereAtRuntime();
136-
}
132+
UnalignedHeapChunk.walkObjectsInline(uChunk, visitor);
137133
uChunk = HeapChunk.getNext(uChunk);
138134
} while (uChunk.isNonNull());
139135

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

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import com.oracle.svm.core.genscavenge.remset.RememberedSet;
3434
import com.oracle.svm.core.heap.ObjectReferenceVisitor;
3535
import com.oracle.svm.core.heap.ReferenceAccess;
36-
import com.oracle.svm.core.hub.LayoutEncoding;
3736
import com.oracle.svm.core.log.Log;
3837

3938
import jdk.graal.compiler.word.Word;
@@ -60,31 +59,32 @@ final class GreyToBlackObjRefVisitor implements ObjectReferenceVisitor {
6059
}
6160

6261
@Override
62+
@AlwaysInline("GC performance")
6363
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
64-
public boolean visitObjectReference(Pointer objRef, boolean compressed, Object holderObject) {
65-
return visitObjectReferenceInline(objRef, 0, compressed, holderObject);
64+
public void visitObjectReferences(Pointer firstObjRef, boolean compressed, int referenceSize, Object holderObject, int count) {
65+
Pointer pos = firstObjRef;
66+
Pointer end = firstObjRef.add(Word.unsigned(count).multiply(referenceSize));
67+
while (pos.belowThan(end)) {
68+
visitObjectReference(pos, compressed, holderObject);
69+
pos = pos.add(referenceSize);
70+
}
6671
}
6772

68-
@Override
6973
@AlwaysInline("GC performance")
7074
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
71-
public boolean visitObjectReferenceInline(Pointer objRef, int innerOffset, boolean compressed, Object holderObject) {
72-
assert innerOffset >= 0;
75+
private void visitObjectReference(Pointer objRef, boolean compressed, Object holderObject) {
7376
assert !objRef.isNull();
7477
counters.noteObjRef();
7578

76-
Pointer offsetP = ReferenceAccess.singleton().readObjectAsUntrackedPointer(objRef, compressed);
77-
assert offsetP.isNonNull() || innerOffset == 0;
78-
79-
Pointer p = offsetP.subtract(innerOffset);
79+
Pointer p = ReferenceAccess.singleton().readObjectAsUntrackedPointer(objRef, compressed);
8080
if (p.isNull()) {
8181
counters.noteNullReferent();
82-
return true;
82+
return;
8383
}
8484

8585
if (HeapImpl.getHeapImpl().isInImageHeap(p)) {
8686
counters.noteNonHeapReferent();
87-
return true;
87+
return;
8888
}
8989

9090
// This is the most expensive check as it accesses the heap fairly randomly, which results
@@ -97,26 +97,23 @@ public boolean visitObjectReferenceInline(Pointer objRef, int innerOffset, boole
9797
counters.noteForwardedReferent();
9898
// Update the reference to point to the forwarded Object.
9999
Object obj = ohi.getForwardedObject(p, header);
100-
Object offsetObj = (innerOffset == 0) ? obj : Word.objectToUntrackedPointer(obj).add(innerOffset).toObject();
101-
ReferenceAccess.singleton().writeObjectAt(objRef, offsetObj, compressed);
100+
ReferenceAccess.singleton().writeObjectAt(objRef, obj, compressed);
102101
RememberedSet.get().dirtyCardIfNecessary(holderObject, obj);
103-
return true;
102+
return;
104103
}
105104

106-
Object obj = p.toObject();
105+
Object obj = p.toObjectNonNull();
107106
if (SerialGCOptions.useCompactingOldGen() && ObjectHeaderImpl.isMarkedHeader(header)) {
108107
RememberedSet.get().dirtyCardIfNecessary(holderObject, obj);
109-
return true;
108+
return;
110109
}
111110

112111
// Promote the Object if necessary, making it at least grey, and ...
113-
assert innerOffset < LayoutEncoding.getSizeFromObjectInGC(obj).rawValue();
114112
Object copy = GCImpl.getGCImpl().promoteObject(obj, header);
115113
if (copy != obj) {
116114
// ... update the reference to point to the copy, making the reference black.
117115
counters.noteCopiedReferent();
118-
Object offsetCopy = (innerOffset == 0) ? copy : Word.objectToUntrackedPointer(copy).add(innerOffset).toObject();
119-
ReferenceAccess.singleton().writeObjectAt(objRef, offsetCopy, compressed);
116+
ReferenceAccess.singleton().writeObjectAt(objRef, copy, compressed);
120117
} else {
121118
counters.noteUnmodifiedReference();
122119
}
@@ -125,7 +122,6 @@ public boolean visitObjectReferenceInline(Pointer objRef, int innerOffset, boole
125122
// might have to dirty the card.
126123
RememberedSet.get().dirtyCardIfNecessary(holderObject, copy);
127124
}
128-
return true;
129125
}
130126

131127
public Counters openCounters() {

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,9 @@
2828
import org.graalvm.nativeimage.Platforms;
2929

3030
import com.oracle.svm.core.AlwaysInline;
31-
import com.oracle.svm.core.NeverInline;
3231
import com.oracle.svm.core.Uninterruptible;
3332
import com.oracle.svm.core.heap.UninterruptibleObjectVisitor;
3433
import com.oracle.svm.core.hub.InteriorObjRefWalker;
35-
import com.oracle.svm.core.util.VMError;
3634

3735
/**
3836
* Run an ObjectReferenceVisitor ({@link GreyToBlackObjRefVisitor}) over any interior object
@@ -48,19 +46,11 @@ public final class GreyToBlackObjectVisitor implements UninterruptibleObjectVisi
4846
this.objRefVisitor = greyToBlackObjRefVisitor;
4947
}
5048

51-
@Override
52-
@NeverInline("Non-performance critical version")
53-
@Uninterruptible(reason = "Visitor requires uninterruptible walk.", callerMustBe = true)
54-
public boolean visitObject(Object o) {
55-
throw VMError.shouldNotReachHere("For performance reasons, this should not be called.");
56-
}
57-
5849
@Override
5950
@AlwaysInline("GC performance")
6051
@Uninterruptible(reason = "Forced inlining (StoredContinuation objects must not move).", callerMustBe = true)
61-
public boolean visitObjectInline(Object o) {
52+
public void visitObject(Object o) {
6253
ReferenceObjectProcessing.discoverIfReference(o, objRefVisitor);
6354
InteriorObjRefWalker.walkObjectInline(o, objRefVisitor);
64-
return true;
6555
}
6656
}

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

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -301,28 +301,25 @@ private static SignedWord offsetFromPointer(Header<?> that, PointerBase pointer)
301301

302302
@NeverInline("Not performance critical")
303303
@Uninterruptible(reason = "Forced inlining (StoredContinuation objects must not move).")
304-
public static boolean walkObjectsFrom(Header<?> that, Pointer start, ObjectVisitor visitor) {
305-
return walkObjectsFromInline(that, start, visitor);
304+
public static void walkObjectsFrom(Header<?> that, Pointer start, ObjectVisitor visitor) {
305+
walkObjectsFromInline(that, start, visitor);
306306
}
307307

308308
@AlwaysInline("GC performance")
309309
@Uninterruptible(reason = "Forced inlining (StoredContinuation objects must not move).", callerMustBe = true)
310-
public static boolean walkObjectsFromInline(Header<?> that, Pointer start, ObjectVisitor visitor) {
310+
public static void walkObjectsFromInline(Header<?> that, Pointer start, ObjectVisitor visitor) {
311311
Pointer p = start;
312312
while (p.belowThan(getTopPointer(that))) { // crucial: top can move, so always re-read
313-
Object obj = p.toObject();
314-
if (!callVisitor(visitor, obj)) {
315-
return false;
316-
}
313+
Object obj = p.toObjectNonNull();
314+
callVisitor(visitor, obj);
317315
p = p.add(LayoutEncoding.getSizeFromObjectInlineInGC(obj));
318316
}
319-
return true;
320317
}
321318

322319
@AlwaysInline("de-virtualize calls to ObjectReferenceVisitor")
323320
@Uninterruptible(reason = "Bridge between uninterruptible and potentially interruptible code.", mayBeInlined = true, calleeMustBe = false)
324-
private static boolean callVisitor(ObjectVisitor visitor, Object obj) {
325-
return visitor.visitObjectInline(obj);
321+
private static void callVisitor(ObjectVisitor visitor, Object obj) {
322+
visitor.visitObject(obj);
326323
}
327324

328325
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)

0 commit comments

Comments
 (0)