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-24402] Support runtime-defined variably-sized objects with references. #4537

Merged
merged 13 commits into from
May 17, 2022
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 @@ -112,7 +112,7 @@ protected Object newMultiArrayImpl(Word hub, int rank, int[] dimensions) {
return callNewMultiArrayStub(hub, rank, dims);
}

private UnsignedWord arrayAllocationSize(int length, int arrayBaseOffset, int log2ElementSize) {
protected UnsignedWord arrayAllocationSize(int length, int arrayBaseOffset, int log2ElementSize) {
int alignment = objectAlignment();
return WordFactory.unsigned(arrayAllocationSize(length, arrayBaseOffset, log2ElementSize, alignment));
}
Expand Down Expand Up @@ -304,7 +304,7 @@ public Object formatArray(Word hub,
return memory.toObjectNonNull();
}

public void emitMemoryBarrierIf(boolean emitMemoryBarrier) {
protected void emitMemoryBarrierIf(boolean emitMemoryBarrier) {
if (emitMemoryBarrier) {
MembarNode.memoryBarrier(MembarNode.FenceKind.ALLOCATION_INIT, LocationIdentity.init());
}
Expand Down Expand Up @@ -379,7 +379,7 @@ public static FillContent fromBoolean(boolean fillContents) {
}

public static class AllocationProfilingData {
final AllocationSnippetCounters snippetCounters;
public final AllocationSnippetCounters snippetCounters;

public AllocationProfilingData(AllocationSnippetCounters snippetCounters) {
this.snippetCounters = snippetCounters;
Expand All @@ -395,9 +395,9 @@ public AllocationSnippetCounters(SnippetCounter.Group.Factory factory) {
stub = new SnippetCounter(allocations, "stub", "alloc and zeroing via stub");
}

final SnippetCounter unrolledInit;
final SnippetCounter loopInit;
final SnippetCounter bulkInit;
final SnippetCounter stub;
public final SnippetCounter unrolledInit;
public final SnippetCounter loopInit;
public final SnippetCounter bulkInit;
public final SnippetCounter stub;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,44 +40,6 @@
*/
package org.graalvm.nativeimage.impl;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

public interface RuntimeReflectionSupport extends ReflectionRegistry {
Map<Class<?>, Set<Class<?>>> getReflectionInnerClasses();

Set<Field> getReflectionFields();

Set<Executable> getReflectionExecutables();

Object getAccessor(Executable method);

/*
* Returns the methods and fields that shadow a superclass element registered for reflection, to
* be excluded from reflection queries.
*/
Set<?> getHidingReflectionFields();

Set<?> getHidingReflectionMethods();

Object[] getRecordComponents(Class<?> type);

void registerHeapDynamicHub(Object hub);

Set<?> getHeapDynamicHubs();

void registerHeapReflectionObject(AccessibleObject object);

Set<AccessibleObject> getHeapReflectionObjects();

int getReflectionClassesCount();

int getReflectionMethodsCount();

int getReflectionFieldsCount();

boolean requiresProcessing();
// needed as reflection-specific ImageSingletons key
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
DynamicHub hub = (DynamicHub) headerHub.toObject();
log.string(" class: ").string(hub.getName());
Object entryAsObject = objectEntry.toObject();
if (LayoutEncoding.isArray(entryAsObject)) {
if (LayoutEncoding.isArrayLike(entryAsObject)) {
int length = ArrayLengthNode.arrayLength(entryAsObject);
log.string(" length: ").signed(length);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import com.oracle.svm.core.genscavenge.UnalignedHeapChunk.UnalignedHeader;
import com.oracle.svm.core.genscavenge.graal.nodes.FormatArrayNode;
import com.oracle.svm.core.genscavenge.graal.nodes.FormatObjectNode;
import com.oracle.svm.core.genscavenge.graal.nodes.FormatPodNode;
import com.oracle.svm.core.graal.snippets.DeoptTester;
import com.oracle.svm.core.heap.OutOfMemoryUtil;
import com.oracle.svm.core.hub.DynamicHub;
Expand Down Expand Up @@ -222,7 +223,7 @@ private static void runSlowPathHooks() {
private static Object slowPathNewInstanceWithoutAllocating(DynamicHub hub) {
DeoptTester.disableDeoptTesting();
try {
HeapImpl.exitIfAllocationDisallowed("ThreadLocalAllocation.allocateNewInstance", DynamicHub.toClass(hub).getName());
HeapImpl.exitIfAllocationDisallowed("ThreadLocalAllocation.slowPathNewInstanceWithoutAllocating", DynamicHub.toClass(hub).getName());
GCImpl.getGCImpl().maybeCollectOnAllocation();

AlignedHeader newTlab = HeapImpl.getChunkProvider().produceAlignedChunk();
Expand All @@ -234,6 +235,15 @@ private static Object slowPathNewInstanceWithoutAllocating(DynamicHub hub) {

@SubstrateForeignCallTarget(stubCallingConvention = false)
private static Object slowPathNewArray(Word objectHeader, int length, int fillStartOffset) {
return slowPathNewArrayOrPodImpl(objectHeader, length, fillStartOffset, null);
}

@SubstrateForeignCallTarget(stubCallingConvention = false)
private static Object slowPathNewPodInstance(Word objectHeader, int arrayLength, int fillStartOffset, byte[] referenceMap) {
return slowPathNewArrayOrPodImpl(objectHeader, arrayLength, fillStartOffset, referenceMap);
}

private static Object slowPathNewArrayOrPodImpl(Word objectHeader, int length, int fillStartOffset, byte[] podReferenceMap) {
/*
* Avoid stack overflow errors while producing memory chunks, because that could leave the
* heap in an inconsistent state.
Expand All @@ -257,7 +267,7 @@ private static Object slowPathNewArray(Word objectHeader, int length, int fillSt
throw OutOfMemoryUtil.reportOutOfMemoryError(outOfMemoryError);
}

Object result = slowPathNewArrayWithoutAllocating(hub, length, size, fillStartOffset);
Object result = slowPathNewArrayOrPodWithoutAllocating(hub, length, size, fillStartOffset, podReferenceMap);
runSlowPathHooks();
return result;
} finally {
Expand All @@ -266,26 +276,26 @@ private static Object slowPathNewArray(Word objectHeader, int length, int fillSt
}

@RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate in the implementation of allocation.")
private static Object slowPathNewArrayWithoutAllocating(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset) {
private static Object slowPathNewArrayOrPodWithoutAllocating(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset, byte[] podReferenceMap) {
DeoptTester.disableDeoptTesting();
try {
HeapImpl.exitIfAllocationDisallowed("Heap.allocateNewArray", DynamicHub.toClass(hub).getName());
HeapImpl.exitIfAllocationDisallowed("ThreadLocalAllocation.slowPathNewArrayOrPodWithoutAllocating", DynamicHub.toClass(hub).getName());
GCImpl.getGCImpl().maybeCollectOnAllocation();

if (size.aboveOrEqual(HeapParameters.getLargeArrayThreshold())) {
/* Large arrays go into their own unaligned chunk. */
boolean needsZeroing = !HeapChunkProvider.areUnalignedChunksZeroed();
UnalignedHeapChunk.UnalignedHeader newTlabChunk = HeapImpl.getChunkProvider().produceUnalignedChunk(size);
return allocateLargeArrayInNewTlab(hub, length, size, fillStartOffset, newTlabChunk, needsZeroing);
return allocateLargeArrayOrPodInNewTlab(hub, length, size, fillStartOffset, newTlabChunk, needsZeroing, podReferenceMap);
}
/* Small arrays go into the regular aligned chunk. */

// We might have allocated in the caller and acquired a TLAB with enough space already
// (but we need to check in an uninterruptible method to be safe)
Object array = allocateSmallArrayInCurrentTlab(hub, length, size, fillStartOffset);
Object array = allocateSmallArrayOrPodInCurrentTlab(hub, length, size, fillStartOffset, podReferenceMap);
if (array == null) { // We need a new chunk.
AlignedHeader newTlabChunk = HeapImpl.getChunkProvider().produceAlignedChunk();
array = allocateSmallArrayInNewTlab(hub, length, size, fillStartOffset, newTlabChunk);
array = allocateSmallArrayOrPodInNewTlab(hub, length, size, fillStartOffset, newTlabChunk, podReferenceMap);
}
return array;
} finally {
Expand All @@ -295,28 +305,30 @@ private static Object slowPathNewArrayWithoutAllocating(DynamicHub hub, int leng

@Uninterruptible(reason = "Holds uninitialized memory.")
private static Object allocateInstanceInNewTlab(DynamicHub hub, AlignedHeader newTlabChunk) {
UnsignedWord size = LayoutEncoding.getInstanceSize(hub.getLayoutEncoding());
UnsignedWord size = LayoutEncoding.getPureInstanceSize(hub.getLayoutEncoding());
Pointer memory = allocateRawMemoryInNewTlab(size, newTlabChunk);
return FormatObjectNode.formatObject(memory, DynamicHub.toClass(hub), false, FillContent.WITH_ZEROES, true);
}

@Uninterruptible(reason = "Holds uninitialized memory.")
private static Object allocateSmallArrayInCurrentTlab(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset) {
private static Object allocateSmallArrayOrPodInCurrentTlab(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset, byte[] podReferenceMap) {
if (size.aboveThan(availableTlabMemory(getTlab()))) {
return null;
}
Pointer memory = allocateRawMemoryInTlab(size, getTlab());
return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, false, FillContent.WITH_ZEROES, fillStartOffset, true);
return formatArrayOrPod(memory, hub, length, false, FillContent.WITH_ZEROES, fillStartOffset, podReferenceMap);
}

@Uninterruptible(reason = "Holds uninitialized memory.")
private static Object allocateSmallArrayInNewTlab(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset, AlignedHeader newTlabChunk) {
private static Object allocateSmallArrayOrPodInNewTlab(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset, AlignedHeader newTlabChunk, byte[] podReferenceMap) {
Pointer memory = allocateRawMemoryInNewTlab(size, newTlabChunk);
return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, false, FillContent.WITH_ZEROES, fillStartOffset, true);
return formatArrayOrPod(memory, hub, length, false, FillContent.WITH_ZEROES, fillStartOffset, podReferenceMap);
}

@Uninterruptible(reason = "Holds uninitialized memory, modifies TLAB")
private static Object allocateLargeArrayInNewTlab(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset, UnalignedHeapChunk.UnalignedHeader newTlabChunk, boolean needsZeroing) {
private static Object allocateLargeArrayOrPodInNewTlab(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset,
UnalignedHeader newTlabChunk, boolean needsZeroing, byte[] podReferenceMap) {

ThreadLocalAllocation.Descriptor tlab = getTlab();

HeapChunk.setNext(newTlabChunk, tlab.getUnalignedChunk());
Expand All @@ -338,7 +350,16 @@ private static Object allocateLargeArrayInNewTlab(DynamicHub hub, int length, Un
* any way.
*/
FillContent fillKind = needsZeroing ? FillContent.WITH_ZEROES : FillContent.DO_NOT_FILL;
return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, true, fillKind, fillStartOffset, true);
return formatArrayOrPod(memory, hub, length, true, fillKind, fillStartOffset, podReferenceMap);
}

@Uninterruptible(reason = "Holds uninitialized memory")
private static Object formatArrayOrPod(Pointer memory, DynamicHub hub, int length, boolean unaligned, FillContent fillContent, int fillStartOffset, byte[] podReferenceMap) {
Class<?> clazz = DynamicHub.toClass(hub);
if (podReferenceMap != null) {
return FormatPodNode.formatPod(memory, clazz, length, podReferenceMap, false, unaligned, fillContent, fillStartOffset, true);
}
return FormatArrayNode.formatArray(memory, clazz, length, false, unaligned, fillContent, fillStartOffset, true);
}

@Uninterruptible(reason = "Returns uninitialized memory, modifies TLAB", callerMustBe = true)
Expand Down
Loading