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
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-44216) Native Image is now shipped as part of the GraalVM JDK and thus no longer needs to be installed via `gu install native-image`.
* (GR-44105) A warning is displayed when trying to generate debug info on macOS since that is not supported. It is now an error to use `-H:+StripDebugInfo` on macOS or `-H:-StripDebugInfo` on Windows since those values are not supported.
* (GR-43966) Remove analysis options -H:AnalysisStatisticsFile and -H:ImageBuildStatisticsFile. Output files are now written to fixed subdirectories relative to image location (reports/image_build_statistics.json).
* (GR-38414) BellSoft implemented the `MemoryPoolMXBean` for the serial and epsilon GCs.
* (GR-40641) Dynamic linking of AWT libraries on Linux.

## Version 22.3.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

import java.util.concurrent.atomic.AtomicBoolean;

import com.oracle.svm.core.heap.GCCause;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.nodes.PauseNode;
import org.graalvm.nativeimage.Platform;
Expand All @@ -36,6 +35,7 @@

import com.oracle.svm.core.SubstrateGCOptions;
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.heap.GCCause;
import com.oracle.svm.core.heap.PhysicalMemory;
import com.oracle.svm.core.heap.ReferenceAccess;
import com.oracle.svm.core.jdk.UninterruptibleUtils;
Expand Down Expand Up @@ -193,13 +193,21 @@ private void updateSizeParametersLocked(SizeParameters params, SizeParameters pr
* but we must still ensure that computations can handle it (for example, no overflows).
*/
survivorSize = UnsignedUtils.min(survivorSize, params.maxSurvivorSize());
edenSize = UnsignedUtils.min(edenSize, maxEdenSize());
edenSize = UnsignedUtils.min(edenSize, getMaximumEdenSize());
oldSize = UnsignedUtils.min(oldSize, params.maxOldSize());
promoSize = UnsignedUtils.min(promoSize, params.maxOldSize());
}

