Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GR-59641] Basic infrastructure to create a DynamicHub at runtime #10270

Merged
merged 1 commit into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,7 @@ public void lower(LoweringTool tool) {
*/
graph().replaceFixedWithFixed(this, graph().add(new MembarNode(MembarNode.FenceKind.CONSTRUCTOR_FREEZE)));
}

@NodeIntrinsic
public static native void finalFieldBarrier(Object object);
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ void absorb(YoungGeneration youngGen) {
}
}

@Override
void appendChunk(AlignedHeapChunk.AlignedHeader hdr) {
space.appendAlignedHeapChunk(hdr);
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
void blackenDirtyCardRoots(GreyToBlackObjectVisitor visitor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ Space getToSpace() {
return toSpace;
}

@Override
void appendChunk(AlignedHeapChunk.AlignedHeader hdr) {
getToSpace().appendAlignedHeapChunk(hdr);
}

@Override
void swapSpaces() {
assert getFromSpace().isEmpty() : "fromSpace should be empty.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.List;

import com.oracle.svm.core.hub.LayoutEncoding;
import org.graalvm.nativeimage.CurrentIsolate;
import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.Platform;
Expand All @@ -54,6 +55,7 @@
import com.oracle.svm.core.genscavenge.ThreadLocalAllocation.Descriptor;
import com.oracle.svm.core.genscavenge.UnalignedHeapChunk.UnalignedHeader;
import com.oracle.svm.core.genscavenge.graal.ForcedSerialPostWriteBarrier;
import com.oracle.svm.core.genscavenge.graal.nodes.FormatArrayNode;
import com.oracle.svm.core.graal.snippets.SubstrateAllocationSnippets;
import com.oracle.svm.core.heap.GC;
import com.oracle.svm.core.heap.GCCause;
Expand All @@ -66,6 +68,7 @@
import com.oracle.svm.core.heap.ReferenceInternals;
import com.oracle.svm.core.heap.RestrictHeapAccess;
import com.oracle.svm.core.heap.RuntimeCodeInfoGCSupport;
import com.oracle.svm.core.heap.VMOperationInfos;
import com.oracle.svm.core.hub.DynamicHub;
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicReference;
Expand All @@ -80,6 +83,7 @@
import com.oracle.svm.core.option.RuntimeOptionKey;
import com.oracle.svm.core.os.ImageHeapProvider;
import com.oracle.svm.core.snippets.KnownIntrinsics;
import com.oracle.svm.core.thread.JavaVMOperation;
import com.oracle.svm.core.thread.PlatformThreads;
import com.oracle.svm.core.thread.ThreadStatus;
import com.oracle.svm.core.thread.VMOperation;
Expand All @@ -95,6 +99,7 @@
import jdk.graal.compiler.core.common.SuppressFBWarnings;
import jdk.graal.compiler.nodes.extended.MembarNode;
import jdk.graal.compiler.nodes.memory.address.OffsetAddressNode;
import jdk.graal.compiler.replacements.AllocationSnippets;
import jdk.graal.compiler.word.Word;

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

private AlignedHeader lastDynamicHubChunk;

/** Head of the linked list of currently pending (ready to be enqueued) {@link Reference}s. */
private Reference<?> refPendingList;
/** Total number of times when a new pending reference list became available. */
Expand Down Expand Up @@ -933,6 +940,83 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
log.indent(false);
}
}

public static DynamicHub allocateDynamicHub(int vTableSlots) {
AllocateDynamicHubOp vmOp = new AllocateDynamicHubOp(vTableSlots);
vmOp.enqueue();
return vmOp.result;
}

private static class AllocateDynamicHubOp extends JavaVMOperation {
int vTableSlots;
DynamicHub result;

AllocateDynamicHubOp(int vTableSlots) {
super(VMOperationInfos.get(AllocateDynamicHubOp.class, "Allocate DynamicHub", SystemEffect.SAFEPOINT));
this.vTableSlots = vTableSlots;
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public boolean isGC() {
/* needs to append chunks into oldGen */
return true;
}

@Override
protected void operate() {
DynamicHub hubOfDynamicHub = DynamicHub.fromClass(Class.class);
/*
* Note that layoutEncoding already encodes the size of a DynamicHub and it is aware of
* its hybrid nature, including the size required for a VTable slot.
*
* Also note that inlined fields like `closedTypeWorldTypeCheckSlots` are not relevant
* here, as they are not available in the open type world configuration.
*/
UnsignedWord size = LayoutEncoding.getArrayAllocationSize(hubOfDynamicHub.getLayoutEncoding(), vTableSlots);

Pointer memory = WordFactory.nullPointer();
if (getHeapImpl().lastDynamicHubChunk.isNonNull()) {
/*
* GR-57355: move this fast-path out of vmOp. Needs some locking (it's not
* thread-local)
*/
memory = AlignedHeapChunk.allocateMemory(getHeapImpl().lastDynamicHubChunk, size);
}

if (memory.isNull()) {
/* Either no storage for DynamicHubs yet or we are out of memory */
allocateNewDynamicHubChunk();

memory = AlignedHeapChunk.allocateMemory(getHeapImpl().lastDynamicHubChunk, size);
}

VMError.guarantee(memory.isNonNull(), "failed to allocate DynamicHub");

/* DynamicHubs live allocated on aligned heap chunks */
boolean unaligned = false;
result = (DynamicHub) FormatArrayNode.formatArray(memory, DynamicHub.class, vTableSlots, true, unaligned, AllocationSnippets.FillContent.WITH_ZEROES, true);
}

private static void allocateNewDynamicHubChunk() {
/*
* GR-60085: Should be a dedicated generation. Make sure that those chunks are close to
* the heap base. The hub is stored as offset relative to the heap base. There are 5
* status bits in the header and in addition, compressed references use a three-bit
* shift that word-aligns objects. This results in a 35-bit address range of 32 GB, of
* which DynamicHubs must reside in the lowest 1 GB.
*/
OldGeneration oldGeneration = getHeapImpl().getOldGeneration();

/*
* GR-60085: DynamicHub objects must never be be moved. Pin them either by (1) pinning
* each DynamicHub, or (2) mark the whole chunk as pinned (not supported yet).
*/
getHeapImpl().lastDynamicHubChunk = oldGeneration.requestAlignedChunk();

oldGeneration.appendChunk(getHeapImpl().lastDynamicHubChunk);
}
}
}

@TargetClass(value = java.lang.Runtime.class, onlyWith = UseSerialOrEpsilonGC.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public abstract class OldGeneration extends Generation {

abstract boolean isInSpace(Pointer ptr);

abstract void appendChunk(AlignedHeapChunk.AlignedHeader hdr);

abstract boolean verifyRememberedSets();

abstract boolean verifySpaces();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ private static Object slowPathNewPodInstance(Word objectHeader, int arrayLength,
return slowPathNewArrayLikeObject(objectHeader, arrayLength, referenceMap);
}

@SubstrateForeignCallTarget(stubCallingConvention = false)
private static Object newDynamicHub(int vTableSlots) {
return HeapImpl.allocateDynamicHub(vTableSlots);
}

private static Object slowPathNewArrayLikeObject(Word objectHeader, int length, byte[] podReferenceMap) {
/*
* Avoid stack overflow errors while producing memory chunks, because that could leave the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider;
import com.oracle.svm.core.graal.snippets.GCAllocationSupport;
import com.oracle.svm.core.heap.Pod;
import com.oracle.svm.core.hub.RuntimeClassLoading;
import com.oracle.svm.core.snippets.SnippetRuntime;
import com.oracle.svm.core.snippets.SnippetRuntime.SubstrateForeignCallDescriptor;
import com.oracle.svm.core.thread.ContinuationSupport;
Expand All @@ -45,6 +46,7 @@ public class GenScavengeAllocationSupport implements GCAllocationSupport {
private static final SubstrateForeignCallDescriptor SLOW_NEW_ARRAY = SnippetRuntime.findForeignCall(ThreadLocalAllocation.class, "slowPathNewArray", NO_SIDE_EFFECT);
private static final SubstrateForeignCallDescriptor SLOW_NEW_STORED_CONTINUATION = SnippetRuntime.findForeignCall(ThreadLocalAllocation.class, "slowPathNewStoredContinuation", NO_SIDE_EFFECT);
private static final SubstrateForeignCallDescriptor SLOW_NEW_POD_INSTANCE = SnippetRuntime.findForeignCall(ThreadLocalAllocation.class, "slowPathNewPodInstance", NO_SIDE_EFFECT);
private static final SubstrateForeignCallDescriptor NEW_DYNAMICHUB = SnippetRuntime.findForeignCall(ThreadLocalAllocation.class, "newDynamicHub", NO_SIDE_EFFECT);
private static final SubstrateForeignCallDescriptor[] UNCONDITIONAL_FOREIGN_CALLS = new SubstrateForeignCallDescriptor[]{SLOW_NEW_INSTANCE, SLOW_NEW_ARRAY};

public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCalls) {
Expand All @@ -55,6 +57,9 @@ public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCal
if (Pod.RuntimeSupport.isPresent()) {
foreignCalls.register(SLOW_NEW_POD_INSTANCE);
}
if (RuntimeClassLoading.isSupported()) {
foreignCalls.register(NEW_DYNAMICHUB);
}
}

@Override
Expand All @@ -77,6 +82,11 @@ public ForeignCallDescriptor getNewPodInstanceStub() {
return SLOW_NEW_POD_INSTANCE;
}

@Override
public SubstrateForeignCallDescriptor getNewDynamicHub() {
return NEW_DYNAMICHUB;
}

@Override
public boolean useTLAB() {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import com.oracle.svm.core.hub.RuntimeClassLoading;
import org.graalvm.nativeimage.CurrentIsolate;
import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.Platform;
Expand Down Expand Up @@ -232,6 +233,19 @@ public ClassInitializationInfo(CFunctionPointer classInitializer, boolean typeRe
this.hasInitializer = classInitializer != null;
}

public ClassInitializationInfo(boolean typeReachedTracked) {
assert RuntimeClassLoading.isSupported();

this.classInitializer = null;
this.hasInitializer = true;

// GR-59739: Needs a new state "Loaded".
this.initState = InitState.Linked;
this.typeReached = typeReachedTracked ? TypeReached.NOT_REACHED : TypeReached.UNTRACKED;
this.slowPathRequired = true;
this.initLock = new ReentrantLock();
}

public boolean hasInitializer() {
return hasInitializer;
}
Expand Down
Loading