33
33
import java .lang .foreign .MemoryLayout ;
34
34
import java .lang .foreign .ValueLayout ;
35
35
import java .lang .invoke .MethodType ;
36
+ import java .lang .reflect .Method ;
36
37
import java .util .ArrayList ;
37
38
import java .util .Arrays ;
38
39
import java .util .Collections ;
39
40
import java .util .EnumMap ;
40
41
import java .util .List ;
41
42
import java .util .Map ;
42
43
import java .util .Objects ;
44
+ import java .util .Optional ;
43
45
import java .util .function .Consumer ;
44
46
import java .util .stream .Stream ;
45
47
46
48
import org .graalvm .nativeimage .ImageSingletons ;
47
49
import org .graalvm .nativeimage .Isolate ;
48
50
import org .graalvm .nativeimage .Platform ;
51
+ import org .graalvm .nativeimage .Platform .HOSTED_ONLY ;
49
52
import org .graalvm .nativeimage .Platforms ;
50
53
import org .graalvm .word .Pointer ;
51
54
59
62
import com .oracle .svm .core .util .BasedOnJDKClass ;
60
63
import com .oracle .svm .core .util .BasedOnJDKFile ;
61
64
import com .oracle .svm .core .util .VMError ;
65
+ import com .oracle .svm .util .ReflectionUtil ;
62
66
63
67
import jdk .graal .compiler .api .replacements .Fold ;
64
68
import jdk .graal .compiler .asm .Label ;
83
87
import jdk .internal .foreign .abi .VMStorage ;
84
88
import jdk .internal .foreign .abi .aarch64 .AArch64Architecture ;
85
89
import jdk .internal .foreign .abi .x64 .X86_64Architecture ;
86
- import jdk .internal .foreign .abi .x64 .sysv .CallArranger ;
87
90
import jdk .vm .ci .aarch64 .AArch64 ;
88
91
import jdk .vm .ci .amd64 .AMD64 ;
89
92
import jdk .vm .ci .code .Register ;
@@ -491,15 +494,31 @@ public static AbiUtils singleton() {
491
494
return ImageSingletons .lookup (AbiUtils .class );
492
495
}
493
496
497
+ /**
498
+ * Specifies if a method handle invoked by an upcall stub needs to drop its return value in case
499
+ * of an in-memory return type. See also: {@link java.lang.invoke.MethodHandles#dropReturn} and
500
+ * {@code jdk.internal.foreign.abi.SharedUtils#adaptUpcallForIMR}
501
+ */
502
+ @ Platforms (Platform .HOSTED_ONLY .class )
503
+ public abstract boolean dropReturn ();
504
+
505
+ /**
506
+ * Calls method {@code isInMemoryReturn} of the appropriate {@code CallArranger}. This method
507
+ * determines, if a given return type requires an in-memory return on the current platform.
508
+ */
509
+ @ Platforms (Platform .HOSTED_ONLY .class )
510
+ public abstract boolean isInMemoryReturn (Optional <MemoryLayout > returnLayout );
511
+
494
512
protected abstract CallingSequence makeCallingSequence (MethodType type , FunctionDescriptor desc , boolean forUpcall , LinkerOptions options );
495
513
496
514
/**
497
515
* This method re-implements a part of the logic from the JDK so that we can get the callee-type
498
516
* (i.e. the ABI low-level type) of a function from its descriptor.
499
517
*/
518
+ @ Platforms (HOSTED_ONLY .class )
500
519
@ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+18/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java#L99" )
501
520
@ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+18/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java#L71-L85" )
502
- public NativeEntryPointInfo makeNativeEntrypoint (FunctionDescriptor desc , LinkerOptions linkerOptions ) {
521
+ public final NativeEntryPointInfo makeNativeEntrypoint (FunctionDescriptor desc , LinkerOptions linkerOptions ) {
503
522
// From Linker.downcallHandle implemented in AbstractLinker.downcallHandle:
504
523
// From AbstractLinker.downcallHandle0
505
524
MethodType type = desc .toMethodType ();
@@ -519,9 +538,9 @@ public NativeEntryPointInfo makeNativeEntrypoint(FunctionDescriptor desc, Linker
519
538
linkerOptions .allowsHeapAccess ());
520
539
}
521
540
522
- @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+18 /src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java#L124 " )
541
+ @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+13 /src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java#L126 " )
523
542
@ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+18/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java#L62-L110" )
524
- public JavaEntryPointInfo makeJavaEntryPoint (FunctionDescriptor desc , LinkerOptions linkerOptions ) {
543
+ public final JavaEntryPointInfo makeJavaEntryPoint (FunctionDescriptor desc , LinkerOptions linkerOptions ) {
525
544
// Linker.upcallStub implemented in AbstractLinker.upcallStub
526
545
MethodType type = desc .toMethodType ();
527
546
@@ -659,7 +678,7 @@ public Pointer write(Pointer at, Isolate isolate, Word methodHandle, Word stubPo
659
678
}
660
679
661
680
@ Platforms (Platform .HOSTED_ONLY .class )
662
- public abstract TrampolineTemplate generateTrampolineTemplate ();
681
+ abstract TrampolineTemplate generateTrampolineTemplate ();
663
682
}
664
683
665
684
class ABIs {
@@ -716,12 +735,26 @@ public int trampolineSize() {
716
735
public TrampolineTemplate generateTrampolineTemplate () {
717
736
return null ;
718
737
}
738
+
739
+ @ Override
740
+ public boolean dropReturn () {
741
+ return fail ();
742
+ }
743
+
744
+ @ Override
745
+ public boolean isInMemoryReturn (Optional <MemoryLayout > returnLayout ) {
746
+ return fail ();
747
+ }
719
748
}
720
749
721
750
@ BasedOnJDKClass (AArch64Architecture .class )
722
751
@ BasedOnJDKClass (jdk .internal .foreign .abi .DowncallLinker .class )
723
752
@ BasedOnJDKClass (jdk .internal .foreign .abi .UpcallLinker .class )
724
753
abstract static class ARM64 extends AbiUtils {
754
+
755
+ @ Platforms (Platform .HOSTED_ONLY .class ) //
756
+ private static final Method IS_IN_MEMORY_RETURN = ReflectionUtil .lookupMethod (jdk .internal .foreign .abi .aarch64 .CallArranger .class , "isInMemoryReturn" , Optional .class );
757
+
725
758
@ Override
726
759
public Registers upcallSpecialArgumentsRegisters () {
727
760
return new Registers (SubstrateAArch64MacroAssembler .scratch1 , SubstrateAArch64MacroAssembler .scratch2 );
@@ -815,6 +848,17 @@ public TrampolineTemplate generateTrampolineTemplate() {
815
848
816
849
return new TrampolineTemplate (assembly , posIsolate , posMHArray , posCallTarget );
817
850
}
851
+
852
+ @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+13/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java#L195" )
853
+ @ Override
854
+ public boolean dropReturn () {
855
+ return true ;
856
+ }
857
+
858
+ @ Override
859
+ public boolean isInMemoryReturn (Optional <MemoryLayout > returnLayout ) {
860
+ return ReflectionUtil .invokeMethod (IS_IN_MEMORY_RETURN , null , returnLayout );
861
+ }
818
862
}
819
863
820
864
@ BasedOnJDKClass (jdk .internal .foreign .abi .aarch64 .linux .LinuxAArch64Linker .class )
@@ -961,6 +1005,10 @@ public TrampolineTemplate generateTrampolineTemplate() {
961
1005
@ BasedOnJDKClass (jdk .internal .foreign .abi .x64 .sysv .SysVx64Linker .class )
962
1006
@ BasedOnJDKClass (jdk .internal .foreign .abi .x64 .sysv .CallArranger .class )
963
1007
static final class SysV extends X86_64 {
1008
+
1009
+ @ Platforms (Platform .HOSTED_ONLY .class ) //
1010
+ private static final Method IS_IN_MEMORY_RETURN = ReflectionUtil .lookupMethod (jdk .internal .foreign .abi .x64 .sysv .CallArranger .class , "isInMemoryReturn" , Optional .class );
1011
+
964
1012
@ Override
965
1013
protected CallingSequence makeCallingSequence (MethodType type , FunctionDescriptor desc , boolean forUpcall , LinkerOptions options ) {
966
1014
return jdk .internal .foreign .abi .x64 .sysv .CallArranger .getBindings (type , desc , forUpcall , options ).callingSequence ();
@@ -1002,11 +1050,26 @@ public void checkLibrarySupport() {
1002
1050
public Map <String , MemoryLayout > canonicalLayouts () {
1003
1051
return SharedUtils .canonicalLayouts (ValueLayout .JAVA_LONG , ValueLayout .JAVA_LONG , ValueLayout .JAVA_INT );
1004
1052
}
1053
+
1054
+ @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+13/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java#L147" )
1055
+ @ Override
1056
+ public boolean dropReturn () {
1057
+ return true ;
1058
+ }
1059
+
1060
+ @ Override
1061
+ public boolean isInMemoryReturn (Optional <MemoryLayout > returnLayout ) {
1062
+ return ReflectionUtil .invokeMethod (IS_IN_MEMORY_RETURN , null , returnLayout );
1063
+ }
1005
1064
}
1006
1065
1007
1066
@ BasedOnJDKClass (jdk .internal .foreign .abi .x64 .windows .Windowsx64Linker .class )
1008
1067
@ BasedOnJDKClass (jdk .internal .foreign .abi .x64 .windows .CallArranger .class )
1009
1068
static final class Win64 extends X86_64 {
1069
+
1070
+ @ Platforms (Platform .HOSTED_ONLY .class ) //
1071
+ private static final Method IS_IN_MEMORY_RETURN = ReflectionUtil .lookupMethod (jdk .internal .foreign .abi .x64 .windows .CallArranger .class , "isInMemoryReturn" , Optional .class );
1072
+
1010
1073
@ Override
1011
1074
protected CallingSequence makeCallingSequence (MethodType type , FunctionDescriptor desc , boolean forUpcall , LinkerOptions options ) {
1012
1075
return jdk .internal .foreign .abi .x64 .windows .CallArranger .getBindings (type , desc , forUpcall , options ).callingSequence ();
@@ -1058,6 +1121,17 @@ public void checkLibrarySupport() {
1058
1121
public Map <String , MemoryLayout > canonicalLayouts () {
1059
1122
return SharedUtils .canonicalLayouts (ValueLayout .JAVA_INT , ValueLayout .JAVA_LONG , ValueLayout .JAVA_CHAR );
1060
1123
}
1124
+
1125
+ @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+13/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java#L139" )
1126
+ @ Override
1127
+ public boolean dropReturn () {
1128
+ return false ;
1129
+ }
1130
+
1131
+ @ Override
1132
+ public boolean isInMemoryReturn (Optional <MemoryLayout > returnLayout ) {
1133
+ return ReflectionUtil .invokeMethod (IS_IN_MEMORY_RETURN , null , returnLayout );
1134
+ }
1061
1135
}
1062
1136
1063
1137
@ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+11/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java#L122-L140" )
0 commit comments