@Override
public UnsignedWord getInitialEdenSize() {
guaranteeSizeParametersInitialized();
return sizes.initialEdenSize;
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
protected UnsignedWord maxEdenSize() {
public UnsignedWord getMaximumEdenSize() {
guaranteeSizeParametersInitialized();
return alignDown(sizes.maxYoungSize.subtract(survivorSize.multiply(2)));
}

Expand All @@ -215,6 +223,18 @@ public UnsignedWord getMaximumYoungGenerationSize() {
return sizes.maxYoungSize;
}

@Override
public UnsignedWord getInitialSurvivorSize() {
guaranteeSizeParametersInitialized();
return sizes.initialSurvivorSize;
}

@Override
public UnsignedWord getMaximumSurvivorSize() {
guaranteeSizeParametersInitialized();
return sizes.maxSurvivorSize();
}

@Override
public UnsignedWord getCurrentHeapCapacity() {
assert VMOperation.isGCInProgress() : "use only during GC";
Expand All @@ -236,6 +256,18 @@ public UnsignedWord getYoungGenerationCapacity() {
return edenSize.add(survivorSize);
}

@Override
public UnsignedWord getInitialOldSize() {
guaranteeSizeParametersInitialized();
return sizes.initialOldSize();
}

@Override
public UnsignedWord getMaximumOldSize() {
guaranteeSizeParametersInitialized();
return sizes.maxOldSize();
}

@Override
public UnsignedWord getOldGenerationCapacity() {
guaranteeSizeParametersInitialized();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2023, BELLSOFT. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.genscavenge;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryType;
import java.lang.management.MemoryUsage;
import java.util.Arrays;

import javax.management.ObjectName;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.UnsignedWord;
import org.graalvm.word.WordFactory;

import com.oracle.svm.core.heap.AbstractMXBean;
import com.oracle.svm.core.jdk.UninterruptibleUtils;

import sun.management.Util;

public abstract class AbstractMemoryPoolMXBean extends AbstractMXBean implements MemoryPoolMXBean {

private final String name;
private final String[] managerNames;
protected final UninterruptibleUtils.AtomicUnsigned peakUsage = new UninterruptibleUtils.AtomicUnsigned();

private static final UnsignedWord UNDEFINED = WordFactory.zero();
protected UnsignedWord initialValue = UNDEFINED;

@Platforms(Platform.HOSTED_ONLY.class)
protected AbstractMemoryPoolMXBean(String name, String... managerNames) {
this.name = name;
this.managerNames = managerNames;
}

UnsignedWord getInitialValue() {
if (initialValue.equal(UNDEFINED)) {
initialValue = computeInitialValue();
}
return initialValue;
}

abstract UnsignedWord computeInitialValue();

abstract UnsignedWord getMaximumValue();

abstract void afterCollection(GCAccounting accounting);

MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) {
return new MemoryUsage(getInitialValue().rawValue(), usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), getMaximumValue().rawValue());
}

MemoryUsage memoryUsage(UnsignedWord used, UnsignedWord committed) {
return new MemoryUsage(getInitialValue().rawValue(), used.rawValue(), committed.rawValue(), getMaximumValue().rawValue());
}

@Override
public String getName() {
return name;
}

@Override
public String[] getMemoryManagerNames() {
return Arrays.copyOf(managerNames, managerNames.length);
}

@Override
public ObjectName getObjectName() {
return Util.newObjectName(ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=" + name);
}

@Override
public MemoryType getType() {
return MemoryType.HEAP;
}

@Override
public boolean isValid() {
return true;
}

@Override
public boolean isUsageThresholdSupported() {
return false;
}

@Override
public long getUsageThreshold() {
throw new UnsupportedOperationException("Usage threshold is not supported");
}

@Override
public void setUsageThreshold(long l) {
throw new UnsupportedOperationException("Usage threshold is not supported");
}

@Override
public boolean isUsageThresholdExceeded() {
throw new UnsupportedOperationException("Usage threshold is not supported");
}

@Override
public long getUsageThresholdCount() {
throw new UnsupportedOperationException("Usage threshold is not supported");
}

@Override
public boolean isCollectionUsageThresholdSupported() {
return false;
}

@Override
public long getCollectionUsageThreshold() {
throw new UnsupportedOperationException("Collection usage threshold is not supported");
}

@Override
public void setCollectionUsageThreshold(long l) {
throw new UnsupportedOperationException("Collection usage threshold is not supported");
}

@Override
public boolean isCollectionUsageThresholdExceeded() {
throw new UnsupportedOperationException("Collection usage threshold is not supported");
}

@Override
public long getCollectionUsageThresholdCount() {
throw new UnsupportedOperationException("Collection usage threshold is not supported");
}

@Override
public void resetPeakUsage() {
peakUsage.set(WordFactory.zero());
}

void updatePeakUsage(UnsignedWord value) {
UnsignedWord current;
do {
current = peakUsage.get();
} while (value.aboveThan(current) && !peakUsage.compareAndSet(current, value));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ protected void computeEdenSpaceSize(@SuppressWarnings("unused") boolean complete
assert isAligned(desiredEdenSize);
desiredEdenSize = minSpaceSize(desiredEdenSize);

UnsignedWord edenLimit = maxEdenSize();
UnsignedWord edenLimit = getMaximumEdenSize();
if (desiredEdenSize.aboveThan(edenLimit)) {
/*
* If the policy says to get a larger eden but is hitting the limit, don't decrease
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ public void updateSizeParameters() {
// Size parameters are recomputed from current values whenever they are queried
}

@Override
public UnsignedWord getInitialEdenSize() {
return UNDEFINED;
}

@Override
public UnsignedWord getMaximumEdenSize() {
return getMaximumYoungGenerationSize();
}

@Override
public final UnsignedWord getMaximumHeapSize() {
long runtimeValue = SubstrateGCOptions.MaxHeapSize.getValue();
Expand Down Expand Up @@ -146,6 +156,16 @@ public final UnsignedWord getMinimumHeapSize() {
return result;
}

@Override
public UnsignedWord getInitialSurvivorSize() {
return UNDEFINED;
}

@Override
public UnsignedWord getMaximumSurvivorSize() {
return WordFactory.zero();
}

@Override
public UnsignedWord getSurvivorSpacesCapacity() {
return WordFactory.zero();
Expand All @@ -156,6 +176,11 @@ public UnsignedWord getYoungGenerationCapacity() {
return getMaximumYoungGenerationSize();
}

@Override
public UnsignedWord getInitialOldSize() {
return UNDEFINED;
}

@Override
public UnsignedWord getOldGenerationCapacity() {
UnsignedWord heapCapacity = getCurrentHeapCapacity();
Expand All @@ -166,6 +191,11 @@ public UnsignedWord getOldGenerationCapacity() {
return heapCapacity.subtract(youngCapacity);
}

@Override
public UnsignedWord getMaximumOldSize() {
return getOldGenerationCapacity();
}

@Override
public final UnsignedWord getMaximumFreeAlignedChunksSize() {
return getMaximumYoungGenerationSize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.UnsignedWord;
import org.graalvm.word.WordFactory;

import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.heap.GCCause;
Expand All @@ -36,6 +37,8 @@

/** The interface for a garbage collection policy. All sizes are in bytes. */
public interface CollectionPolicy {
UnsignedWord UNDEFINED = WordFactory.unsigned(-1);

@Platforms(Platform.HOSTED_ONLY.class)
static String getInitialPolicyName() {
if (SubstrateOptions.UseEpsilonGC.getValue()) {
Expand Down Expand Up @@ -143,6 +146,11 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) {
*/
UnsignedWord getCurrentHeapCapacity();

/** May be {@link #UNDEFINED}. */
UnsignedWord getInitialEdenSize();

UnsignedWord getMaximumEdenSize();

/**
* The hard limit for the size of the entire heap. Exceeding this limit triggers an
* {@link OutOfMemoryError}.
Expand All @@ -158,6 +166,11 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) {
/** The minimum heap size, for inclusion in diagnostic output. */
UnsignedWord getMinimumHeapSize();

/** May be {@link #UNDEFINED}. */
UnsignedWord getInitialSurvivorSize();

UnsignedWord getMaximumSurvivorSize();

/**
* The total capacity of all survivor-from spaces of all ages, equal to the size of all
* survivor-to spaces of all ages. In other words, when copying during a collection, up to 2x
Expand All @@ -168,9 +181,14 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) {
/** The capacity of the young generation, comprising the eden and survivor spaces. */
UnsignedWord getYoungGenerationCapacity();

/** May be {@link #UNDEFINED}. */
UnsignedWord getInitialOldSize();

/** The capacity of the old generation. */
UnsignedWord getOldGenerationCapacity();

UnsignedWord getMaximumOldSize();

/**
* The maximum number of bytes that should be kept readily available for allocation or copying
* during collections.
Expand All @@ -189,5 +207,4 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) {

/** Called before the end of a collection, in the safepoint operation. */
void onCollectionEnd(boolean completeCollection, GCCause cause);

}
Loading