Skip to content

Commit 4e39f63

Browse files
authored
Merge pull request #153 from bulasevich/GR-59582
[Backport][GR-59582] Better messages for OutOfMemoryErrors and small cleanups/bugfixes.
2 parents 778eeab + 8eaa8df commit 4e39f63

File tree

12 files changed

+100
-52
lines changed

12 files changed

+100
-52
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.oracle.svm.core.heap.PhysicalMemory;
3838
import com.oracle.svm.core.heap.ReferenceAccess;
3939
import com.oracle.svm.core.util.TimeUtils;
40+
import com.oracle.svm.core.util.UnsignedUtils;
4041
import com.oracle.svm.core.util.VMError;
4142

4243
/** Basic/legacy garbage collection policies. */
@@ -109,9 +110,7 @@ public final UnsignedWord getMaximumHeapSize() {
109110
int maximumHeapSizePercent = HeapParameters.getMaximumHeapSizePercent();
110111
/* Do not cache because `-Xmx` option parsing may not have happened yet. */
111112
UnsignedWord result = physicalMemorySize.unsignedDivide(100).multiply(maximumHeapSizePercent);
112-
if (result.belowThan(addressSpaceSize)) {
113-
return result;
114-
}
113+
return UnsignedUtils.min(result, addressSpaceSize);
115114
}
116115
return addressSpaceSize;
117116
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555
* list. Memory for unaligned chunks is released immediately.
5656
*/
5757
final class HeapChunkProvider {
58+
/** These {@link OutOfMemoryError}s are only needed for legacy code, see GR-59639. */
59+
private static final OutOfMemoryError ALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an aligned heap chunk");
60+
private static final OutOfMemoryError UNALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an unaligned heap chunk");
61+
5862
/**
5963
* The head of the linked list of unused aligned chunks. Chunks are chained using
6064
* {@link HeapChunk#getNext}.
@@ -79,10 +83,6 @@ public UnsignedWord getBytesInUnusedChunks() {
7983
return numUnusedAlignedChunks.get().multiply(HeapParameters.getAlignedHeapChunkSize());
8084
}
8185

82-
private static final OutOfMemoryError ALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an aligned heap chunk");
83-
84-
private static final OutOfMemoryError UNALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an unaligned heap chunk");
85-
8686
/** Acquire a new AlignedHeapChunk, either from the free list or from the operating system. */
8787
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
8888
AlignedHeader produceAlignedChunk() {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,13 @@ public static int getHeapChunkHeaderPadding() {
109109

110110
static int getMaximumYoungGenerationSizePercent() {
111111
int result = SerialAndEpsilonGCOptions.MaximumYoungGenerationSizePercent.getValue();
112-
VMError.guarantee((result >= 0) && (result <= 100), "MaximumYoungGenerationSizePercent should be in [0 ..100]");
112+
VMError.guarantee(result >= 0 && result <= 100, "MaximumYoungGenerationSizePercent should be in [0..100]");
113113
return result;
114114
}
115115

116116
static int getMaximumHeapSizePercent() {
117117
int result = SerialAndEpsilonGCOptions.MaximumHeapSizePercent.getValue();
118-
VMError.guarantee((result >= 0) && (result <= 100), "MaximumHeapSizePercent should be in [0 ..100]");
118+
VMError.guarantee(result >= 0 && result <= 100, "MaximumHeapSizePercent should be in [0..100]");
119119
return result;
120120
}
121121

substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPhysicalMemorySupportImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@
2424
*/
2525
package com.oracle.svm.core.windows;
2626

27+
import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
28+
2729
import org.graalvm.nativeimage.c.struct.SizeOf;
2830
import org.graalvm.word.UnsignedWord;
2931
import org.graalvm.word.WordFactory;
3032

33+
import com.oracle.svm.core.Uninterruptible;
3134
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
3235
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
3336
import com.oracle.svm.core.heap.PhysicalMemory.PhysicalMemorySupport;
@@ -37,6 +40,7 @@
3740
class WindowsPhysicalMemorySupportImpl implements PhysicalMemorySupport {
3841

3942
@Override
43+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
4044
public UnsignedWord size() {
4145
SysinfoAPI.MEMORYSTATUSEX memStatusEx = UnsafeStackValue.get(SysinfoAPI.MEMORYSTATUSEX.class);
4246
memStatusEx.set_dwLength(SizeOf.get(SysinfoAPI.MEMORYSTATUSEX.class));

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/IsolateArgumentParser.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,9 @@ private static CCharPointer startsWith(CCharPointer input, CCharPointer prefix)
429429

430430
@Fold
431431
public static int getOptionIndex(RuntimeOptionKey<?> key) {
432-
for (int i = 0; i < OPTIONS.length; i++) {
433-
if (OPTIONS[i] == key) {
432+
RuntimeOptionKey<?>[] options = OPTIONS;
433+
for (int i = 0; i < options.length; i++) {
434+
if (options[i] == key) {
434435
return i;
435436
}
436437
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateGCOptions.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class SubstrateGCOptions {
4747
@Override
4848
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Long oldValue, Long newValue) {
4949
if (!SubstrateUtil.HOSTED) {
50-
HeapSizeVerifier.verifyMinHeapSizeAgainstAddressSpace(WordFactory.unsigned(newValue));
50+
HeapSizeVerifier.verifyMinHeapSizeAgainstMaxAddressSpaceSize(WordFactory.unsigned(newValue));
5151
}
5252
super.onValueUpdate(values, oldValue, newValue);
5353
}
@@ -58,7 +58,7 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Long oldV
5858
@Override
5959
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Long oldValue, Long newValue) {
6060
if (!SubstrateUtil.HOSTED) {
61-
HeapSizeVerifier.verifyMaxHeapSizeAgainstAddressSpace(WordFactory.unsigned(newValue));
61+
HeapSizeVerifier.verifyMaxHeapSizeAgainstMaxAddressSpaceSize(WordFactory.unsigned(newValue));
6262
}
6363
super.onValueUpdate(values, oldValue, newValue);
6464
}
@@ -69,7 +69,7 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Long oldV
6969
@Override
7070
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Long oldValue, Long newValue) {
7171
if (!SubstrateUtil.HOSTED) {
72-
HeapSizeVerifier.verifyMaxNewSizeAgainstAddressSpace(WordFactory.unsigned(newValue));
72+
HeapSizeVerifier.verifyMaxNewSizeAgainstMaxAddressSpaceSize(WordFactory.unsigned(newValue));
7373
}
7474
super.onValueUpdate(values, oldValue, newValue);
7575
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/AbstractRuntimeCodeInstaller.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class AbstractRuntimeCodeInstaller {
4141
protected Pointer allocateCodeMemory(long size) {
4242
PointerBase result = RuntimeCodeInfoAccess.allocateCodeMemory(WordFactory.unsigned(size));
4343
if (result.isNull()) {
44-
throw new OutOfMemoryError();
44+
throw new OutOfMemoryError("Could not allocate memory for runtime-compiled code.");
4545
}
4646
return (Pointer) result;
4747
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/HeapSizeVerifier.java

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,63 +29,96 @@
2929

3030
import com.oracle.svm.core.SubstrateGCOptions;
3131
import com.oracle.svm.core.SubstrateUtil;
32-
import com.oracle.svm.core.feature.InternalFeature;
3332
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
33+
import com.oracle.svm.core.feature.InternalFeature;
3434
import com.oracle.svm.core.util.UserError;
3535
import com.oracle.svm.core.util.UserError.UserException;
3636

37+
/**
38+
* Verifies that the heap size options are used consistently. Note that some checks seem redundant
39+
* at first glance. However, those checks are needed because options don't necessarily have a value.
40+
*/
3741
public final class HeapSizeVerifier {
42+
private static final String MAX_HEAP_SIZE_NAME = "maximum heap size";
43+
private static final String MIN_HEAP_SIZE_NAME = "minimum heap size";
44+
private static final String MAX_NEW_SIZE_NAME = "maximum new generation size";
45+
46+
/**
47+
* This method is executed once at build-time and once at runtime-time (after parsing all option
48+
* values).
49+
*/
3850
public static void verifyHeapOptions() {
39-
UnsignedWord minHeapSize = WordFactory.unsigned(SubstrateGCOptions.MinHeapSize.getValue());
51+
verifyReservedAddressSpaceSize();
52+
verifyMaxHeapSize();
53+
verifyMinHeapSize();
54+
verifyMaxNewSize();
55+
}
56+
57+
private static void verifyReservedAddressSpaceSize() {
58+
UnsignedWord reservedAddressSpaceSize = WordFactory.unsigned(SubstrateGCOptions.ReservedAddressSpaceSize.getValue());
59+
verifyAgainstMaxAddressSpaceSize(reservedAddressSpaceSize, "value of the option '" + SubstrateGCOptions.ReservedAddressSpaceSize.getName() + "'");
60+
}
61+
62+
private static void verifyMaxHeapSize() {
4063
UnsignedWord maxHeapSize = WordFactory.unsigned(SubstrateGCOptions.MaxHeapSize.getValue());
41-
UnsignedWord maxNewSize = WordFactory.unsigned(SubstrateGCOptions.MaxNewSize.getValue());
64+
verifyMaxHeapSizeAgainstMaxAddressSpaceSize(maxHeapSize);
65+
verifyAgainstReservedAddressSpaceSize(maxHeapSize, MAX_HEAP_SIZE_NAME);
66+
}
67+
68+
private static void verifyMinHeapSize() {
69+
UnsignedWord minHeapSize = WordFactory.unsigned(SubstrateGCOptions.MinHeapSize.getValue());
70+
verifyMinHeapSizeAgainstMaxAddressSpaceSize(minHeapSize);
71+
verifyAgainstReservedAddressSpaceSize(minHeapSize, MIN_HEAP_SIZE_NAME);
4272

43-
verifyMaxHeapSizeAgainstAddressSpace(maxHeapSize);
44-
verifyMinHeapSizeAgainstAddressSpace(minHeapSize);
45-
verifyMaxNewSizeAgainstAddressSpace(maxNewSize);
46-
verifyMinHeapSizeAgainstMaxHeapSize(minHeapSize);
47-
verifyMaxNewSizeAgainstMaxHeapSize(maxHeapSize);
73+
UnsignedWord maxHeapSize = WordFactory.unsigned(SubstrateGCOptions.MaxHeapSize.getValue());
74+
if (maxHeapSize.notEqual(0) && minHeapSize.aboveThan(maxHeapSize)) {
75+
throwError(minHeapSize, MIN_HEAP_SIZE_NAME, maxHeapSize, MAX_HEAP_SIZE_NAME);
76+
}
4877
}
4978

50-
public static void verifyMinHeapSizeAgainstAddressSpace(UnsignedWord minHeapSize) throws UserException {
51-
verifyAgainstAddressSpace(minHeapSize, "minimum heap size");
79+
private static void verifyMaxNewSize() {
80+
UnsignedWord maxNewSize = WordFactory.unsigned(SubstrateGCOptions.MaxNewSize.getValue());
81+
verifyMaxNewSizeAgainstMaxAddressSpaceSize(maxNewSize);
82+
verifyAgainstReservedAddressSpaceSize(maxNewSize, MAX_NEW_SIZE_NAME);
83+
84+
UnsignedWord maxHeapSize = WordFactory.unsigned(SubstrateGCOptions.MaxHeapSize.getValue());
85+
if (maxHeapSize.notEqual(0) && maxNewSize.aboveThan(maxHeapSize)) {
86+
throwError(maxNewSize, MAX_NEW_SIZE_NAME, maxHeapSize, MAX_HEAP_SIZE_NAME);
87+
}
5288
}
5389

54-
public static void verifyMaxHeapSizeAgainstAddressSpace(UnsignedWord maxHeapSize) throws UserException {
55-
verifyAgainstAddressSpace(maxHeapSize, "maximum heap size");
90+
public static void verifyMinHeapSizeAgainstMaxAddressSpaceSize(UnsignedWord minHeapSize) throws UserException {
91+
verifyAgainstMaxAddressSpaceSize(minHeapSize, MIN_HEAP_SIZE_NAME);
5692
}
5793

58-
public static void verifyMaxNewSizeAgainstAddressSpace(UnsignedWord maxNewSize) {
59-
verifyAgainstAddressSpace(maxNewSize, "maximum new generation size");
94+
public static void verifyMaxHeapSizeAgainstMaxAddressSpaceSize(UnsignedWord maxHeapSize) throws UserException {
95+
verifyAgainstMaxAddressSpaceSize(maxHeapSize, MAX_HEAP_SIZE_NAME);
6096
}
6197

62-
private static void verifyAgainstAddressSpace(UnsignedWord actualValue, String actualValueName) {
63-
UnsignedWord addressSpaceSize = ReferenceAccess.singleton().getAddressSpaceSize();
64-
if (actualValue.aboveThan(addressSpaceSize)) {
65-
throwError(actualValue, actualValueName, addressSpaceSize, "largest possible address space");
66-
}
98+
public static void verifyMaxNewSizeAgainstMaxAddressSpaceSize(UnsignedWord maxNewSize) {
99+
verifyAgainstMaxAddressSpaceSize(maxNewSize, MAX_NEW_SIZE_NAME);
67100
}
68101

69-
private static void verifyMinHeapSizeAgainstMaxHeapSize(UnsignedWord minHeapSize) {
70-
UnsignedWord maxHeapSize = WordFactory.unsigned(SubstrateGCOptions.MaxHeapSize.getValue());
71-
if (maxHeapSize.notEqual(0) && minHeapSize.aboveThan(maxHeapSize)) {
72-
throwError(minHeapSize, "minimum heap size", maxHeapSize, "maximum heap size");
102+
private static void verifyAgainstMaxAddressSpaceSize(UnsignedWord actualValue, String actualValueName) {
103+
UnsignedWord maxAddressSpaceSize = ReferenceAccess.singleton().getAddressSpaceSize();
104+
if (actualValue.aboveThan(maxAddressSpaceSize)) {
105+
throwError(actualValue, actualValueName, maxAddressSpaceSize, "largest possible heap address space");
73106
}
74107
}
75108

76-
private static void verifyMaxNewSizeAgainstMaxHeapSize(UnsignedWord maxNewSize) {
77-
UnsignedWord maxHeapSize = WordFactory.unsigned(SubstrateGCOptions.MaxHeapSize.getValue());
78-
if (maxHeapSize.notEqual(0) && maxNewSize.aboveThan(maxHeapSize)) {
79-
throwError(maxNewSize, "maximum new generation size", maxHeapSize, "maximum heap size");
109+
private static void verifyAgainstReservedAddressSpaceSize(UnsignedWord actualValue, String actualValueName) {
110+
UnsignedWord reservedAddressSpaceSize = WordFactory.unsigned(SubstrateGCOptions.ReservedAddressSpaceSize.getValue());
111+
if (reservedAddressSpaceSize.notEqual(0) && actualValue.aboveThan(reservedAddressSpaceSize)) {
112+
throwError(actualValue, actualValueName, reservedAddressSpaceSize, "value of the option '" + SubstrateGCOptions.ReservedAddressSpaceSize.getName() + "'");
80113
}
81114
}
82115

83116
private static void throwError(UnsignedWord actualValue, String actualValueName, UnsignedWord maxValue, String maxValueName) throws UserException {
84117
if (SubstrateUtil.HOSTED) {
85-
throw UserError.abort("The specified %s (%s) is larger than the %s (%s).", actualValueName, format(actualValue), maxValueName, format(maxValue));
118+
throw UserError.abort("The specified %s (%s) must not be larger than the %s (%s).", actualValueName, format(actualValue), maxValueName, format(maxValue));
86119
} else {
87120
throw new IllegalArgumentException(
88-
"The specified " + actualValueName + " (" + format(actualValue) + ") is larger than the " + maxValueName + " (" + format(maxValue) + ").");
121+
"The specified " + actualValueName + " (" + format(actualValue) + ") must not be larger than the " + maxValueName + " (" + format(maxValue) + ").");
89122
}
90123
}
91124

@@ -105,8 +138,7 @@ private static String format(UnsignedWord bytes) {
105138
class HostedHeapSizeVerifierFeature implements InternalFeature {
106139
@Override
107140
public void beforeAnalysis(BeforeAnalysisAccess access) {
108-
// At build-time, we can do a reasonable GC-independent verification of all the heap size
109-
// settings.
141+
/* At build-time, we can do a GC-independent verification of all the heap size settings. */
110142
HeapSizeVerifier.verifyHeapOptions();
111143
}
112144
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrTypeRepository.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,8 @@ private long getClassLoaderId(TypeInfo typeInfo, ClassLoader classLoader) {
314314
return flushedClassLoaders.get(classLoader);
315315
}
316316
return typeInfo.classLoaders.get(classLoader);
317-
} else {
318-
return 0;
319317
}
318+
return 0;
320319
}
321320

322321
private void clearEpochData() {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractImageHeapProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ protected static UnsignedWord getImageHeapAddressSpaceSize() {
4141
}
4242

4343
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
44-
protected static UnsignedWord getImageHeapSizeInFile() {
44+
public static UnsignedWord getImageHeapSizeInFile() {
4545
Word imageHeapBegin = IMAGE_HEAP_BEGIN.get();
4646
return IMAGE_HEAP_END.get().subtract(imageHeapBegin);
4747
}

0 commit comments

Comments
 (0)