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
3 changes: 3 additions & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

This changelog summarizes major changes to GraalVM Native Image.

## Version 23.1.0
* (GR-35746) Lower the default aligned chunk size from 1 MB to 512 KB for the serial and epsilon GCs, reducing memory usage and image size in many cases.

## Version 23.0.0
* (GR-40187) Report invalid use of SVM specific classes on image class- or module-path as error. As a temporary workaround, `-H:+AllowDeprecatedBuilderClassesOnImageClasspath` allows turning the error into a warning.
* (GR-41196) Provide `.debug.svm.imagebuild.*` sections that contain build options and properties used in the build of the image.
Expand Down
1 change: 1 addition & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@
],
"requiresConcealed" : {
"java.base" : [
"jdk.internal",
"jdk.internal.event",
"jdk.internal.misc",
"jdk.internal.vm.annotation",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public final class SerialAndEpsilonGCOptions {
public static final RuntimeOptionKey<Integer> MaximumYoungGenerationSizePercent = new NotifyGCRuntimeOptionKey<>(10, SerialAndEpsilonGCOptions::serialOrEpsilonGCOnly);

@Option(help = "The size of an aligned chunk. Serial and epsilon GC only.", type = OptionType.Expert) //
public static final HostedOptionKey<Long> AlignedHeapChunkSize = new HostedOptionKey<>(1L * 1024L * 1024L, SerialAndEpsilonGCOptions::serialOrEpsilonGCOnly) {
public static final HostedOptionKey<Long> AlignedHeapChunkSize = new HostedOptionKey<>(512 * 1024L, SerialAndEpsilonGCOptions::serialOrEpsilonGCOnly) {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Long oldValue, Long newValue) {
int multiple = 4096;
Expand All @@ -57,7 +57,7 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Long oldV
* This should be a fraction of the size of an aligned chunk, else large small arrays will not
* fit in an aligned chunk.
*/
@Option(help = "The size at or above which an array will be allocated in its own unaligned chunk. 0 implies (AlignedHeapChunkSize / 8). Serial and epsilon GC only.", type = OptionType.Expert) //
@Option(help = "The size at or above which an array will be allocated in its own unaligned chunk. Serial and epsilon GC only.", type = OptionType.Expert) //
public static final HostedOptionKey<Long> LargeArrayThreshold = new HostedOptionKey<>(0L, SerialAndEpsilonGCOptions::serialOrEpsilonGCOnly);

@Option(help = "Fill unused memory chunks with a sentinel value. Serial and epsilon GC only.", type = OptionType.Debug) //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
*/
package com.oracle.svm.hosted;

import java.lang.annotation.Annotation;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
Expand Down Expand Up @@ -75,15 +74,13 @@
import com.oracle.svm.hosted.meta.HostedMetaAccess;
import com.oracle.svm.hosted.meta.HostedUniverse;
import com.oracle.svm.hosted.substitute.UnsafeAutomaticSubstitutionProcessor;
import com.oracle.svm.util.ReflectionUtil;

import jdk.internal.ValueBased;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;

public class HostedConfiguration {
@SuppressWarnings("unchecked") private static final Class<? extends Annotation> VALUE_BASED_ANNOTATION = //
(Class<? extends Annotation>) ReflectionUtil.lookupClass(false, "jdk.internal.ValueBased");

public HostedConfiguration() {
}
Expand Down Expand Up @@ -269,7 +266,7 @@ protected void processedSynchronizedTypes(BigBang bb, HostedUniverse hUniverse,
* Types that must be immutable cannot have a monitor field.
*/
protected static void maybeSetMonitorField(HostedUniverse hUniverse, Set<AnalysisType> immutableTypes, AnalysisType type) {
if (!type.isArray() && !immutableTypes.contains(type) && !type.isAnnotationPresent(VALUE_BASED_ANNOTATION)) {
if (!type.isArray() && !immutableTypes.contains(type) && !type.isAnnotationPresent(ValueBased.class)) {
setMonitorField(hUniverse, type);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@
import org.junit.Test;

import com.oracle.svm.core.NeverInline;
import com.oracle.svm.core.genscavenge.HeapParameters;
import com.oracle.svm.core.jfr.JfrEvent;
import com.oracle.svm.core.util.UnsignedUtils;

import jdk.jfr.consumer.RecordedClass;
import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.consumer.RecordedThread;

public class TestObjectAllocationInNewTLABEvent extends JfrRecordingTest {
private static final int K = 1024;
private static final int DEFAULT_ALIGNED_HEAP_CHUNK_SIZE = 1024 * K;

@Override
public String[] getTestedEvents() {
Expand All @@ -50,6 +51,8 @@ public String[] getTestedEvents() {

@Override
protected void validateEvents(List<RecordedEvent> events) throws Throwable {
final int alignedHeapChunkSize = UnsignedUtils.safeToInt(HeapParameters.getAlignedHeapChunkSize());

boolean foundBigByteArray = false;
boolean foundSmallByteArray = false;
boolean foundBigCharArray = false;
Expand All @@ -66,16 +69,16 @@ protected void validateEvents(List<RecordedEvent> events) throws Throwable {
String className = event.<RecordedClass> getValue("objectClass").getName();

// >= To account for size of reference
if (allocationSize >= 2 * DEFAULT_ALIGNED_HEAP_CHUNK_SIZE && tlabSize >= 2 * DEFAULT_ALIGNED_HEAP_CHUNK_SIZE) {
if (allocationSize >= 2 * alignedHeapChunkSize && tlabSize >= 2 * alignedHeapChunkSize) {
// verify previous owner
if (className.equals(char[].class.getName())) {
foundBigCharArray = true;
} else if (className.equals(byte[].class.getName())) {
foundBigByteArray = true;
}
} else if (allocationSize >= K && tlabSize == DEFAULT_ALIGNED_HEAP_CHUNK_SIZE && className.equals(byte[].class.getName())) {
} else if (allocationSize >= K && tlabSize == alignedHeapChunkSize && className.equals(byte[].class.getName())) {
foundSmallByteArray = true;
} else if (tlabSize == DEFAULT_ALIGNED_HEAP_CHUNK_SIZE && className.equals(Helper.class.getName())) {
} else if (tlabSize == alignedHeapChunkSize && className.equals(Helper.class.getName())) {
foundInstance = true;
}
}
Expand All @@ -88,17 +91,19 @@ protected void validateEvents(List<RecordedEvent> events) throws Throwable {

@Test
public void test() throws Exception {
final int alignedHeapChunkSize = UnsignedUtils.safeToInt(HeapParameters.getAlignedHeapChunkSize());

// Allocate large arrays (always need a new TLAB).
allocateByteArray(2 * DEFAULT_ALIGNED_HEAP_CHUNK_SIZE);
allocateCharArray(DEFAULT_ALIGNED_HEAP_CHUNK_SIZE);
allocateByteArray(2 * alignedHeapChunkSize);
allocateCharArray(alignedHeapChunkSize);

// Exhaust TLAB with small arrays.
for (int i = 0; i < DEFAULT_ALIGNED_HEAP_CHUNK_SIZE / K; i++) {
for (int i = 0; i < alignedHeapChunkSize / K; i++) {
allocateByteArray(K);
}

// Exhaust TLAB with instances.
for (int i = 0; i < DEFAULT_ALIGNED_HEAP_CHUNK_SIZE; i++) {
for (int i = 0; i < alignedHeapChunkSize; i++) {
allocateInstance();
}
}
Expand Down