26
26
27
27
import java .lang .reflect .Modifier ;
28
28
29
+ import org .graalvm .compiler .nodes .NamedLocationIdentity ;
30
+ import org .graalvm .compiler .word .BarrieredAccess ;
29
31
import org .graalvm .nativeimage .Platform .HOSTED_ONLY ;
30
32
import org .graalvm .nativeimage .Platforms ;
31
33
import org .graalvm .nativeimage .c .function .CFunctionPointer ;
32
34
import org .graalvm .nativeimage .c .function .CodePointer ;
35
+ import org .graalvm .word .PointerBase ;
36
+ import org .graalvm .word .WordFactory ;
33
37
34
38
import com .oracle .graal .pointsto .meta .AnalysisUniverse ;
35
39
import com .oracle .svm .core .annotate .AlwaysInline ;
36
40
import com .oracle .svm .core .annotate .Uninterruptible ;
41
+ import com .oracle .svm .core .graal .meta .KnownOffsets ;
37
42
import com .oracle .svm .core .meta .MethodPointer ;
38
43
import com .oracle .svm .core .util .VMError ;
39
44
import com .oracle .svm .hosted .FeatureImpl .CompilationAccessImpl ;
45
+ import com .oracle .svm .hosted .meta .HostedMethod ;
40
46
import com .oracle .svm .hosted .meta .HostedUniverse ;
41
- import com .oracle .svm .jni .hosted .JNIJavaCallMethod ;
42
47
import com .oracle .svm .jni .hosted .JNIJavaCallVariantWrapperMethod ;
43
48
import com .oracle .svm .jni .hosted .JNIJavaCallVariantWrapperMethod .CallVariant ;
44
49
import com .oracle .svm .jni .hosted .JNIJavaCallWrapperMethod ;
53
58
* Information on a method that can be looked up and called via JNI.
54
59
*/
55
60
public 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 ;
56
64
57
65
static ResolvedJavaField getCallVariantWrapperField (MetaAccessProvider metaAccess , CallVariant variant , boolean nonVirtual ) {
58
66
StringBuilder name = new StringBuilder (32 );
@@ -74,15 +82,18 @@ static ResolvedJavaField getCallVariantWrapperField(MetaAccessProvider metaAcces
74
82
75
83
@ Platforms (HOSTED_ONLY .class ) private final JNIAccessibleMethodDescriptor descriptor ;
76
84
private final int modifiers ;
77
- private CodePointer javaCall ;
85
+ private int vtableOffset = VTABLE_OFFSET_NOT_YET_COMPUTED ;
86
+ private CodePointer nonvirtualTarget ;
87
+ private PointerBase newObjectTarget ; // for constructors
78
88
private CodePointer callWrapper ;
79
89
@ SuppressWarnings ("unused" ) private CFunctionPointer varargsWrapper ;
80
90
@ SuppressWarnings ("unused" ) private CFunctionPointer arrayWrapper ;
81
91
@ SuppressWarnings ("unused" ) private CFunctionPointer valistWrapper ;
82
92
@ SuppressWarnings ("unused" ) private CFunctionPointer varargsNonvirtualWrapper ;
83
93
@ SuppressWarnings ("unused" ) private CFunctionPointer arrayNonvirtualWrapper ;
84
94
@ 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 ;
86
97
@ Platforms (HOSTED_ONLY .class ) private final JNIJavaCallWrapperMethod callWrapperMethod ;
87
98
@ Platforms (HOSTED_ONLY .class ) private final JNIJavaCallVariantWrapperMethod varargsWrapperMethod ;
88
99
@ Platforms (HOSTED_ONLY .class ) private final JNIJavaCallVariantWrapperMethod arrayWrapperMethod ;
@@ -92,9 +103,9 @@ static ResolvedJavaField getCallVariantWrapperField(MetaAccessProvider metaAcces
92
103
@ Platforms (HOSTED_ONLY .class ) private final JNIJavaCallVariantWrapperMethod valistNonvirtualWrapperMethod ;
93
104
94
105
JNIAccessibleMethod (JNIAccessibleMethodDescriptor descriptor ,
95
- int modifiers ,
96
106
JNIAccessibleClass declaringClass ,
97
- JNIJavaCallMethod javaCallMethod ,
107
+ ResolvedJavaMethod targetMethod ,
108
+ ResolvedJavaMethod newObjectTargetMethod ,
98
109
JNIJavaCallWrapperMethod callWrapperMethod ,
99
110
JNIJavaCallVariantWrapperMethod varargsWrapper ,
100
111
JNIJavaCallVariantWrapperMethod arrayWrapper ,
@@ -103,13 +114,14 @@ static ResolvedJavaField getCallVariantWrapperField(MetaAccessProvider metaAcces
103
114
JNIJavaCallVariantWrapperMethod arrayNonvirtualWrapper ,
104
115
JNIJavaCallVariantWrapperMethod valistNonvirtualWrapper ) {
105
116
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 ()) //
108
119
? (varargsNonvirtualWrapper == null && arrayNonvirtualWrapper == null && valistNonvirtualWrapper == null )
109
120
: (varargsNonvirtualWrapper != null & arrayNonvirtualWrapper != null && valistNonvirtualWrapper != null );
110
121
this .descriptor = descriptor ;
111
- this .modifiers = modifiers ;
112
- this .javaCallMethod = javaCallMethod ;
122
+ this .modifiers = targetMethod .getModifiers ();
123
+ this .targetMethod = targetMethod ;
124
+ this .newObjectTargetMethod = newObjectTargetMethod ;
113
125
this .callWrapperMethod = callWrapperMethod ;
114
126
this .varargsWrapperMethod = varargsWrapper ;
115
127
this .arrayWrapperMethod = arrayWrapper ;
@@ -119,18 +131,31 @@ static ResolvedJavaField getCallVariantWrapperField(MetaAccessProvider metaAcces
119
131
this .valistNonvirtualWrapperMethod = valistNonvirtualWrapper ;
120
132
}
121
133
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
-
128
134
@ AlwaysInline ("Work around an issue with the LLVM backend with which the return value was accessed incorrectly." )
129
135
@ Uninterruptible (reason = "Allow inlining from call wrappers, which are uninterruptible." , mayBeInlined = true )
130
136
public CodePointer getCallWrapperAddress () {
131
137
return callWrapper ;
132
138
}
133
139
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 nonvirtualTarget ;
149
+ }
150
+
151
+ public PointerBase getNewObjectAddress () {
152
+ return newObjectTarget ;
153
+ }
154
+
155
+ public Class <?> getDeclaringClassObject () {
156
+ return getDeclaringClass ().getClassObject ();
157
+ }
158
+
134
159
boolean isPublic () {
135
160
return Modifier .isPublic (modifiers );
136
161
}
@@ -143,7 +168,19 @@ boolean isStatic() {
143
168
void finishBeforeCompilation (CompilationAccessImpl access ) {
144
169
HostedUniverse hUniverse = access .getUniverse ();
145
170
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
+ nonvirtualTarget = 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
+ }
147
184
callWrapper = new MethodPointer (hUniverse .lookup (aUniverse .lookup (callWrapperMethod )));
148
185
varargsWrapper = new MethodPointer (hUniverse .lookup (aUniverse .lookup (varargsWrapperMethod )));
149
186
arrayWrapper = new MethodPointer (hUniverse .lookup (aUniverse .lookup (arrayWrapperMethod )));
0 commit comments