2626
2727import java .lang .reflect .Modifier ;
2828
29+ import org .graalvm .compiler .nodes .NamedLocationIdentity ;
30+ import org .graalvm .compiler .word .BarrieredAccess ;
2931import org .graalvm .nativeimage .Platform .HOSTED_ONLY ;
3032import org .graalvm .nativeimage .Platforms ;
3133import org .graalvm .nativeimage .c .function .CFunctionPointer ;
3234import org .graalvm .nativeimage .c .function .CodePointer ;
35+ import org .graalvm .word .PointerBase ;
36+ import org .graalvm .word .WordFactory ;
3337
3438import com .oracle .graal .pointsto .meta .AnalysisUniverse ;
3539import com .oracle .svm .core .annotate .AlwaysInline ;
3640import com .oracle .svm .core .annotate .Uninterruptible ;
41+ import com .oracle .svm .core .graal .meta .KnownOffsets ;
3742import com .oracle .svm .core .meta .MethodPointer ;
3843import com .oracle .svm .core .util .VMError ;
3944import com .oracle .svm .hosted .FeatureImpl .CompilationAccessImpl ;
45+ import com .oracle .svm .hosted .meta .HostedMethod ;
4046import com .oracle .svm .hosted .meta .HostedUniverse ;
41- import com .oracle .svm .jni .hosted .JNIJavaCallMethod ;
4247import com .oracle .svm .jni .hosted .JNIJavaCallVariantWrapperMethod ;
4348import com .oracle .svm .jni .hosted .JNIJavaCallVariantWrapperMethod .CallVariant ;
4449import com .oracle .svm .jni .hosted .JNIJavaCallWrapperMethod ;
5358 * Information on a method that can be looked up and called via JNI.
5459 */
5560public final class JNIAccessibleMethod extends JNIAccessibleMember {
61+ public static final int STATICALLY_BOUND_METHOD = -1 ;
62+ public static final int VTABLE_OFFSET_NOT_YET_COMPUTED = -2 ;
63+ public static final int NEW_OBJECT_INVALID_FOR_ABSTRACT_TYPE = -1 ;
5664
5765 static ResolvedJavaField getCallVariantWrapperField (MetaAccessProvider metaAccess , CallVariant variant , boolean nonVirtual ) {
5866 StringBuilder name = new StringBuilder (32 );
@@ -74,15 +82,18 @@ static ResolvedJavaField getCallVariantWrapperField(MetaAccessProvider metaAcces
7482
7583 @ Platforms (HOSTED_ONLY .class ) private final JNIAccessibleMethodDescriptor descriptor ;
7684 private final int modifiers ;
77- private CodePointer javaCall ;
7885 private CodePointer callWrapper ;
86+ private int vtableOffset = VTABLE_OFFSET_NOT_YET_COMPUTED ;
87+ private CodePointer directTarget ;
88+ private PointerBase newObjectTarget ; // for constructors
7989 @ SuppressWarnings ("unused" ) private CFunctionPointer varargsWrapper ;
8090 @ SuppressWarnings ("unused" ) private CFunctionPointer arrayWrapper ;
8191 @ SuppressWarnings ("unused" ) private CFunctionPointer valistWrapper ;
8292 @ SuppressWarnings ("unused" ) private CFunctionPointer varargsNonvirtualWrapper ;
8393 @ SuppressWarnings ("unused" ) private CFunctionPointer arrayNonvirtualWrapper ;
8494 @ SuppressWarnings ("unused" ) private CFunctionPointer valistNonvirtualWrapper ;
85- @ Platforms (HOSTED_ONLY .class ) private final JNIJavaCallMethod javaCallMethod ;
95+ @ Platforms (HOSTED_ONLY .class ) private final ResolvedJavaMethod targetMethod ;
96+ @ Platforms (HOSTED_ONLY .class ) private final ResolvedJavaMethod newObjectTargetMethod ;
8697 @ Platforms (HOSTED_ONLY .class ) private final JNIJavaCallWrapperMethod callWrapperMethod ;
8798 @ Platforms (HOSTED_ONLY .class ) private final JNIJavaCallVariantWrapperMethod varargsWrapperMethod ;
8899 @ Platforms (HOSTED_ONLY .class ) private final JNIJavaCallVariantWrapperMethod arrayWrapperMethod ;
@@ -92,9 +103,9 @@ static ResolvedJavaField getCallVariantWrapperField(MetaAccessProvider metaAcces
92103 @ Platforms (HOSTED_ONLY .class ) private final JNIJavaCallVariantWrapperMethod valistNonvirtualWrapperMethod ;
93104
94105 JNIAccessibleMethod (JNIAccessibleMethodDescriptor descriptor ,
95- int modifiers ,
96106 JNIAccessibleClass declaringClass ,
97- JNIJavaCallMethod javaCallMethod ,
107+ ResolvedJavaMethod targetMethod ,
108+ ResolvedJavaMethod newObjectTargetMethod ,
98109 JNIJavaCallWrapperMethod callWrapperMethod ,
99110 JNIJavaCallVariantWrapperMethod varargsWrapper ,
100111 JNIJavaCallVariantWrapperMethod arrayWrapper ,
@@ -103,13 +114,14 @@ static ResolvedJavaField getCallVariantWrapperField(MetaAccessProvider metaAcces
103114 JNIJavaCallVariantWrapperMethod arrayNonvirtualWrapper ,
104115 JNIJavaCallVariantWrapperMethod valistNonvirtualWrapper ) {
105116 super (declaringClass );
106- assert javaCallMethod != null && callWrapperMethod != null && varargsWrapper != null && arrayWrapper != null && valistWrapper != null ;
107- assert (Modifier .isStatic (modifiers ) || Modifier .isAbstract (modifiers )) //
117+ assert callWrapperMethod != null && varargsWrapper != null && arrayWrapper != null && valistWrapper != null ;
118+ assert (targetMethod .isStatic () || targetMethod .isAbstract ()) //
108119 ? (varargsNonvirtualWrapper == null && arrayNonvirtualWrapper == null && valistNonvirtualWrapper == null )
109120 : (varargsNonvirtualWrapper != null & arrayNonvirtualWrapper != null && valistNonvirtualWrapper != null );
110121 this .descriptor = descriptor ;
111- this .modifiers = modifiers ;
112- this .javaCallMethod = javaCallMethod ;
122+ this .modifiers = targetMethod .getModifiers ();
123+ this .targetMethod = targetMethod ;
124+ this .newObjectTargetMethod = newObjectTargetMethod ;
113125 this .callWrapperMethod = callWrapperMethod ;
114126 this .varargsWrapperMethod = varargsWrapper ;
115127 this .arrayWrapperMethod = arrayWrapper ;
@@ -119,18 +131,31 @@ static ResolvedJavaField getCallVariantWrapperField(MetaAccessProvider metaAcces
119131 this .valistNonvirtualWrapperMethod = valistNonvirtualWrapper ;
120132 }
121133
122- @ AlwaysInline ("Work around an issue with the LLVM backend with which the return value was accessed incorrectly." )
123- @ Uninterruptible (reason = "Allow inlining from entry points, which are uninterruptible." , mayBeInlined = true )
124- public CodePointer getJavaCallAddress () {
125- return javaCall ;
126- }
127-
128134 @ AlwaysInline ("Work around an issue with the LLVM backend with which the return value was accessed incorrectly." )
129135 @ Uninterruptible (reason = "Allow inlining from call wrappers, which are uninterruptible." , mayBeInlined = true )
130136 public CodePointer getCallWrapperAddress () {
131137 return callWrapper ;
132138 }
133139
140+ @ AlwaysInline ("Work around an issue with the LLVM backend with which the return value was accessed incorrectly." )
141+ public CodePointer getJavaCallAddress (Object instance , boolean nonVirtual ) {
142+ if (!nonVirtual ) {
143+ assert vtableOffset != JNIAccessibleMethod .VTABLE_OFFSET_NOT_YET_COMPUTED ;
144+ if (vtableOffset != JNIAccessibleMethod .STATICALLY_BOUND_METHOD ) {
145+ return BarrieredAccess .readWord (instance .getClass (), vtableOffset , NamedLocationIdentity .FINAL_LOCATION );
146+ }
147+ }
148+ return directTarget ;
149+ }
150+
151+ public PointerBase getNewObjectAddress () {
152+ return newObjectTarget ;
153+ }
154+
155+ public Class <?> getDeclaringClassObject () {
156+ return getDeclaringClass ().getClassObject ();
157+ }
158+
134159 boolean isPublic () {
135160 return Modifier .isPublic (modifiers );
136161 }
@@ -143,7 +168,19 @@ boolean isStatic() {
143168 void finishBeforeCompilation (CompilationAccessImpl access ) {
144169 HostedUniverse hUniverse = access .getUniverse ();
145170 AnalysisUniverse aUniverse = access .getUniverse ().getBigBang ().getUniverse ();
146- javaCall = new MethodPointer (hUniverse .lookup (aUniverse .lookup (javaCallMethod )));
171+ HostedMethod hTarget = hUniverse .lookup (aUniverse .lookup (targetMethod ));
172+ if (hTarget .canBeStaticallyBound ()) {
173+ vtableOffset = STATICALLY_BOUND_METHOD ;
174+ } else {
175+ vtableOffset = KnownOffsets .singleton ().getVTableOffset (hTarget .getVTableIndex ());
176+ }
177+ directTarget = new MethodPointer (hTarget );
178+ if (newObjectTargetMethod != null ) {
179+ newObjectTarget = new MethodPointer (hUniverse .lookup (aUniverse .lookup (newObjectTargetMethod )));
180+ } else if (targetMethod .isConstructor ()) {
181+ assert targetMethod .getDeclaringClass ().isAbstract ();
182+ newObjectTarget = WordFactory .signed (NEW_OBJECT_INVALID_FOR_ABSTRACT_TYPE );
183+ }
147184 callWrapper = new MethodPointer (hUniverse .lookup (aUniverse .lookup (callWrapperMethod )));
148185 varargsWrapper = new MethodPointer (hUniverse .lookup (aUniverse .lookup (varargsWrapperMethod )));
149186 arrayWrapper = new MethodPointer (hUniverse .lookup (aUniverse .lookup (arrayWrapperMethod )));
0 commit comments