Skip to content

Commit 96fde9a

Browse files
committed
Intrinsify linkToNative
1 parent 8e2ad55 commit 96fde9a

File tree

17 files changed

+569
-29
lines changed

17 files changed

+569
-29
lines changed

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

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,15 @@
4141
import jdk.graal.compiler.replacements.nodes.MacroInvokable;
4242
import jdk.graal.compiler.replacements.nodes.MacroNode;
4343
import jdk.graal.compiler.replacements.nodes.MethodHandleNode;
44+
import jdk.graal.compiler.replacements.nodes.MethodHandleNode.GraphAdder;
45+
import jdk.graal.compiler.replacements.nodes.MethodHandleNode.InvokeFactory;
4446
import jdk.vm.ci.meta.JavaKind;
4547
import jdk.vm.ci.meta.MethodHandleAccessProvider;
4648
import jdk.vm.ci.meta.MethodHandleAccessProvider.IntrinsicMethod;
4749
import jdk.vm.ci.meta.ResolvedJavaMethod;
4850

4951
public class MethodHandlePlugin implements NodePlugin {
50-
private final MethodHandleAccessProvider methodHandleAccess;
52+
protected final MethodHandleAccessProvider methodHandleAccess;
5153
private final boolean safeForDeoptimization;
5254

5355
public MethodHandlePlugin(MethodHandleAccessProvider methodHandleAccess, boolean safeForDeoptimization) {
@@ -75,11 +77,7 @@ protected void onCreateHook(MacroInvokable methodHandleNode, GraphBuilderContext
7577
@Override
7678
public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
7779
IntrinsicMethod intrinsicMethod = methodHandleAccess.lookupMethodHandleIntrinsic(method);
78-
// We skip intrinsification for LINK_TO_NATIVE, because:
79-
// 1. HotSpot generates compiler entry jumping to the native wrapper of the target c method.
80-
// 2. SVM intrinsification is not yet implemented.
81-
// Use String comparison for JDK21 compatibility.
82-
if (intrinsicMethod != null && !"LINK_TO_NATIVE".equals(intrinsicMethod.name())) {
80+
if (intrinsicMethod != null && canHandleIntrinsicMethod(intrinsicMethod)) {
8381
InvokeKind invokeKind = b.getInvokeKind();
8482
if (invokeKind != InvokeKind.Static) {
8583
args[0] = b.nullCheckedValue(args[0]);
@@ -91,7 +89,7 @@ public <T extends ValueNode> T add(T node) {
9189
return b.add(node);
9290
}
9391
};
94-
Invoke invoke = MethodHandleNode.tryResolveTargetInvoke(adder, this::createInvoke, methodHandleAccess, intrinsicMethod, method, b.bci(), invokeReturnStamp, args);
92+
Invoke invoke = tryResolveTargetInvoke(adder, this::createInvoke, intrinsicMethod, method, b.bci(), invokeReturnStamp, args);
9593
if (invoke == null) {
9694
MacroInvokable methodHandleNode = createMethodHandleNode(b, method, args, intrinsicMethod, invokeKind, invokeReturnStamp);
9795
onCreateHook(methodHandleNode, b);
@@ -159,4 +157,18 @@ public <T extends ValueNode> T add(T node) {
159157
}
160158
return false;
161159
}
160+
161+
protected boolean canHandleIntrinsicMethod(IntrinsicMethod intrinsicMethod) {
162+
assert intrinsicMethod != null;
163+
/*
164+
* We skip intrinsification for LINK_TO_NATIVE because HotSpot generates compiler entry code
165+
* jumping to the native wrapper of the target C method.
166+
*/
167+
return intrinsicMethod != IntrinsicMethod.LINK_TO_NATIVE;
168+
}
169+
170+
protected <T extends Invoke> T tryResolveTargetInvoke(GraphAdder adder, InvokeFactory<T> factory, IntrinsicMethod intrinsicMethod,
171+
ResolvedJavaMethod original, int bci, StampPair returnStamp, ValueNode... arguments) {
172+
return MethodHandleNode.tryResolveTargetInvoke(adder, factory, methodHandleAccess, intrinsicMethod, original, bci, returnStamp, arguments);
173+
}
162174
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import jdk.graal.compiler.replacements.nodes.MacroInvokable;
3535
import jdk.graal.compiler.replacements.nodes.MacroNode;
3636
import jdk.graal.compiler.replacements.nodes.MethodHandleWithExceptionNode;
37-
3837
import jdk.vm.ci.meta.MethodHandleAccessProvider;
3938
import jdk.vm.ci.meta.ResolvedJavaMethod;
4039

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ private static <T extends Invoke> T getTargetInvokeNode(GraphAdder adder, Invoke
302302
* @param index of the argument to be cast
303303
* @param type the type the argument should be cast to
304304
*/
305-
private static void maybeCastArgument(GraphAdder adder, ValueNode[] arguments, int index, JavaType type) {
305+
public static void maybeCastArgument(GraphAdder adder, ValueNode[] arguments, int index, JavaType type) {
306306
ValueNode argument = arguments[index];
307307
if (type instanceof ResolvedJavaType && !((ResolvedJavaType) type).isJavaLangObject()) {
308308
Assumptions assumptions = adder.getAssumptions();

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleWithExceptionNode.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -31,29 +31,35 @@
3131

3232
import jdk.graal.compiler.graph.NodeClass;
3333
import jdk.graal.compiler.nodeinfo.NodeInfo;
34+
import jdk.graal.compiler.nodes.Invoke;
3435
import jdk.graal.compiler.nodes.InvokeWithExceptionNode;
3536
import jdk.graal.compiler.nodes.ValueNode;
3637
import jdk.graal.compiler.nodes.WithExceptionNode;
3738
import jdk.graal.compiler.nodes.spi.Simplifiable;
3839
import jdk.graal.compiler.nodes.spi.SimplifierTool;
39-
40+
import jdk.graal.compiler.replacements.nodes.MethodHandleNode.GraphAdder;
41+
import jdk.graal.compiler.replacements.nodes.MethodHandleNode.InvokeFactory;
4042
import jdk.vm.ci.meta.MethodHandleAccessProvider;
4143
import jdk.vm.ci.meta.MethodHandleAccessProvider.IntrinsicMethod;
4244

4345
/**
4446
* Node for invocation methods defined on the class {@link MethodHandle}.
4547
*/
4648
@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "see MacroNode", size = SIZE_UNKNOWN, sizeRationale = "see MacroNode")
47-
public final class MethodHandleWithExceptionNode extends MacroWithExceptionNode implements Simplifiable {
49+
public class MethodHandleWithExceptionNode extends MacroWithExceptionNode implements Simplifiable {
4850
public static final NodeClass<MethodHandleWithExceptionNode> TYPE = NodeClass.create(MethodHandleWithExceptionNode.class);
4951

5052
protected final IntrinsicMethod intrinsicMethod;
5153

52-
public MethodHandleWithExceptionNode(IntrinsicMethod intrinsicMethod, MacroNode.MacroParams p) {
53-
super(TYPE, p);
54+
protected MethodHandleWithExceptionNode(NodeClass<? extends MacroWithExceptionNode> c, IntrinsicMethod intrinsicMethod, MacroNode.MacroParams p) {
55+
super(c, p);
5456
this.intrinsicMethod = intrinsicMethod;
5557
}
5658

59+
public MethodHandleWithExceptionNode(IntrinsicMethod intrinsicMethod, MacroNode.MacroParams p) {
60+
this(TYPE, intrinsicMethod, p);
61+
}
62+
5763
@Override
5864
public void simplify(SimplifierTool tool) {
5965
MethodHandleAccessProvider methodHandleAccess = tool.getConstantReflection().getMethodHandleAccess();
@@ -69,7 +75,7 @@ public WithExceptionNode trySimplify(MethodHandleAccessProvider methodHandleAcce
6975
invoke.setStamp(stmp);
7076
return invoke;
7177
};
72-
InvokeWithExceptionNode invoke = MethodHandleNode.tryResolveTargetInvoke(adder, invokeFactory, methodHandleAccess, intrinsicMethod, targetMethod, bci, returnStamp, argumentsArray);
78+
InvokeWithExceptionNode invoke = tryResolveTargetInvoke(adder, invokeFactory, methodHandleAccess, argumentsArray);
7379
if (invoke == null) {
7480
return this;
7581
}
@@ -80,4 +86,8 @@ public WithExceptionNode trySimplify(MethodHandleAccessProvider methodHandleAcce
8086
graph().replaceWithExceptionSplit(this, invoke);
8187
return invoke;
8288
}
89+
90+
protected <T extends Invoke> T tryResolveTargetInvoke(GraphAdder adder, InvokeFactory<T> factory, MethodHandleAccessProvider methodHandleAccess, ValueNode... argumentsArray) {
91+
return MethodHandleNode.tryResolveTargetInvoke(adder, factory, methodHandleAccess, intrinsicMethod, targetMethod, bci, returnStamp, argumentsArray);
92+
}
8393
}

substratevm/mx.substratevm/suite.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@
839839
"jdk.internal.foreign.layout",
840840
"jdk.internal.loader",
841841
"jdk.internal.reflect",
842+
"jdk.internal.vm.annotation",
842843
],
843844
"jdk.internal.vm.ci" : [
844845
"jdk.vm.ci.aarch64",

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ FunctionPointerHolder getDowncallStubPointerHolder(NativeEntryPointInfo nep) {
232232
return holder;
233233
}
234234

235-
CFunctionPointer getDowncallStubPointer(NativeEntryPointInfo nep) {
235+
public CFunctionPointer getDowncallStubPointer(NativeEntryPointInfo nep) {
236236
return getDowncallStubPointerHolder(nep).functionPointer;
237237
}
238238

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -41,20 +41,22 @@
4141
import org.graalvm.nativeimage.c.function.CFunction.Transition;
4242
import org.graalvm.nativeimage.c.function.CLibrary;
4343
import org.graalvm.word.Pointer;
44+
import org.graalvm.word.impl.Word;
4445

45-
import com.oracle.svm.shared.util.SubstrateUtil;
4646
import com.oracle.svm.shared.util.BasedOnJDKClass;
47+
import com.oracle.svm.shared.util.SubstrateUtil;
4748
import com.oracle.svm.shared.util.VMError;
4849

50+
import jdk.graal.compiler.util.ObjectCopier;
4951
import jdk.internal.foreign.Utils;
50-
import org.graalvm.word.impl.Word;
5152

5253
/**
5354
* Separated from {@link Target_jdk_internal_foreign_SystemLookup} to allow (forced) runtime
5455
* initialization.
5556
*/
5657
@BasedOnJDKClass(jdk.internal.foreign.SystemLookup.class)
5758
public final class RuntimeSystemLookup {
59+
@ObjectCopier.NotExternalValue(reason = "Lazy runtime lookup; must not be read during external value gathering") //
5860
static final SymbolLookup INSTANCE = makeSystemLookup();
5961

6062
public static SymbolLookup makeSystemLookup() {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import com.oracle.svm.configure.config.ForeignConfiguration.StubDesc;
4343
import com.oracle.svm.shared.AlwaysInline;
4444
import com.oracle.svm.core.ArenaIntrinsics;
45+
import com.oracle.svm.core.NeverInline;
4546
import com.oracle.svm.core.SubstrateOptions;
4647
import com.oracle.svm.core.foreign.ForeignFunctionsRuntime.LinkRequest;
4748
import com.oracle.svm.core.nodes.foreign.ScopedMemExceptionHandlerClusterNode.ClusterBeginNode;
@@ -202,4 +203,14 @@ private static String memoryLayoutToString(MemoryLayout memoryLayout) {
202203
}
203204
return layoutString;
204205
}
206+
207+
@NeverInline("inlining cut off")
208+
static IllegalArgumentException getSymbolIsNullException(MemorySegment symbol) {
209+
return new IllegalArgumentException("Symbol is NULL: " + symbol);
210+
}
211+
212+
@NeverInline("inlining cut off")
213+
static IllegalArgumentException getHeapSegmentNotAllowedException(MemorySegment segment) {
214+
return new IllegalArgumentException("Heap segment not allowed: " + segment);
215+
}
205216
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2026, 2026, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package com.oracle.svm.core.foreign;
27+
28+
import java.lang.foreign.MemorySegment;
29+
import java.util.Objects;
30+
31+
import com.oracle.svm.core.annotate.Substitute;
32+
import com.oracle.svm.core.annotate.TargetClass;
33+
34+
import jdk.internal.foreign.abi.SharedUtils;
35+
import jdk.internal.vm.annotation.ForceInline;
36+
37+
@TargetClass(value = SharedUtils.class, onlyWith = ForeignAPIPredicates.Enabled.class)
38+
final class Target_jdk_internal_foreign_abi_SharedUtils {
39+
@ForceInline
40+
@Substitute
41+
public static void checkSymbol(MemorySegment symbol) {
42+
Objects.requireNonNull(symbol);
43+
if (MemorySegment.NULL.equals(symbol)) {
44+
throw SubstrateForeignUtil.getSymbolIsNullException(symbol);
45+
}
46+
}
47+
48+
@ForceInline
49+
@Substitute
50+
public static void checkNative(MemorySegment segment) {
51+
if (!segment.isNative()) {
52+
throw SubstrateForeignUtil.getHeapSegmentNotAllowedException(segment);
53+
}
54+
}
55+
}

substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/DowncallStub.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ static ResolvedSignature<ResolvedJavaType> createSignature(MetaAccessProvider me
132132
this.nepi = nepi;
133133
}
134134

135+
MethodType getMethodType() {
136+
return nepi.methodType();
137+
}
138+
135139
private static final List<AnnotationValue> INJECTED_ANNOTATIONS_FOR_ALLOW_HEAP_ACCESS = List.of(
136140
newAnnotationValue(GuestAccess.elements().Uninterruptible,
137141
"reason", "See DowncallStub.getInjectedAnnotations.",

0 commit comments

Comments
 (0)