28
28
29
29
import java .lang .invoke .MethodHandle ;
30
30
import java .lang .invoke .MethodType ;
31
+ import java .lang .reflect .AccessibleObject ;
31
32
import java .lang .reflect .Constructor ;
32
33
import java .lang .reflect .Field ;
33
34
import java .lang .reflect .InvocationTargetException ;
35
+ import java .lang .reflect .Member ;
34
36
import java .lang .reflect .Method ;
35
37
import java .lang .reflect .Modifier ;
36
38
import java .util .Arrays ;
45
47
import com .oracle .svm .core .classinitialization .EnsureClassInitializedNode ;
46
48
import com .oracle .svm .core .invoke .MethodHandleUtils ;
47
49
import com .oracle .svm .core .invoke .Target_java_lang_invoke_MemberName ;
50
+ import com .oracle .svm .core .reflect .SubstrateAccessor ;
51
+ import com .oracle .svm .core .reflect .SubstrateConstructorAccessor ;
48
52
import com .oracle .svm .core .reflect .SubstrateMethodAccessor ;
49
53
import com .oracle .svm .core .reflect .target .Target_java_lang_reflect_AccessibleObject ;
54
+ import com .oracle .svm .core .reflect .target .Target_java_lang_reflect_Constructor ;
50
55
import com .oracle .svm .core .reflect .target .Target_java_lang_reflect_Method ;
51
- import com .oracle .svm .core .reflect .target .Target_jdk_internal_reflect_MethodAccessor ;
52
56
import com .oracle .svm .core .util .VMError ;
53
57
54
58
import sun .invoke .util .ValueConversions ;
@@ -118,22 +122,22 @@ Object invokeExact(Object... args) throws Throwable {
118
122
119
123
@ Substitute (polymorphicSignature = true )
120
124
static Object linkToVirtual (Object ... args ) throws Throwable {
121
- return Util_java_lang_invoke_MethodHandle .linkTo (true , args );
125
+ return Util_java_lang_invoke_MethodHandle .linkTo (args );
122
126
}
123
127
124
128
@ Substitute (polymorphicSignature = true )
125
129
static Object linkToStatic (Object ... args ) throws Throwable {
126
- return Util_java_lang_invoke_MethodHandle .linkTo (false , args );
130
+ return Util_java_lang_invoke_MethodHandle .linkTo (args );
127
131
}
128
132
129
133
@ Substitute (polymorphicSignature = true )
130
134
static Object linkToInterface (Object ... args ) throws Throwable {
131
- return Util_java_lang_invoke_MethodHandle .linkTo (true , args );
135
+ return Util_java_lang_invoke_MethodHandle .linkTo (args );
132
136
}
133
137
134
138
@ Substitute (polymorphicSignature = true )
135
139
static Object linkToSpecial (Object ... args ) throws Throwable {
136
- return Util_java_lang_invoke_MethodHandle .linkTo (true , args );
140
+ return Util_java_lang_invoke_MethodHandle .linkTo (args );
137
141
}
138
142
139
143
@ Substitute (polymorphicSignature = true )
@@ -158,13 +162,10 @@ void maybeCustomize() {
158
162
}
159
163
160
164
final class Util_java_lang_invoke_MethodHandle {
161
- static Object linkTo (boolean hasReceiver , Object ... args ) throws Throwable {
165
+ static Object linkTo (Object ... args ) throws Throwable {
162
166
assert args .length > 0 ;
163
167
Target_java_lang_invoke_MemberName memberName = (Target_java_lang_invoke_MemberName ) args [args .length - 1 ];
164
- MethodType methodType = memberName .getMethodType ();
165
- if (hasReceiver ) {
166
- methodType = methodType .insertParameterTypes (0 , memberName .getDeclaringClass ());
167
- }
168
+ MethodType methodType = memberName .getInvocationType ();
168
169
return MethodHandleUtils .cast (invokeInternal (memberName , methodType , Arrays .copyOf (args , args .length - 1 )), methodType .returnType ());
169
170
}
170
171
@@ -179,95 +180,129 @@ static Object invokeInternal(Target_java_lang_invoke_MemberName memberName, Meth
179
180
}
180
181
181
182
if (memberName .intrinsic != null ) { /* Intrinsic call */
182
- assert memberName .reflectAccess == null ;
183
+ VMError . guarantee ( memberName .reflectAccess == null ) ;
183
184
return memberName .intrinsic .execute (args );
184
- } else if (memberName .isField ()) { /* Field access */
185
- Target_java_lang_reflect_AccessibleObject executable = SubstrateUtil .cast (memberName .reflectAccess , Target_java_lang_reflect_AccessibleObject .class );
186
-
187
- /* Access control was already performed by the JDK code calling invokeBasic */
188
- boolean oldOverride = executable .override ;
189
- executable .override = true ;
190
- try {
191
- Field field = (Field ) memberName .reflectAccess ;
192
- byte refKind = memberName .getReferenceKind ();
193
- if (Modifier .isStatic (field .getModifiers ())) {
194
- if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_getStatic ) {
195
- assert (args == null || args .length == 0 ) && field .canAccess (null );
196
- return field .get (null );
197
- } else if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_putStatic ) {
198
- assert args .length == 1 && field .canAccess (null );
199
- Object value = args [0 ];
200
- field .set (null , value );
201
- return null ;
202
- } else {
203
- throw VMError .shouldNotReachHere ("Wrong reference kind for static field access: " + memberName .getReferenceKind ());
204
- }
205
- } else {
206
- if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_getField ) {
207
- assert args .length == 1 && field .canAccess (args [0 ]);
208
- Object receiver = args [0 ];
209
- return field .get (receiver );
210
- } else if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_putField ) {
211
- assert args .length == 2 && field .canAccess (args [0 ]);
212
- Object receiver = args [0 ];
213
- Object value = args [1 ];
214
- field .set (receiver , value );
215
- return null ;
216
- } else {
217
- throw VMError .shouldNotReachHere ("Wrong reference kind for instance field access: " + memberName .getReferenceKind ());
218
- }
219
- }
220
- } finally {
221
- executable .override = oldOverride ;
222
- }
223
- } else { /* Method or constructor invocation */
224
- assert args .length == methodType .parameterCount ();
225
- for (int i = 0 ; i < args .length ; ++i ) {
226
- Class <?> expectedParamType = methodType .parameterType (i );
227
- if (expectedParamType .isPrimitive ()) {
228
- Wrapper destWrapper = Wrapper .forPrimitiveType (expectedParamType );
229
- Wrapper srcWrapper = Wrapper .forWrapperType (args [i ].getClass ());
230
- if (destWrapper != srcWrapper ) {
231
- /* We can't rely on automatic casting for the argument */
232
- Target_java_lang_invoke_MethodHandle typeConverter = SubstrateUtil .cast (ValueConversions .convertPrimitive (srcWrapper , destWrapper ),
233
- Target_java_lang_invoke_MethodHandle .class );
234
- args [i ] = typeConverter .invokeBasic (args [i ]);
235
- }
236
- }
185
+ }
186
+
187
+ Target_java_lang_reflect_AccessibleObject reflectAccess = SubstrateUtil .cast (memberName .reflectAccess , Target_java_lang_reflect_AccessibleObject .class );
188
+
189
+ /* Access control was already performed by the JDK code calling invokeBasic */
190
+ boolean oldOverride = reflectAccess .override ;
191
+ reflectAccess .override = true ;
192
+ try {
193
+ byte refKind = memberName .getReferenceKind ();
194
+ /* This cannot be a switch as the REF_ aliases are not declared as final. */
195
+ if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_getField ) {
196
+ checkArgs (args , 1 , "getField" );
197
+ Object receiver = args [0 ];
198
+ Field field = asField (memberName , receiver );
199
+ return field .get (receiver );
200
+ } else if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_getStatic ) {
201
+ checkArgs (args , 0 , "getStatic" );
202
+ Field field = asField (memberName , null );
203
+ return field .get (null );
204
+ } else if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_putField ) {
205
+ checkArgs (args , 2 , "putField" );
206
+ Object receiver = args [0 ];
207
+ Object value = args [1 ];
208
+ Field field = asField (memberName , receiver );
209
+ field .set (receiver , value );
210
+ return null ;
211
+ } else if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_putStatic ) {
212
+ checkArgs (args , 1 , "putStatic" );
213
+ Object value = args [0 ];
214
+ Field field = asField (memberName , null );
215
+ field .set (null , value );
216
+ return null ;
217
+ } else if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_invokeVirtual ||
218
+ refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_invokeInterface ) {
219
+ convertArgs (args , methodType );
220
+ Object receiver = args [0 ];
221
+ Object [] invokeArgs = Arrays .copyOfRange (args , 1 , args .length );
222
+ Method method = asMethod (memberName , receiver );
223
+ return method .invoke (receiver , invokeArgs );
224
+ } else if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_invokeStatic ) {
225
+ convertArgs (args , methodType );
226
+ Method method = asMethod (memberName , null );
227
+ return method .invoke (null , args );
228
+ } else if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_invokeSpecial ) {
229
+ convertArgs (args , methodType );
230
+ Object receiver = args [0 ];
231
+ Object [] invokeArgs = Arrays .copyOfRange (args , 1 , args .length );
232
+ SubstrateAccessor accessor = getAccessor (memberName );
233
+ Object returnValue = accessor .invokeSpecial (receiver , invokeArgs );
234
+ return methodType .returnType () == void .class ? null : returnValue ;
235
+ } else if (refKind == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_newInvokeSpecial ) {
236
+ convertArgs (args , methodType );
237
+ Constructor <?> constructor = asConstructor (memberName );
238
+ return constructor .newInstance (args );
239
+ } else {
240
+ throw VMError .shouldNotReachHere ("Unknown method handle reference kind: " + refKind );
237
241
}
242
+ } catch (InvocationTargetException e ) {
243
+ /* Exceptions are thrown unchanged from method handles */
244
+ throw e .getCause ();
245
+ } finally {
246
+ reflectAccess .override = oldOverride ;
247
+ }
248
+ }
249
+
250
+ private static Field asField (Target_java_lang_invoke_MemberName memberName , Object receiver ) {
251
+ VMError .guarantee (memberName .isField (), "Cannot perform field operations on an executable" );
252
+ Field field = (Field ) memberName .reflectAccess ;
253
+ checkMember (field , receiver );
254
+ return field ;
255
+ }
256
+
257
+ private static Method asMethod (Target_java_lang_invoke_MemberName memberName , Object receiver ) {
258
+ VMError .guarantee (memberName .isMethod (), "Cannot perform method operations on a field or constructor" );
259
+ Method method = (Method ) memberName .reflectAccess ;
260
+ checkMember (method , receiver );
261
+ return method ;
262
+ }
263
+
264
+ private static Constructor <?> asConstructor (Target_java_lang_invoke_MemberName memberName ) {
265
+ VMError .guarantee (memberName .isConstructor (), "Cannot perform constructor operations on a field or constructor" );
266
+ Constructor <?> constructor = (Constructor <?>) memberName .reflectAccess ;
267
+ checkMember (constructor , null );
268
+ return constructor ;
269
+ }
270
+
271
+ private static <T extends AccessibleObject & Member > void checkMember (T member , Object receiver ) {
272
+ if (!(member instanceof Constructor <?>)) {
273
+ boolean isStatic = receiver == null ;
274
+ VMError .guarantee (Modifier .isStatic (member .getModifiers ()) == isStatic ,
275
+ "Cannot perform %s operation on a %s member" .formatted (isStatic ? "static" : "non-static" , isStatic ? "non-static" : "static" ));
276
+ }
277
+ VMError .guarantee (member .canAccess (receiver ), "The member should have been made accessible by the method handle implementation" );
278
+ }
279
+
280
+ private static SubstrateAccessor getAccessor (Target_java_lang_invoke_MemberName memberName ) {
281
+ VMError .guarantee (memberName .isInvocable (), "Cannot perform invokeSpecial on a field" );
282
+ if (memberName .isMethod ()) {
283
+ return SubstrateUtil .cast (SubstrateUtil .cast (memberName .reflectAccess , Target_java_lang_reflect_Method .class ).acquireMethodAccessor (), SubstrateMethodAccessor .class );
284
+ } else {
285
+ return SubstrateUtil .cast (SubstrateUtil .cast (memberName .reflectAccess , Target_java_lang_reflect_Constructor .class ).acquireConstructorAccessor (), SubstrateConstructorAccessor .class );
286
+ }
287
+ }
288
+
289
+ private static void checkArgs (Object [] args , int expectedLength , String methodName ) {
290
+ VMError .guarantee ((expectedLength == 0 && args == null ) || args .length == expectedLength , "%s requires exactly %d arguments" .formatted (methodName , expectedLength ));
291
+ }
238
292
239
- Target_java_lang_reflect_AccessibleObject executable = SubstrateUtil .cast (memberName .reflectAccess , Target_java_lang_reflect_AccessibleObject .class );
240
-
241
- /* Access control was already performed by the JDK code calling invokeBasic */
242
- boolean oldOverride = executable .override ;
243
- executable .override = true ;
244
- try {
245
- if (memberName .isConstructor ()) {
246
- Constructor <?> constructor = (Constructor <?>) memberName .reflectAccess ;
247
- assert constructor .canAccess (null );
248
- return constructor .newInstance (args );
249
- } else {
250
- Method method = (Method ) memberName .reflectAccess ;
251
- if (Modifier .isStatic (method .getModifiers ())) {
252
- assert method .canAccess (null );
253
- return method .invoke (null , args );
254
- } else {
255
- assert method .canAccess (args [0 ]);
256
- Object receiver = args [0 ];
257
- Object [] invokeArgs = Arrays .copyOfRange (args , 1 , args .length );
258
- if (memberName .getReferenceKind () == Target_java_lang_invoke_MethodHandleNatives_Constants .REF_invokeSpecial ) {
259
- Target_jdk_internal_reflect_MethodAccessor accessor = SubstrateUtil .cast (method , Target_java_lang_reflect_Method .class ).acquireMethodAccessor ();
260
- return SubstrateUtil .cast (accessor , SubstrateMethodAccessor .class ).invokeSpecial (receiver , invokeArgs );
261
- } else {
262
- return method .invoke (receiver , invokeArgs );
263
- }
264
- }
293
+ private static void convertArgs (Object [] args , MethodType methodType ) throws Throwable {
294
+ assert args .length == methodType .parameterCount ();
295
+ for (int i = 0 ; i < args .length ; ++i ) {
296
+ Class <?> expectedParamType = methodType .parameterType (i );
297
+ if (expectedParamType .isPrimitive ()) {
298
+ Wrapper destWrapper = Wrapper .forPrimitiveType (expectedParamType );
299
+ Wrapper srcWrapper = Wrapper .forWrapperType (args [i ].getClass ());
300
+ if (destWrapper != srcWrapper ) {
301
+ /* We can't rely on automatic casting for the argument */
302
+ Target_java_lang_invoke_MethodHandle typeConverter = SubstrateUtil .cast (ValueConversions .convertPrimitive (srcWrapper , destWrapper ),
303
+ Target_java_lang_invoke_MethodHandle .class );
304
+ args [i ] = typeConverter .invokeBasic (args [i ]);
265
305
}
266
- } catch (InvocationTargetException e ) {
267
- /* Exceptions are thrown unchanged from method handles */
268
- throw e .getCause ();
269
- } finally {
270
- executable .override = oldOverride ;
271
306
}
272
307
}
273
308
}
0 commit comments