Skip to content

[GR-61959] SVM: Add shared arena support. #11125

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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 @@ -47,6 +47,13 @@ public final class GraalDirectives {
public static final double SLOWPATH_PROBABILITY = 0.0001;
public static final double FASTPATH_PROBABILITY = 1.0 - SLOWPATH_PROBABILITY;

/**
* Forces a safepoint in the compiled code.
*/
public static void safepoint() {

}

/**
* Directive for the compiler to fall back to the bytecode interpreter at this point. All
* arguments to this method must be compile-time constant.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,24 @@ public final boolean hasExactlyOneUsageOfType(InputType inputType) {
return numUses == 1;
}

/**
* Checks whether {@code this} has any usages of type {@code inputType}.
*
* @param inputType the type of usages to look for
*/
public final boolean hasUsagesOfType(InputType inputType) {
for (Node usage : usages()) {
for (Position pos : usage.inputPositions()) {
if (pos.get(usage) == this) {
if (pos.getInputType() == inputType) {
return true;
}
}
}
}
return false;
}

/**
* Adds a given node to this node's {@linkplain #usages() usages}.
*
Expand Down Expand Up @@ -1179,6 +1197,38 @@ public void replaceAtUsages(Node replacement, InputType inputType) {
}
}

/**
* For each use of {@code this} in another node, {@code n}, replace it with {@code replacement}
* if the type of the use is in {@code inputTypes} and if {@code filter.test(n) == true}.
*
* @see #replaceAtUsages(Node)
*/
public void replaceAtUsages(Node replacement, Predicate<Node> filter, InputType inputType) {
checkReplaceWith(replacement);
int i = 0;
int usageCount = this.getUsageCount();
if (usageCount == 0) {
return;
}
usages: while (i < usageCount) {
Node usage = this.getUsageAt(i);
if (filter.test(usage)) {
for (Position pos : usage.inputPositions()) {
if (pos.getInputType() == inputType && pos.get(usage) == this) {
replaceAtUsagePos(replacement, usage, pos);
this.movUsageFromEndTo(i);
usageCount--;
continue usages;
}
}
}
i++;
}
if (hasNoUsages()) {
maybeNotifyZeroUsages(this);
}
}

/**
* For each use of {@code this} in another node, {@code n}, replace it with {@code replacement}
* if the type of the use is in {@code inputTypes}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,13 @@ public FrameState(int bci) {
* @param bci this must be {@link BytecodeFrame#AFTER_BCI}
*/
public FrameState(int bci, ValueNode returnValueOrExceptionObject) {
this(null, null, bci, 0, returnValueOrExceptionObject.getStackKind().getSlotCount(), 0, returnValueOrExceptionObject instanceof ExceptionObjectNode ? StackState.Rethrow : StackState.BeforePop,
this(bci, returnValueOrExceptionObject, null, true);
}

public FrameState(int bci, ValueNode returnValueOrExceptionObject, Bytecode code, boolean checkBCI) {
this(null, code, bci, 0, returnValueOrExceptionObject.getStackKind().getSlotCount(), 0, returnValueOrExceptionObject instanceof ExceptionObjectNode ? StackState.Rethrow : StackState.BeforePop,
true, null, null);
assert (bci == BytecodeFrame.AFTER_BCI && !rethrowException()) || (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && rethrowException()) : Assertions.errorMessage(bci);
assert !checkBCI || (bci == BytecodeFrame.AFTER_BCI && !rethrowException()) || (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && rethrowException()) : Assertions.errorMessage(bci);
ValueNode[] stack = {returnValueOrExceptionObject};
this.values = new NodeInputList<>(this, stack);
}
Expand Down Expand Up @@ -568,7 +572,7 @@ public FrameState duplicateModified(JavaKind popKind,
ValueNode pushedValue,
List<EscapeObjectState> pushedVirtualObjectMappings) {
assert pushedValue != null;
assert pushedValue.getStackKind() == popKind : Assertions.errorMessage(pushedValue, popKind, this);
assert pushedValue.getStackKind() == pushedSlotKind : Assertions.errorMessage(pushedValue, popKind, this);
return duplicateModified(graph(), bci, stackState, popKind, new JavaKind[]{pushedSlotKind}, new ValueNode[]{pushedValue}, pushedVirtualObjectMappings);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,10 @@ public UnwindNode(ValueNode exception) {
public void generate(NodeLIRBuilderTool gen) {
gen.getLIRGeneratorTool().emitUnwind(gen.operand(exception()));
}

public void setException(ValueNode exception) {
updateUsages(this.exception, exception);
this.exception = exception;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import static jdk.graal.compiler.core.common.type.StampFactory.objectNonNull;
import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;

import java.util.List;

import jdk.graal.compiler.bytecode.Bytecode;
import jdk.graal.compiler.core.common.type.AbstractPointerStamp;
import jdk.graal.compiler.core.common.type.IntegerStamp;
Expand Down Expand Up @@ -71,6 +73,7 @@
import jdk.graal.compiler.nodes.extended.GuardingNode;
import jdk.graal.compiler.nodes.java.InstanceOfDynamicNode;
import jdk.graal.compiler.nodes.type.StampTool;
import jdk.internal.misc.ScopedMemoryAccess;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.DeoptimizationAction;
Expand Down Expand Up @@ -595,4 +598,22 @@ static <T extends Node> T setStateAfterIfNecessary(GraphBuilderContext b, T valu
default boolean currentBlockCatchesOOME() {
return false;
}

/**
* Iff this parsing context is processing a method that is annotated with
* {@link ScopedMemoryAccess} saves the associated session object.
*
* @param scopedMemorySession the currently parsed session of this context
*/
default void setIsParsingScopedMemoryMethod(ValueNode scopedMemorySession) {
// nothing to do
}

/**
* Determines if the current parsing context has set any scoped memory access that needs to be
* handled.
*/
default List<ValueNode> getScopedMemorySessions() {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import org.graalvm.word.LocationIdentity;

import jdk.graal.compiler.core.common.type.Stamp;
import jdk.graal.compiler.core.common.type.StampFactory;
import jdk.graal.compiler.core.common.type.TypeReference;
import jdk.graal.compiler.debug.GraalError;
Expand Down Expand Up @@ -75,6 +76,10 @@ public ExceptionObjectNode(MetaAccessProvider metaAccess) {
super(TYPE, StampFactory.objectNonNull(TypeReference.createTrustedWithoutAssumptions(metaAccess.lookupJavaType(Throwable.class))));
}

public ExceptionObjectNode(Stamp s) {
super(TYPE, s);
}

@Override
public LocationIdentity getKilledLocationIdentity() {
return LocationIdentity.any();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
import jdk.graal.compiler.nodes.NamedLocationIdentity;
import jdk.graal.compiler.nodes.NodeView;
import jdk.graal.compiler.nodes.PiNode;
import jdk.graal.compiler.nodes.SafepointNode;
import jdk.graal.compiler.nodes.ProfileData.BranchProbabilityData;
import jdk.graal.compiler.nodes.SpinWaitNode;
import jdk.graal.compiler.nodes.StateSplit;
Expand Down Expand Up @@ -720,7 +721,8 @@ private static void registerUnsafePlugins(InvocationPlugins plugins, Replacement
jdkInternalMiscUnsafe.register(new AllocateUninitializedArrayPlugin("allocateUninitializedArray0", false));
}

private static void registerUnsafeAtomicsPlugins(Registration r, boolean isSunMiscUnsafe, boolean explicitUnsafeNullChecks, String casPrefix, JavaKind[] supportedJavaKinds,
private static void registerUnsafeAtomicsPlugins(Registration r, boolean isSunMiscUnsafe, boolean explicitUnsafeNullChecks, String casPrefix,
JavaKind[] supportedJavaKinds,
MemoryOrderMode... memoryOrders) {
for (JavaKind kind : supportedJavaKinds) {
Class<?> javaClass = getJavaClass(kind);
Expand Down Expand Up @@ -787,7 +789,8 @@ private static void registerUnsafePlugins0(Registration r, boolean sunMiscUnsafe
r.register(new UnsafePutPlugin(kind, explicitUnsafeNullChecks, putName, Receiver.class, Object.class, long.class, javaClass));
// Volatile object-based accesses
r.register(new UnsafeGetPlugin(kind, MemoryOrderMode.VOLATILE, explicitUnsafeNullChecks, getName + "Volatile", Receiver.class, Object.class, long.class));
r.register(new UnsafePutPlugin(kind, MemoryOrderMode.VOLATILE, explicitUnsafeNullChecks, putName + "Volatile", Receiver.class, Object.class, long.class, javaClass));
r.register(new UnsafePutPlugin(kind, MemoryOrderMode.VOLATILE, explicitUnsafeNullChecks, putName + "Volatile", Receiver.class, Object.class, long.class,
javaClass));
// Ordered object-based accesses
if (sunMiscUnsafe) {
if (kind == JavaKind.Int || kind == JavaKind.Long || kind == JavaKind.Object) {
Expand Down Expand Up @@ -1546,11 +1549,13 @@ private static FixedWithNextNode createMemoryAccessNode(StructuredGraph graph, U
return nodeConstructor.create(ConstantNode.forLong(0L, graph), OFF_HEAP_LOCATION);
}

private void setAccessNodeResult(FixedWithNextNode node, GraphBuilderContext b) {
private FixedWithNextNode setAccessNodeResult(FixedWithNextNode node, GraphBuilderContext b) {
if (returnKind != JavaKind.Void) {
b.addPush(returnKind, node);
return node;
} else {
b.add(node);
return node;
}
}

Expand Down Expand Up @@ -1582,8 +1587,8 @@ protected final void createUnsafeAccess(ValueNode value, GraphBuilderContext b,
FixedWithNextNode[] accessNodes = new FixedWithNextNode[]{objectAccess, memoryAccess};

LogicNode condition = graph.addOrUniqueWithInputs(IsNullNode.create(value));
// We do not know the probability of this being a native memory or object, thus we
// inject 0.5. We still inject it to ensure no code verifying profiles reports
// We do not know the probability of this being a native memory or object, thus
// we inject 0.5. We still inject it to ensure no code verifying profiles reports
// missing ones.
BranchProbabilityData probability = BranchProbabilityData.injected(0.5, true);
IfNode ifNode = b.add(new IfNode(condition, memoryAccess, objectAccess, probability));
Expand Down Expand Up @@ -1616,6 +1621,7 @@ protected final void createUnsafeAccess(ValueNode value, GraphBuilderContext b,
}
b.setStateAfter(merge);
}

}
}

Expand Down Expand Up @@ -1651,7 +1657,10 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
// Emits a null-check for the otherwise unused receiver
unsafe.get(true);
// Note that non-ordered raw accesses can be turned into floatable field accesses.
UnsafeNodeConstructor unsafeNodeConstructor = (obj, loc) -> new RawLoadNode(obj, offset, unsafeAccessKind, loc, memoryOrder);
UnsafeNodeConstructor unsafeNodeConstructor = (obj, loc) -> {
RawLoadNode rl = new RawLoadNode(obj, offset, unsafeAccessKind, loc, memoryOrder);
return rl;
};
createUnsafeAccess(object, b, unsafeNodeConstructor, RawLoadNode.class);
return true;
}
Expand Down Expand Up @@ -1691,7 +1700,10 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
// Emits a null-check for the otherwise unused receiver
unsafe.get(true);
ValueNode maskedValue = b.maskSubWordValue(value, unsafeAccessKind);
createUnsafeAccess(object, b, (obj, loc) -> new RawStoreNode(obj, offset, maskedValue, unsafeAccessKind, loc, true, memoryOrder), RawStoreNode.class);
createUnsafeAccess(object, b, (obj, loc) -> {
RawStoreNode store = new RawStoreNode(obj, offset, maskedValue, unsafeAccessKind, loc, true, memoryOrder);
return store;
}, RawStoreNode.class);
return true;
}
}
Expand Down Expand Up @@ -1846,6 +1858,15 @@ DeoptimizeNode add(GraphBuilderContext b, DeoptimizationAction action, Deoptimiz

private static void registerGraalDirectivesPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection) {
Registration r = new Registration(plugins, GraalDirectives.class);

r.register(new RequiredInlineOnlyInvocationPlugin("safepoint") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.append(new SafepointNode());
return true;
}
});

r.register(new DeoptimizePlugin(snippetReflection, None, TransferToInterpreter, false, "deoptimize"));
r.register(new DeoptimizePlugin(snippetReflection, InvalidateReprofile, TransferToInterpreter, false, "deoptimizeAndInvalidate"));
r.register(new DeoptimizePlugin(snippetReflection, null, null, null,
Expand Down
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This changelog summarizes major changes to GraalVM Native Image.

## GraalVM for JDK 25
* (GR-52276) (GR-61959) Add support for Arena.ofShared().
* (GR-58668) Enabled [Whole-Program Sparse Conditional Constant Propagation (WP-SCCP)](https://github.com/oracle/graal/pull/9821) by default, improving the precision of points-to analysis in Native Image. This optimization enhances static analysis accuracy and scalability, potentially reducing the size of the final native binary.
* (GR-59313) Deprecated class-level metadata extraction using `native-image-inspect` and removed option `DumpMethodsData`. Use class-level SBOMs instead by passing `--enable-sbom=class-level,export` to the `native-image` builder. The default value of option `IncludeMethodData` was changed to `false`.
* (GR-52400) The build process now uses 85% of system memory in containers and CI environments. Otherwise, it tries to only use available memory. If less than 8GB of memory are available, it falls back to 85% of system memory. The reason for the selected memory limit is now also shown in the build resources section of the build output.
Expand Down
13 changes: 13 additions & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@
"sun.util.calendar",
"sun.util.locale.provider",
"sun.util.resources",
"jdk.internal.foreign",
"jdk.internal.access",
"jdk.internal.event",
"jdk.internal.loader",
Expand Down Expand Up @@ -727,6 +728,7 @@
"jdk.internal.loader",
"jdk.internal.misc",
"jdk.internal.vm.annotation",
"jdk.internal.foreign",
"sun.net.www",
"sun.reflect.annotation",
"sun.security.jca",
Expand Down Expand Up @@ -787,6 +789,10 @@
],
"requiresConcealed": {
"java.base": [
"jdk.internal.misc",
"jdk.internal.util",
"jdk.internal.access.foreign",
"jdk.internal.vm.vector",
"jdk.internal.foreign",
"jdk.internal.foreign.abi",
"jdk.internal.foreign.abi.x64",
Expand Down Expand Up @@ -833,6 +839,8 @@
],
"requiresConcealed": {
"java.base": [
"jdk.internal.misc",
"jdk.internal.util",
"jdk.internal.foreign",
"jdk.internal.foreign.abi",
"jdk.internal.foreign.abi.x64.windows",
Expand Down Expand Up @@ -2518,6 +2526,9 @@
],
"moduleInfo" : {
"name" : "org.graalvm.nativeimage.foreign",
"opens" : [
"com.oracle.svm.core.foreign to org.graalvm.nativeimage.builder"
],
"requires" : [
"org.graalvm.nativeimage.builder",
"org.graalvm.collections",
Expand All @@ -2533,6 +2544,8 @@
"jdk.vm.ci.aarch64",
],
"java.base": [
"jdk.internal.misc",
"jdk.internal.util",
"jdk.internal.foreign",
"jdk.internal.foreign.abi",
"jdk.internal.foreign.abi.x64",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ public void addDowncallStubPointer(NativeEntryPointInfo nep, CFunctionPointer pt

@Platforms(Platform.HOSTED_ONLY.class)
public void addUpcallStubPointer(JavaEntryPointInfo jep, CFunctionPointer ptr) {
VMError.guarantee(!upcallStubs.containsKey(jep), "Seems like multiple stubs were generated for " + jep);
VMError.guarantee(!upcallStubs.containsKey(jep), "Seems like multiple stubs were generated for %s", jep);
VMError.guarantee(upcallStubs.put(jep, new FunctionPointerHolder(ptr)) == null);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void addDirectUpcallStubPointer(DirectMethodHandleDesc desc, CFunctionPointer ptr) {
VMError.guarantee(!directUpcallStubs.containsKey(desc), "Seems like multiple stubs were generated for " + desc);
VMError.guarantee(!directUpcallStubs.containsKey(desc), "Seems like multiple stubs were generated for %s", desc);
VMError.guarantee(directUpcallStubs.put(desc, new FunctionPointerHolder(ptr)) == null);
}

Expand Down
Loading
Loading