Skip to content
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 @@ -27,6 +27,7 @@
import java.nio.ByteBuffer;
import java.util.List;

import org.graalvm.nativeimage.ImageInfo;
import org.graalvm.word.UnsignedWord;

import com.oracle.svm.core.SubstrateOptions;
Expand All @@ -41,6 +42,8 @@
import com.oracle.svm.core.image.ImageHeapLayoutInfo;
import com.oracle.svm.core.image.ImageHeapLayouter;
import com.oracle.svm.core.image.ImageHeapObject;
import com.oracle.svm.core.option.SubstrateOptionsParser;
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.core.common.NumUtil;
Expand Down Expand Up @@ -75,6 +78,8 @@ public class ChunkedImageHeapLayouter implements ImageHeapLayouter {
private static final int READ_ONLY_HUGE = WRITABLE_HUGE + 1;
private static final int PARTITION_COUNT = READ_ONLY_HUGE + 1;

private static final String ALIGNED_HEAP_CHUNK_OPTION = SubstrateOptionsParser.commandArgument(SerialAndEpsilonGCOptions.AlignedHeapChunkSize, "<2^n>");

private final ChunkedImageHeapPartition[] partitions;
private final ImageHeapInfo heapInfo;
private final long startOffset;
Expand Down Expand Up @@ -120,15 +125,21 @@ private ChunkedImageHeapPartition choosePartition(ImageHeapObject info, boolean
if (patched) {
return getWritablePatched();
} else if (immutable) {
if (hasRelocatables) {
VMError.guarantee(info.getSize() < hugeObjectThreshold, "Objects with relocatable pointers cannot be huge objects");
return getReadOnlyRelocatable();
}
if (info.getSize() >= hugeObjectThreshold) {
VMError.guarantee(info.getObjectClass() != DynamicHub.class, "Class metadata (dynamic hubs) cannot be huge objects");
if (hasRelocatables) {
if (info.getObjectClass() == DynamicHub.class) {
throw reportHugeObjectError(info, "Class metadata (dynamic hubs) cannot be huge objects: the dynamic hub %s", info.getObject().toString());
}
throw reportHugeObjectError(info, "Objects in image heap with relocatable pointers cannot be huge objects. Detected an object of type %s",
info.getObject().getClass().getTypeName());
}
return getReadOnlyHuge();
}
return getReadOnlyRegular();
if (hasRelocatables) {
return getReadOnlyRelocatable();
} else {
return getReadOnlyRegular();
}
} else {
assert info.getObjectClass() != DynamicHub.class : "Class metadata (dynamic hubs) cannot be writable";
if (info.getSize() >= hugeObjectThreshold) {
Expand All @@ -138,6 +149,16 @@ private ChunkedImageHeapPartition choosePartition(ImageHeapObject info, boolean
}
}

private Error reportHugeObjectError(ImageHeapObject info, String objectTypeMsg, String objectText) {
String msg = String.format(objectTypeMsg + " with size %d B and the limit is %d B. Use '%s' to increase GC chunk size to be larger than the object.",
objectText, info.getSize(), hugeObjectThreshold, ALIGNED_HEAP_CHUNK_OPTION);
if (ImageInfo.inImageBuildtimeCode()) {
throw UserError.abort(msg);
} else {
throw VMError.shouldNotReachHere(msg);
}
}

@Override
public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
int objectAlignment = ConfigurationValues.getObjectLayout().getAlignment();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,12 @@
*/
package com.oracle.svm.core.genscavenge;

import org.graalvm.collections.EconomicMap;

import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.option.HostedOptionKey;
import com.oracle.svm.core.option.NotifyGCRuntimeOptionKey;
import com.oracle.svm.core.option.RuntimeOptionKey;
import com.oracle.svm.core.util.UserError;

import jdk.graal.compiler.options.Option;
import jdk.graal.compiler.options.OptionKey;
import jdk.graal.compiler.options.OptionType;

/** Common options that can be specified for both the serial and the epsilon GC. */
Expand All @@ -45,13 +41,7 @@ public final class SerialAndEpsilonGCOptions {
public static final RuntimeOptionKey<Integer> MaximumYoungGenerationSizePercent = new NotifyGCRuntimeOptionKey<>(10, SerialAndEpsilonGCOptions::validateSerialOrEpsilonRuntimeOption);

@Option(help = "The size of an aligned chunk. Serial and epsilon GC only.", type = OptionType.Expert) //
public static final HostedOptionKey<Long> AlignedHeapChunkSize = new HostedOptionKey<>(512 * 1024L, SerialAndEpsilonGCOptions::validateSerialOrEpsilonHostedOption) {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Long oldValue, Long newValue) {
int multiple = 4096;
UserError.guarantee(newValue > 0 && newValue % multiple == 0, "%s value must be a multiple of %d.", getName(), multiple);
}
};
public static final HostedOptionKey<Long> AlignedHeapChunkSize = new HostedOptionKey<>(512 * 1024L, SerialAndEpsilonGCOptions::validateSerialOrEpsilonHostedOption);

/*
* This should be a fraction of the size of an aligned chunk, else large small arrays will not
Expand Down
Loading