Skip to content

Commit f0c0d69

Browse files
otethalfangerer
authored andcommitted
[GR-74883] Migrate NFIPosixSupport from NFI to the FFM API
PullRequest: graalpython/4536
2 parents 15153da + d572e29 commit f0c0d69

32 files changed

Lines changed: 4330 additions & 2941 deletions

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.annotations;
42+
43+
import java.lang.annotation.ElementType;
44+
import java.lang.annotation.Retention;
45+
import java.lang.annotation.RetentionPolicy;
46+
import java.lang.annotation.Target;
47+
48+
@Retention(RetentionPolicy.SOURCE)
49+
@Target(ElementType.METHOD)
50+
public @interface DowncallSignature {
51+
NativeSimpleType returnType();
52+
53+
NativeSimpleType[] argumentTypes() default {};
54+
55+
Class<?> retConversion() default void.class;
56+
57+
Class<?>[] argConversions() default {};
58+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeSimpleType.java renamed to graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/NativeSimpleType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3939
* SOFTWARE.
4040
*/
41-
package com.oracle.graal.python.runtime.nativeaccess;
41+
package com.oracle.graal.python.annotations;
4242

4343
/**
4444
* Simple native carrier types used by native access signatures.
@@ -55,5 +55,5 @@ public enum NativeSimpleType {
5555
SINT64,
5656
FLOAT,
5757
DOUBLE,
58-
RAW_POINTER; // arg must be long, retval is long
58+
POINTER; // raw pointer represented in Java as a long
5959
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
com.oracle.graal.python.processor.ArgumentClinicProcessor
22
com.oracle.graal.python.processor.GenerateEnumConstantsProcessor
3+
com.oracle.graal.python.processor.GenerateNativeDowncallsProcessor
34
com.oracle.graal.python.processor.CApiBuiltinsProcessor
4-
com.oracle.graal.python.processor.SlotsProcessor
5+
com.oracle.graal.python.processor.SlotsProcessor

graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/CApiBuiltinsProcessor.java

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
*/
4141
package com.oracle.graal.python.processor;
4242

43+
import static com.oracle.graal.python.processor.NativeDowncallMethodHandleGenerator.argName;
44+
4345
import java.io.IOException;
4446
import java.nio.file.Files;
4547
import java.nio.file.Path;
@@ -86,6 +88,7 @@
8688
import com.oracle.graal.python.annotations.CApiFields;
8789
import com.oracle.graal.python.annotations.CApiStructs;
8890
import com.oracle.graal.python.annotations.CApiUpcallTarget;
91+
import com.oracle.graal.python.annotations.NativeSimpleType;
8992
import com.sun.source.tree.VariableTree;
9093
import com.sun.source.util.TreePathScanner;
9194
import com.sun.source.util.Trees;
@@ -291,10 +294,6 @@ private String capiTypeToForeignPrimitiveType(VariableElement element) {
291294
return type.equals("void") ? "void" : ("j" + type);
292295
}
293296

294-
private static String argName(int i) {
295-
return "" + (char) ('a' + i);
296-
}
297-
298297
private static final String CAPI_BUILTIN = "com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin";
299298
private static final String CAPI_BUILTINS = "com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltins";
300299
private static final String CAPI_WRAPPER_DESCRIPTOR = "com.oracle.graal.python.builtins.objects.cext.capi.ExternalFunctionNodes.CApiWrapperDescriptor";
@@ -1261,21 +1260,6 @@ private TypeMirror toJavaNfiType(TypeMirror typeMirror) {
12611260
return processingEnv.getTypeUtils().getPrimitiveType(TypeKind.LONG);
12621261
}
12631262

1264-
private static String getNativeMethodHandleVarName(String signatureName) {
1265-
return "NATIVE_METHOD_HANDLE_" + signatureName;
1266-
}
1267-
1268-
private static String toClassLiteral(String javaType) {
1269-
return switch (javaType) {
1270-
case "void" -> "void.class";
1271-
case "int" -> "int.class";
1272-
case "long" -> "long.class";
1273-
case "float" -> "float.class";
1274-
case "double" -> "double.class";
1275-
default -> throw new IllegalArgumentException("Unexpected Java type: " + javaType);
1276-
};
1277-
}
1278-
12791263
private boolean isCannotRaise(VariableElement signature) {
12801264
String externalFunctionSignatureInitializer = getExternalFunctionSignatureInitializer(signature);
12811265
int start = externalFunctionSignatureInitializer.indexOf('(');
@@ -1348,7 +1332,6 @@ private void generateExternalFunctionInvoker(List<CApiExternalFunctionSignatureD
13481332
assert sig.returnType != null;
13491333
assert sig.argumentTypes != null;
13501334
String returnType = toJavaNfiType(sig.returnType);
1351-
String returnTypeLiteral = toClassLiteral(returnType);
13521335
List<String> argTypes = Arrays.stream(sig.argumentTypes).map(this::toJavaNfiType).toList();
13531336

13541337
boolean isVoidReturn = "void".equals(returnType);
@@ -1381,14 +1364,7 @@ private void generateExternalFunctionInvoker(List<CApiExternalFunctionSignatureD
13811364
for (String argType : argTypes) {
13821365
typedArgs.add(argType + " " + argName(i++));
13831366
}
1384-
1385-
List<String> methodTypeArgs = new ArrayList<>();
1386-
methodTypeArgs.add("long.class");
1387-
for (String argType : argTypes) {
1388-
methodTypeArgs.add(toClassLiteral(argType));
1389-
}
1390-
lines.add(" private static final MethodHandle " + getNativeMethodHandleVarName(sig.name) + " = NativeAccessSupport.createDowncallHandle(" +
1391-
"MethodType.methodType(" + returnTypeLiteral + ", " + String.join(", ", methodTypeArgs) + "), false);");
1367+
NativeDowncallMethodHandleGenerator.emitMethodHandleField(lines, NativeDowncallMethodHandleGenerator.methodHandleVarName(sig.name), returnType, argTypes);
13921368

13931369
lines.add("");
13941370
if (sig.cannotRaise) {
@@ -1464,9 +1440,9 @@ private void generateExternalFunctionInvoker(List<CApiExternalFunctionSignatureD
14641440
lines.add(" public static " + returnType + " invoke" + sig.name + "(" + String.join(", ", rawInvokeArgs) + ") throws Throwable {");
14651441
String directArgExpr = cArgs.isEmpty() ? "function" : "function, " + String.join(", ", cArgs);
14661442
if (isVoidReturn) {
1467-
lines.add(" " + getNativeMethodHandleVarName(sig.name) + ".invokeExact(" + directArgExpr + ");");
1443+
lines.add(" " + NativeDowncallMethodHandleGenerator.methodHandleVarName(sig.name) + ".invokeExact(" + directArgExpr + ");");
14681444
} else {
1469-
lines.add(" return (" + returnType + ") " + getNativeMethodHandleVarName(sig.name) + ".invokeExact(" + directArgExpr + ");");
1445+
lines.add(" return (" + returnType + ") " + NativeDowncallMethodHandleGenerator.methodHandleVarName(sig.name) + ".invokeExact(" + directArgExpr + ");");
14701446
}
14711447
lines.add(" }");
14721448
}
@@ -1504,6 +1480,7 @@ private void generateNativeAccessSupport(Element[] origins) throws IOException {
15041480
lines.add("import java.util.OptionalLong;");
15051481
lines.add("");
15061482
lines.add("import static com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere;");
1483+
lines.add("import " + NativeSimpleType.class.getCanonicalName() + ";");
15071484
lines.add("");
15081485
lines.add("public final class " + NATIVE_ACCESS_SUPPORT_IMPL_CLASS_NAME + " extends " + NATIVE_ACCESS_SUPPORT_CLASS_NAME + " {");
15091486
lines.add(" private static final MethodHandle OF_ADDRESS;");
@@ -1604,7 +1581,7 @@ private void generateNativeAccessSupport(Element[] origins) throws IOException {
16041581
lines.add(" case SINT64 -> ValueLayout.JAVA_LONG;");
16051582
lines.add(" case FLOAT -> ValueLayout.JAVA_FLOAT;");
16061583
lines.add(" case DOUBLE -> ValueLayout.JAVA_DOUBLE;");
1607-
lines.add(" case RAW_POINTER -> ValueLayout.JAVA_LONG;");
1584+
lines.add(" case POINTER -> ValueLayout.JAVA_LONG;");
16081585
lines.add(" };");
16091586
lines.add(" }");
16101587
lines.add("}");
@@ -1626,6 +1603,8 @@ private void generateDummyNativeAccessSupport(Element[] origins) throws IOExcept
16261603
lines.add("import java.lang.invoke.MethodHandle;");
16271604
lines.add("import java.lang.invoke.MethodType;");
16281605
lines.add("");
1606+
lines.add("import " + NativeSimpleType.class.getCanonicalName() + ";");
1607+
lines.add("");
16291608
lines.add("public final class " + NATIVE_ACCESS_SUPPORT_IMPL_CLASS_NAME + " extends " + NATIVE_ACCESS_SUPPORT_CLASS_NAME + " {");
16301609
lines.add(" @Override");
16311610
lines.add(" protected Object createArenaImpl() {");

0 commit comments

Comments
 (0)