Skip to content

Commit 1ce5535

Browse files
committed
[GR-59641] Basic infrastructure to create a DynamicHub at runtime
PullRequest: graal/19268
2 parents aa392a0 + 6446aea commit 1ce5535

File tree

25 files changed

+923
-60
lines changed

25 files changed

+923
-60
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/FinalFieldBarrierNode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,7 @@ public void lower(LoweringTool tool) {
7676
*/
7777
graph().replaceFixedWithFixed(this, graph().add(new MembarNode(MembarNode.FenceKind.CONSTRUCTOR_FREEZE)));
7878
}
79+
80+
@NodeIntrinsic
81+
public static native void finalFieldBarrier(Object object);
7982
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ void absorb(YoungGeneration youngGen) {
139139
}
140140
}
141141

142+
@Override
143+
void appendChunk(AlignedHeapChunk.AlignedHeader hdr) {
144+
space.appendAlignedHeapChunk(hdr);
145+
}
146+
142147
@Override
143148
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
144149
void blackenDirtyCardRoots(GreyToBlackObjectVisitor visitor) {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ Space getToSpace() {
143143
return toSpace;
144144
}
145145

146+
@Override
147+
void appendChunk(AlignedHeapChunk.AlignedHeader hdr) {
148+
getToSpace().appendAlignedHeapChunk(hdr);
149+
}
150+
146151
@Override
147152
void swapSpaces() {
148153
assert getFromSpace().isEmpty() : "fromSpace should be empty.";

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

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.ArrayList;
2929
import java.util.List;
3030

31+
import com.oracle.svm.core.hub.LayoutEncoding;
3132
import org.graalvm.nativeimage.CurrentIsolate;
3233
import org.graalvm.nativeimage.IsolateThread;
3334
import org.graalvm.nativeimage.Platform;
@@ -54,6 +55,7 @@
5455
import com.oracle.svm.core.genscavenge.ThreadLocalAllocation.Descriptor;
5556
import com.oracle.svm.core.genscavenge.UnalignedHeapChunk.UnalignedHeader;
5657
import com.oracle.svm.core.genscavenge.graal.ForcedSerialPostWriteBarrier;
58+
import com.oracle.svm.core.genscavenge.graal.nodes.FormatArrayNode;
5759
import com.oracle.svm.core.graal.snippets.SubstrateAllocationSnippets;
5860
import com.oracle.svm.core.heap.GC;
5961
import com.oracle.svm.core.heap.GCCause;
@@ -66,6 +68,7 @@
6668
import com.oracle.svm.core.heap.ReferenceInternals;
6769
import com.oracle.svm.core.heap.RestrictHeapAccess;
6870
import com.oracle.svm.core.heap.RuntimeCodeInfoGCSupport;
71+
import com.oracle.svm.core.heap.VMOperationInfos;
6972
import com.oracle.svm.core.hub.DynamicHub;
7073
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
7174
import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicReference;
@@ -80,6 +83,7 @@
8083
import com.oracle.svm.core.option.RuntimeOptionKey;
8184
import com.oracle.svm.core.os.ImageHeapProvider;
8285
import com.oracle.svm.core.snippets.KnownIntrinsics;
86+
import com.oracle.svm.core.thread.JavaVMOperation;
8387
import com.oracle.svm.core.thread.PlatformThreads;
8488
import com.oracle.svm.core.thread.ThreadStatus;
8589
import com.oracle.svm.core.thread.VMOperation;
@@ -95,6 +99,7 @@
9599
import jdk.graal.compiler.core.common.SuppressFBWarnings;
96100
import jdk.graal.compiler.nodes.extended.MembarNode;
97101
import jdk.graal.compiler.nodes.memory.address.OffsetAddressNode;
102+
import jdk.graal.compiler.replacements.AllocationSnippets;
98103
import jdk.graal.compiler.word.Word;
99104

100105
public final class HeapImpl extends Heap {
@@ -111,6 +116,8 @@ public final class HeapImpl extends Heap {
111116
private final RuntimeCodeInfoGCSupportImpl runtimeCodeInfoGcSupport;
112117
private final HeapAccounting accounting = new HeapAccounting();
113118

119+
private AlignedHeader lastDynamicHubChunk;
120+
114121
/** Head of the linked list of currently pending (ready to be enqueued) {@link Reference}s. */
115122
private Reference<?> refPendingList;
116123
/** Total number of times when a new pending reference list became available. */
@@ -933,6 +940,83 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
933940
log.indent(false);
934941
}
935942
}
943+
944+
public static DynamicHub allocateDynamicHub(int vTableSlots) {
945+
AllocateDynamicHubOp vmOp = new AllocateDynamicHubOp(vTableSlots);
946+
vmOp.enqueue();
947+
return vmOp.result;
948+
}
949+
950+
private static class AllocateDynamicHubOp extends JavaVMOperation {
951+
int vTableSlots;
952+
DynamicHub result;
953+
954+
AllocateDynamicHubOp(int vTableSlots) {
955+
super(VMOperationInfos.get(AllocateDynamicHubOp.class, "Allocate DynamicHub", SystemEffect.SAFEPOINT));
956+
this.vTableSlots = vTableSlots;
957+
}
958+
959+
@Override
960+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
961+
public boolean isGC() {
962+
/* needs to append chunks into oldGen */
963+
return true;
964+
}
965+
966+
@Override
967+
protected void operate() {
968+
DynamicHub hubOfDynamicHub = DynamicHub.fromClass(Class.class);
969+
/*
970+
* Note that layoutEncoding already encodes the size of a DynamicHub and it is aware of
971+
* its hybrid nature, including the size required for a VTable slot.
972+
*
973+
* Also note that inlined fields like `closedTypeWorldTypeCheckSlots` are not relevant
974+
* here, as they are not available in the open type world configuration.
975+
*/
976+
UnsignedWord size = LayoutEncoding.getArrayAllocationSize(hubOfDynamicHub.getLayoutEncoding(), vTableSlots);
977+
978+
Pointer memory = WordFactory.nullPointer();
979+
if (getHeapImpl().lastDynamicHubChunk.isNonNull()) {
980+
/*
981+
* GR-57355: move this fast-path out of vmOp. Needs some locking (it's not
982+
* thread-local)
983+
*/
984+
memory = AlignedHeapChunk.allocateMemory(getHeapImpl().lastDynamicHubChunk, size);
985+
}
986+
987+
if (memory.isNull()) {
988+
/* Either no storage for DynamicHubs yet or we are out of memory */
989+
allocateNewDynamicHubChunk();
990+
991+
memory = AlignedHeapChunk.allocateMemory(getHeapImpl().lastDynamicHubChunk, size);
992+
}
993+
994+
VMError.guarantee(memory.isNonNull(), "failed to allocate DynamicHub");
995+
996+
/* DynamicHubs live allocated on aligned heap chunks */
997+
boolean unaligned = false;
998+
result = (DynamicHub) FormatArrayNode.formatArray(memory, DynamicHub.class, vTableSlots, true, unaligned, AllocationSnippets.FillContent.WITH_ZEROES, true);
999+
}
1000+
1001+
private static void allocateNewDynamicHubChunk() {
1002+
/*
1003+
* GR-60085: Should be a dedicated generation. Make sure that those chunks are close to
1004+
* the heap base. The hub is stored as offset relative to the heap base. There are 5
1005+
* status bits in the header and in addition, compressed references use a three-bit
1006+
* shift that word-aligns objects. This results in a 35-bit address range of 32 GB, of
1007+
* which DynamicHubs must reside in the lowest 1 GB.
1008+
*/
1009+
OldGeneration oldGeneration = getHeapImpl().getOldGeneration();
1010+
1011+
/*
1012+
* GR-60085: DynamicHub objects must never be be moved. Pin them either by (1) pinning
1013+
* each DynamicHub, or (2) mark the whole chunk as pinned (not supported yet).
1014+
*/
1015+
getHeapImpl().lastDynamicHubChunk = oldGeneration.requestAlignedChunk();
1016+
1017+
oldGeneration.appendChunk(getHeapImpl().lastDynamicHubChunk);
1018+
}
1019+
}
9361020
}
9371021

9381022
@TargetClass(value = java.lang.Runtime.class, onlyWith = UseSerialOrEpsilonGC.class)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public abstract class OldGeneration extends Generation {
6363

6464
abstract boolean isInSpace(Pointer ptr);
6565

66+
abstract void appendChunk(AlignedHeapChunk.AlignedHeader hdr);
67+
6668
abstract boolean verifyRememberedSets();
6769

6870
abstract boolean verifySpaces();

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,11 @@ private static Object slowPathNewPodInstance(Word objectHeader, int arrayLength,
266266
return slowPathNewArrayLikeObject(objectHeader, arrayLength, referenceMap);
267267
}
268268

269+
@SubstrateForeignCallTarget(stubCallingConvention = false)
270+
private static Object newDynamicHub(int vTableSlots) {
271+
return HeapImpl.allocateDynamicHub(vTableSlots);
272+
}
273+
269274
private static Object slowPathNewArrayLikeObject(Word objectHeader, int length, byte[] podReferenceMap) {
270275
/*
271276
* Avoid stack overflow errors while producing memory chunks, because that could leave the

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSupport.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider;
3434
import com.oracle.svm.core.graal.snippets.GCAllocationSupport;
3535
import com.oracle.svm.core.heap.Pod;
36+
import com.oracle.svm.core.hub.RuntimeClassLoading;
3637
import com.oracle.svm.core.snippets.SnippetRuntime;
3738
import com.oracle.svm.core.snippets.SnippetRuntime.SubstrateForeignCallDescriptor;
3839
import com.oracle.svm.core.thread.ContinuationSupport;
@@ -45,6 +46,7 @@ public class GenScavengeAllocationSupport implements GCAllocationSupport {
4546
private static final SubstrateForeignCallDescriptor SLOW_NEW_ARRAY = SnippetRuntime.findForeignCall(ThreadLocalAllocation.class, "slowPathNewArray", NO_SIDE_EFFECT);
4647
private static final SubstrateForeignCallDescriptor SLOW_NEW_STORED_CONTINUATION = SnippetRuntime.findForeignCall(ThreadLocalAllocation.class, "slowPathNewStoredContinuation", NO_SIDE_EFFECT);
4748
private static final SubstrateForeignCallDescriptor SLOW_NEW_POD_INSTANCE = SnippetRuntime.findForeignCall(ThreadLocalAllocation.class, "slowPathNewPodInstance", NO_SIDE_EFFECT);
49+
private static final SubstrateForeignCallDescriptor NEW_DYNAMICHUB = SnippetRuntime.findForeignCall(ThreadLocalAllocation.class, "newDynamicHub", NO_SIDE_EFFECT);
4850
private static final SubstrateForeignCallDescriptor[] UNCONDITIONAL_FOREIGN_CALLS = new SubstrateForeignCallDescriptor[]{SLOW_NEW_INSTANCE, SLOW_NEW_ARRAY};
4951

5052
public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCalls) {
@@ -55,6 +57,9 @@ public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCal
5557
if (Pod.RuntimeSupport.isPresent()) {
5658
foreignCalls.register(SLOW_NEW_POD_INSTANCE);
5759
}
60+
if (RuntimeClassLoading.isSupported()) {
61+
foreignCalls.register(NEW_DYNAMICHUB);
62+
}
5863
}
5964

6065
@Override
@@ -77,6 +82,11 @@ public ForeignCallDescriptor getNewPodInstanceStub() {
7782
return SLOW_NEW_POD_INSTANCE;
7883
}
7984

85+
@Override
86+
public SubstrateForeignCallDescriptor getNewDynamicHub() {
87+
return NEW_DYNAMICHUB;
88+
}
89+
8090
@Override
8191
public boolean useTLAB() {
8292
return true;

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.concurrent.locks.Condition;
2828
import java.util.concurrent.locks.ReentrantLock;
2929

30+
import com.oracle.svm.core.hub.RuntimeClassLoading;
3031
import org.graalvm.nativeimage.CurrentIsolate;
3132
import org.graalvm.nativeimage.IsolateThread;
3233
import org.graalvm.nativeimage.Platform;
@@ -232,6 +233,19 @@ public ClassInitializationInfo(CFunctionPointer classInitializer, boolean typeRe
232233
this.hasInitializer = classInitializer != null;
233234
}
234235

236+
public ClassInitializationInfo(boolean typeReachedTracked) {
237+
assert RuntimeClassLoading.isSupported();
238+
239+
this.classInitializer = null;
240+
this.hasInitializer = true;
241+
242+
// GR-59739: Needs a new state "Loaded".
243+
this.initState = InitState.Linked;
244+
this.typeReached = typeReachedTracked ? TypeReached.NOT_REACHED : TypeReached.UNTRACKED;
245+
this.slowPathRequired = true;
246+
this.initLock = new ReentrantLock();
247+
}
248+
235249
public boolean hasInitializer() {
236250
return hasInitializer;
237251
}

0 commit comments

Comments
 (0)