Skip to content

Commit 4e764cf

Browse files
committed
[GR-61959] SVM: Add shared arena support.
PullRequest: graal/20112
2 parents fe142b1 + d6f4c1b commit 4e764cf

31 files changed

+3058
-78
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/api/directives/GraalDirectives.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ public final class GraalDirectives {
4747
public static final double SLOWPATH_PROBABILITY = 0.0001;
4848
public static final double FASTPATH_PROBABILITY = 1.0 - SLOWPATH_PROBABILITY;
4949

50+
/**
51+
* Forces a safepoint in the compiled code.
52+
*/
53+
public static void safepoint() {
54+
55+
}
56+
5057
/**
5158
* Directive for the compiler to fall back to the bytecode interpreter at this point. All
5259
* arguments to this method must be compile-time constant.

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/Node.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,24 @@ public final boolean hasExactlyOneUsageOfType(InputType inputType) {
547547
return numUses == 1;
548548
}
549549

550+
/**
551+
* Checks whether {@code this} has any usages of type {@code inputType}.
552+
*
553+
* @param inputType the type of usages to look for
554+
*/
555+
public final boolean hasUsagesOfType(InputType inputType) {
556+
for (Node usage : usages()) {
557+
for (Position pos : usage.inputPositions()) {
558+
if (pos.get(usage) == this) {
559+
if (pos.getInputType() == inputType) {
560+
return true;
561+
}
562+
}
563+
}
564+
}
565+
return false;
566+
}
567+
550568
/**
551569
* Adds a given node to this node's {@linkplain #usages() usages}.
552570
*
@@ -1179,6 +1197,38 @@ public void replaceAtUsages(Node replacement, InputType inputType) {
11791197
}
11801198
}
11811199

1200+
/**
1201+
* For each use of {@code this} in another node, {@code n}, replace it with {@code replacement}
1202+
* if the type of the use is in {@code inputTypes} and if {@code filter.test(n) == true}.
1203+
*
1204+
* @see #replaceAtUsages(Node)
1205+
*/
1206+
public void replaceAtUsages(Node replacement, Predicate<Node> filter, InputType inputType) {
1207+
checkReplaceWith(replacement);
1208+
int i = 0;
1209+
int usageCount = this.getUsageCount();
1210+
if (usageCount == 0) {
1211+
return;
1212+
}
1213+
usages: while (i < usageCount) {
1214+
Node usage = this.getUsageAt(i);
1215+
if (filter.test(usage)) {
1216+
for (Position pos : usage.inputPositions()) {
1217+
if (pos.getInputType() == inputType && pos.get(usage) == this) {
1218+
replaceAtUsagePos(replacement, usage, pos);
1219+
this.movUsageFromEndTo(i);
1220+
usageCount--;
1221+
continue usages;
1222+
}
1223+
}
1224+
}
1225+
i++;
1226+
}
1227+
if (hasNoUsages()) {
1228+
maybeNotifyZeroUsages(this);
1229+
}
1230+
}
1231+
11821232
/**
11831233
* For each use of {@code this} in another node, {@code n}, replace it with {@code replacement}
11841234
* if the type of the use is in {@code inputTypes}.

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/FrameState.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,13 @@ public FrameState(int bci) {
302302
* @param bci this must be {@link BytecodeFrame#AFTER_BCI}
303303
*/
304304
public FrameState(int bci, ValueNode returnValueOrExceptionObject) {
305-
this(null, null, bci, 0, returnValueOrExceptionObject.getStackKind().getSlotCount(), 0, returnValueOrExceptionObject instanceof ExceptionObjectNode ? StackState.Rethrow : StackState.BeforePop,
305+
this(bci, returnValueOrExceptionObject, null, true);
306+
}
307+
308+
public FrameState(int bci, ValueNode returnValueOrExceptionObject, Bytecode code, boolean checkBCI) {
309+
this(null, code, bci, 0, returnValueOrExceptionObject.getStackKind().getSlotCount(), 0, returnValueOrExceptionObject instanceof ExceptionObjectNode ? StackState.Rethrow : StackState.BeforePop,
306310
true, null, null);
307-
assert (bci == BytecodeFrame.AFTER_BCI && !rethrowException()) || (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && rethrowException()) : Assertions.errorMessage(bci);
311+
assert !checkBCI || (bci == BytecodeFrame.AFTER_BCI && !rethrowException()) || (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && rethrowException()) : Assertions.errorMessage(bci);
308312
ValueNode[] stack = {returnValueOrExceptionObject};
309313
this.values = new NodeInputList<>(this, stack);
310314
}
@@ -568,7 +572,7 @@ public FrameState duplicateModified(JavaKind popKind,
568572
ValueNode pushedValue,
569573
List<EscapeObjectState> pushedVirtualObjectMappings) {
570574
assert pushedValue != null;
571-
assert pushedValue.getStackKind() == popKind : Assertions.errorMessage(pushedValue, popKind, this);
575+
assert pushedValue.getStackKind() == pushedSlotKind : Assertions.errorMessage(pushedValue, popKind, this);
572576
return duplicateModified(graph(), bci, stackState, popKind, new JavaKind[]{pushedSlotKind}, new ValueNode[]{pushedValue}, pushedVirtualObjectMappings);
573577
}
574578

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/UnwindNode.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,10 @@ public UnwindNode(ValueNode exception) {
5858
public void generate(NodeLIRBuilderTool gen) {
5959
gen.getLIRGeneratorTool().emitUnwind(gen.operand(exception()));
6060
}
61+
62+
public void setException(ValueNode exception) {
63+
updateUsages(this.exception, exception);
64+
this.exception = exception;
65+
}
66+
6167
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GraphBuilderContext.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import static jdk.graal.compiler.core.common.type.StampFactory.objectNonNull;
2929
import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
3030

31+
import java.util.List;
32+
3133
import jdk.graal.compiler.bytecode.Bytecode;
3234
import jdk.graal.compiler.core.common.type.AbstractPointerStamp;
3335
import jdk.graal.compiler.core.common.type.IntegerStamp;
@@ -71,6 +73,7 @@
7173
import jdk.graal.compiler.nodes.extended.GuardingNode;
7274
import jdk.graal.compiler.nodes.java.InstanceOfDynamicNode;
7375
import jdk.graal.compiler.nodes.type.StampTool;
76+
import jdk.internal.misc.ScopedMemoryAccess;
7477
import jdk.vm.ci.code.BailoutException;
7578
import jdk.vm.ci.meta.Assumptions;
7679
import jdk.vm.ci.meta.DeoptimizationAction;
@@ -595,4 +598,22 @@ static <T extends Node> T setStateAfterIfNecessary(GraphBuilderContext b, T valu
595598
default boolean currentBlockCatchesOOME() {
596599
return false;
597600
}
601+
602+
/**
603+
* Iff this parsing context is processing a method that is annotated with
604+
* {@link ScopedMemoryAccess} saves the associated session object.
605+
*
606+
* @param scopedMemorySession the currently parsed session of this context
607+
*/
608+
default void setIsParsingScopedMemoryMethod(ValueNode scopedMemorySession) {
609+
// nothing to do
610+
}
611+
612+
/**
613+
* Determines if the current parsing context has set any scoped memory access that needs to be
614+
* handled.
615+
*/
616+
default List<ValueNode> getScopedMemorySessions() {
617+
return null;
618+
}
598619
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/ExceptionObjectNode.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
import org.graalvm.word.LocationIdentity;
3232

33+
import jdk.graal.compiler.core.common.type.Stamp;
3334
import jdk.graal.compiler.core.common.type.StampFactory;
3435
import jdk.graal.compiler.core.common.type.TypeReference;
3536
import jdk.graal.compiler.debug.GraalError;
@@ -75,6 +76,10 @@ public ExceptionObjectNode(MetaAccessProvider metaAccess) {
7576
super(TYPE, StampFactory.objectNonNull(TypeReference.createTrustedWithoutAssumptions(metaAccess.lookupJavaType(Throwable.class))));
7677
}
7778

79+
public ExceptionObjectNode(Stamp s) {
80+
super(TYPE, s);
81+
}
82+
7883
@Override
7984
public LocationIdentity getKilledLocationIdentity() {
8085
return LocationIdentity.any();

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/StandardGraphBuilderPlugins.java

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
import jdk.graal.compiler.nodes.NamedLocationIdentity;
8989
import jdk.graal.compiler.nodes.NodeView;
9090
import jdk.graal.compiler.nodes.PiNode;
91+
import jdk.graal.compiler.nodes.SafepointNode;
9192
import jdk.graal.compiler.nodes.ProfileData.BranchProbabilityData;
9293
import jdk.graal.compiler.nodes.SpinWaitNode;
9394
import jdk.graal.compiler.nodes.StateSplit;
@@ -720,7 +721,8 @@ private static void registerUnsafePlugins(InvocationPlugins plugins, Replacement
720721
jdkInternalMiscUnsafe.register(new AllocateUninitializedArrayPlugin("allocateUninitializedArray0", false));
721722
}
722723

723-
private static void registerUnsafeAtomicsPlugins(Registration r, boolean isSunMiscUnsafe, boolean explicitUnsafeNullChecks, String casPrefix, JavaKind[] supportedJavaKinds,
724+
private static void registerUnsafeAtomicsPlugins(Registration r, boolean isSunMiscUnsafe, boolean explicitUnsafeNullChecks, String casPrefix,
725+
JavaKind[] supportedJavaKinds,
724726
MemoryOrderMode... memoryOrders) {
725727
for (JavaKind kind : supportedJavaKinds) {
726728
Class<?> javaClass = getJavaClass(kind);
@@ -787,7 +789,8 @@ private static void registerUnsafePlugins0(Registration r, boolean sunMiscUnsafe
787789
r.register(new UnsafePutPlugin(kind, explicitUnsafeNullChecks, putName, Receiver.class, Object.class, long.class, javaClass));
788790
// Volatile object-based accesses
789791
r.register(new UnsafeGetPlugin(kind, MemoryOrderMode.VOLATILE, explicitUnsafeNullChecks, getName + "Volatile", Receiver.class, Object.class, long.class));
790-
r.register(new UnsafePutPlugin(kind, MemoryOrderMode.VOLATILE, explicitUnsafeNullChecks, putName + "Volatile", Receiver.class, Object.class, long.class, javaClass));
792+
r.register(new UnsafePutPlugin(kind, MemoryOrderMode.VOLATILE, explicitUnsafeNullChecks, putName + "Volatile", Receiver.class, Object.class, long.class,
793+
javaClass));
791794
// Ordered object-based accesses
792795
if (sunMiscUnsafe) {
793796
if (kind == JavaKind.Int || kind == JavaKind.Long || kind == JavaKind.Object) {
@@ -1546,11 +1549,13 @@ private static FixedWithNextNode createMemoryAccessNode(StructuredGraph graph, U
15461549
return nodeConstructor.create(ConstantNode.forLong(0L, graph), OFF_HEAP_LOCATION);
15471550
}
15481551

1549-
private void setAccessNodeResult(FixedWithNextNode node, GraphBuilderContext b) {
1552+
private FixedWithNextNode setAccessNodeResult(FixedWithNextNode node, GraphBuilderContext b) {
15501553
if (returnKind != JavaKind.Void) {
15511554
b.addPush(returnKind, node);
1555+
return node;
15521556
} else {
15531557
b.add(node);
1558+
return node;
15541559
}
15551560
}
15561561

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

15841589
LogicNode condition = graph.addOrUniqueWithInputs(IsNullNode.create(value));
1585-
// We do not know the probability of this being a native memory or object, thus we
1586-
// inject 0.5. We still inject it to ensure no code verifying profiles reports
1590+
// We do not know the probability of this being a native memory or object, thus
1591+
// we inject 0.5. We still inject it to ensure no code verifying profiles reports
15871592
// missing ones.
15881593
BranchProbabilityData probability = BranchProbabilityData.injected(0.5, true);
15891594
IfNode ifNode = b.add(new IfNode(condition, memoryAccess, objectAccess, probability));
@@ -1616,6 +1621,7 @@ protected final void createUnsafeAccess(ValueNode value, GraphBuilderContext b,
16161621
}
16171622
b.setStateAfter(merge);
16181623
}
1624+
16191625
}
16201626
}
16211627

@@ -1651,7 +1657,10 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
16511657
// Emits a null-check for the otherwise unused receiver
16521658
unsafe.get(true);
16531659
// Note that non-ordered raw accesses can be turned into floatable field accesses.
1654-
UnsafeNodeConstructor unsafeNodeConstructor = (obj, loc) -> new RawLoadNode(obj, offset, unsafeAccessKind, loc, memoryOrder);
1660+
UnsafeNodeConstructor unsafeNodeConstructor = (obj, loc) -> {
1661+
RawLoadNode rl = new RawLoadNode(obj, offset, unsafeAccessKind, loc, memoryOrder);
1662+
return rl;
1663+
};
16551664
createUnsafeAccess(object, b, unsafeNodeConstructor, RawLoadNode.class);
16561665
return true;
16571666
}
@@ -1691,7 +1700,10 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
16911700
// Emits a null-check for the otherwise unused receiver
16921701
unsafe.get(true);
16931702
ValueNode maskedValue = b.maskSubWordValue(value, unsafeAccessKind);
1694-
createUnsafeAccess(object, b, (obj, loc) -> new RawStoreNode(obj, offset, maskedValue, unsafeAccessKind, loc, true, memoryOrder), RawStoreNode.class);
1703+
createUnsafeAccess(object, b, (obj, loc) -> {
1704+
RawStoreNode store = new RawStoreNode(obj, offset, maskedValue, unsafeAccessKind, loc, true, memoryOrder);
1705+
return store;
1706+
}, RawStoreNode.class);
16951707
return true;
16961708
}
16971709
}
@@ -1846,6 +1858,15 @@ DeoptimizeNode add(GraphBuilderContext b, DeoptimizationAction action, Deoptimiz
18461858

18471859
private static void registerGraalDirectivesPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection) {
18481860
Registration r = new Registration(plugins, GraalDirectives.class);
1861+
1862+
r.register(new RequiredInlineOnlyInvocationPlugin("safepoint") {
1863+
@Override
1864+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
1865+
b.append(new SafepointNode());
1866+
return true;
1867+
}
1868+
});
1869+
18491870
r.register(new DeoptimizePlugin(snippetReflection, None, TransferToInterpreter, false, "deoptimize"));
18501871
r.register(new DeoptimizePlugin(snippetReflection, InvalidateReprofile, TransferToInterpreter, false, "deoptimizeAndInvalidate"));
18511872
r.register(new DeoptimizePlugin(snippetReflection, null, null, null,

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
This changelog summarizes major changes to GraalVM Native Image.
44

55
## GraalVM for JDK 25
6+
* (GR-52276) (GR-61959) Add support for Arena.ofShared().
67
* (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.
78
* (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`.
89
* (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.

substratevm/mx.substratevm/suite.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@
365365
"sun.util.calendar",
366366
"sun.util.locale.provider",
367367
"sun.util.resources",
368+
"jdk.internal.foreign",
368369
"jdk.internal.access",
369370
"jdk.internal.event",
370371
"jdk.internal.loader",
@@ -727,6 +728,7 @@
727728
"jdk.internal.loader",
728729
"jdk.internal.misc",
729730
"jdk.internal.vm.annotation",
731+
"jdk.internal.foreign",
730732
"sun.net.www",
731733
"sun.reflect.annotation",
732734
"sun.security.jca",
@@ -787,6 +789,10 @@
787789
],
788790
"requiresConcealed": {
789791
"java.base": [
792+
"jdk.internal.misc",
793+
"jdk.internal.util",
794+
"jdk.internal.access.foreign",
795+
"jdk.internal.vm.vector",
790796
"jdk.internal.foreign",
791797
"jdk.internal.foreign.abi",
792798
"jdk.internal.foreign.abi.x64",
@@ -833,6 +839,8 @@
833839
],
834840
"requiresConcealed": {
835841
"java.base": [
842+
"jdk.internal.misc",
843+
"jdk.internal.util",
836844
"jdk.internal.foreign",
837845
"jdk.internal.foreign.abi",
838846
"jdk.internal.foreign.abi.x64.windows",
@@ -2518,6 +2526,9 @@
25182526
],
25192527
"moduleInfo" : {
25202528
"name" : "org.graalvm.nativeimage.foreign",
2529+
"opens" : [
2530+
"com.oracle.svm.core.foreign to org.graalvm.nativeimage.builder"
2531+
],
25212532
"requires" : [
25222533
"org.graalvm.nativeimage.builder",
25232534
"org.graalvm.collections",
@@ -2533,6 +2544,8 @@
25332544
"jdk.vm.ci.aarch64",
25342545
],
25352546
"java.base": [
2547+
"jdk.internal.misc",
2548+
"jdk.internal.util",
25362549
"jdk.internal.foreign",
25372550
"jdk.internal.foreign.abi",
25382551
"jdk.internal.foreign.abi.x64",

substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/ForeignFunctionsRuntime.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,13 @@ public void addDowncallStubPointer(NativeEntryPointInfo nep, CFunctionPointer pt
103103

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

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

0 commit comments

Comments
 (0)