42
42
43
43
import static jdk .vm .ci .hotspot .HotSpotJVMCIRuntime .runtime ;
44
44
45
- import java .lang .reflect .InvocationTargetException ;
46
- import java .lang .reflect .Method ;
47
- import java .util .Arrays ;
48
-
45
+ import org .graalvm .nativeimage .ImageInfo ;
49
46
import org .graalvm .nativeimage .IsolateThread ;
50
47
import org .graalvm .nativeimage .c .function .CEntryPoint ;
51
48
import org .graalvm .word .PointerBase ;
58
55
import jdk .vm .ci .hotspot .HotSpotResolvedJavaType ;
59
56
import jdk .vm .ci .hotspot .HotSpotSpeculationLog ;
60
57
import jdk .vm .ci .services .Services ;
61
- import org .graalvm .nativeimage .ImageInfo ;
62
58
63
59
/**
64
60
* Access to libgraal, a shared library containing an AOT compiled version of Graal produced by
65
61
* GraalVM Native Image. The libgraal library is only available if the HotSpot
66
62
* {@code UseJVMCINativeLibrary} flag is true and the current runtime includes the relevant JVMCI
67
63
* API additions for accessing libgraal.
68
64
*
69
- * The {@link #isAvailable()} method is provided to test these conditions. It must be used to guard
70
- * usage of all other methods in this class. In addition, only the following methods can be called
71
- * from within libgraal:
72
- * <ul>
73
- * <li>{@link #isAvailable()}</li>
74
- * <li>{@link #translate(Object)}</li>
75
- * <li>{@link #unhand(Class, long)}</li>
76
- * </ul>
77
- *
78
65
* The typical usage of this class is to {@linkplain #registerNativeMethods link} and call
79
66
* {@link CEntryPoint}s in libgraal. Each call to a {@link CEntryPoint} requires an
80
67
* {@link IsolateThread} argument which can be {@linkplain LibGraalScope#getIsolateThread obtained}
81
68
* from a {@link LibGraalScope}.
82
69
*/
83
70
public class LibGraal {
84
71
85
- // NOTE: The use of reflection to access JVMCI API is to support
86
- // compiling on JDKs with varying versions of JVMCI.
87
-
88
72
static {
89
73
// Initialize JVMCI to ensure JVMCI opens its packages to Graal.
90
74
ModulesSupport .exportJVMCI (LibGraal .class );
91
75
Services .initializeJVMCI ();
92
76
}
93
77
94
- private static final Method unhand = methodOrNull (HotSpotJVMCIRuntime .class , "unhand" , sig (Class .class , Long .TYPE ));
95
- private static final Method translate = methodIf (unhand , HotSpotJVMCIRuntime .class , "translate" , sig (Object .class ));
96
- private static final Method registerNativeMethods = methodIf (unhand , HotSpotJVMCIRuntime .class , "registerNativeMethods" , sig (Class .class ));
97
- private static final Method isCurrentThreadAttached = methodIf (unhand , HotSpotJVMCIRuntime .class , "isCurrentThreadAttached" );
98
- private static final Method attachCurrentThread = methodIf (unhand , HotSpotJVMCIRuntime .class , "attachCurrentThread" , sig (Boolean .TYPE , long [].class ), sig (Boolean .TYPE ));
99
- private static final Method detachCurrentThread = methodIf (unhand , HotSpotJVMCIRuntime .class , "detachCurrentThread" , sig (Boolean .TYPE ), sig ());
100
- private static final Method getFailedSpeculationsAddress = methodIf (unhand , HotSpotSpeculationLog .class , "getFailedSpeculationsAddress" );
78
+ static final long INITIAL_ISOLATE = ImageInfo .inImageBuildtimeCode () ? 0L : initializeLibgraal ();
79
+ static final boolean AVAILABLE = INITIAL_ISOLATE != 0L ;
101
80
102
- private static final Method asResolvedJavaType = methodOrNull (HotSpotJVMCIRuntime .class , "asResolvedJavaType" , sig (Long .TYPE ));
103
- private static final Method getJObjectValue = methodIf (asResolvedJavaType , HotSpotJVMCIRuntime .class , "getJObjectValue" , sig (HotSpotObjectConstant .class ));
81
+ private static long initializeLibgraal () {
82
+ try {
83
+ long [] javaVMInfo = runtime ().registerNativeMethods (LibGraalScope .class );
84
+ long isolate = javaVMInfo [1 ];
85
+ return isolate ;
86
+ } catch (UnsupportedOperationException e ) {
87
+ return 0L ;
88
+ }
89
+ }
104
90
105
91
/**
106
92
* Determines if libgraal is available for use.
107
93
*/
108
94
public static boolean isAvailable () {
109
- return available ;
110
- }
111
-
112
- /**
113
- * Determines if the current runtime supports building a libgraal image.
114
- */
115
- public static boolean isSupported () {
116
- return getFailedSpeculationsAddress != null ;
95
+ return AVAILABLE ;
117
96
}
118
97
119
98
/**
@@ -136,13 +115,7 @@ public static void registerNativeMethods(Class<?> clazz) {
136
115
if (!isAvailable ()) {
137
116
throw new IllegalStateException ();
138
117
}
139
- try {
140
- registerNativeMethods .invoke (runtime (), clazz );
141
- } catch (Error e ) {
142
- throw e ;
143
- } catch (Throwable throwable ) {
144
- throw new InternalError (throwable );
145
- }
118
+ runtime ().registerNativeMethods (clazz );
146
119
}
147
120
148
121
/**
@@ -160,11 +133,7 @@ public static long translate(Object obj) {
160
133
if (!isAvailable ()) {
161
134
throw new IllegalStateException ();
162
135
}
163
- try {
164
- return (long ) translate .invoke (runtime (), obj );
165
- } catch (Throwable throwable ) {
166
- throw new InternalError (throwable );
167
- }
136
+ return runtime ().translate (obj );
168
137
}
169
138
170
139
/**
@@ -181,73 +150,29 @@ public static <T> T unhand(Class<T> type, long handle) {
181
150
if (!isAvailable ()) {
182
151
throw new IllegalStateException ();
183
152
}
184
- try {
185
- return (T ) unhand .invoke (runtime (), type , handle );
186
- } catch (Throwable throwable ) {
187
- throw new InternalError (throwable );
188
- }
153
+ return runtime ().unhand (type , handle );
189
154
}
190
155
191
- private static long initializeLibgraal () {
192
- if (registerNativeMethods == null ) {
193
- return 0L ;
194
- }
195
- try {
196
- long [] javaVMInfo = (long []) registerNativeMethods .invoke (runtime (), LibGraalScope .class );
197
- long isolate = javaVMInfo [1 ];
198
- return isolate ;
199
- } catch (InvocationTargetException e ) {
200
- if (e .getTargetException () instanceof UnsupportedOperationException ) {
201
- // libgraal available but not enabled
202
- return 0L ;
203
- }
204
- throw new InternalError (e );
205
- } catch (Throwable throwable ) {
206
- throw new InternalError (throwable );
207
- }
208
- }
209
-
210
- static final long initialIsolate = ImageInfo .inImageBuildtimeCode () ? 0L : initializeLibgraal ();
211
- static final boolean available = initialIsolate != 0L ;
212
-
213
156
/**
214
157
* Determines if the current thread is {@linkplain #attachCurrentThread attached} to the peer
215
158
* runtime.
216
159
*/
217
160
static boolean isCurrentThreadAttached () {
218
- try {
219
- return (boolean ) isCurrentThreadAttached .invoke (runtime ());
220
- } catch (Throwable throwable ) {
221
- throw new InternalError (throwable );
222
- }
161
+ return runtime ().isCurrentThreadAttached ();
223
162
}
224
163
225
164
/**
226
165
* @see HotSpotJVMCIRuntime#getJObjectValue(HotSpotObjectConstant)
227
166
*/
228
167
public static <T extends PointerBase > T getJObjectValue (HotSpotObjectConstant constant ) {
229
- if (getJObjectValue == null ) {
230
- return WordFactory .nullPointer ();
231
- }
232
- try {
233
- return WordFactory .pointer ((long ) getJObjectValue .invoke (runtime (), constant ));
234
- } catch (Throwable throwable ) {
235
- throw new InternalError (throwable );
236
- }
168
+ return WordFactory .pointer (runtime ().getJObjectValue (constant ));
237
169
}
238
170
239
171
/**
240
172
* @see HotSpotJVMCIRuntime#asResolvedJavaType(long)
241
173
*/
242
174
public static HotSpotResolvedJavaType asResolvedJavaType (PointerBase pointer ) {
243
- if (asResolvedJavaType == null ) {
244
- return null ;
245
- }
246
- try {
247
- return (HotSpotResolvedJavaType ) asResolvedJavaType .invoke (runtime (), pointer .rawValue ());
248
- } catch (Throwable throwable ) {
249
- throw new InternalError (throwable );
250
- }
175
+ return runtime ().asResolvedJavaType (pointer .rawValue ());
251
176
}
252
177
253
178
/**
@@ -259,23 +184,12 @@ public static HotSpotResolvedJavaType asResolvedJavaType(PointerBase pointer) {
259
184
* thread was already attached
260
185
*/
261
186
public static boolean attachCurrentThread (boolean isDaemon , long [] isolate ) {
262
- try {
263
- if (attachCurrentThread .getParameterCount () == 2 ) {
264
- long [] javaVMInfo = isolate != null ? new long [4 ] : null ;
265
- boolean res = (boolean ) attachCurrentThread .invoke (runtime (), isDaemon , javaVMInfo );
266
- if (isolate != null ) {
267
- isolate [0 ] = javaVMInfo [1 ];
268
- }
269
- return res ;
270
- } else {
271
- if (isolate != null ) {
272
- isolate [0 ] = initialIsolate ;
273
- }
274
- return (boolean ) attachCurrentThread .invoke (runtime (), isDaemon );
275
- }
276
- } catch (Throwable throwable ) {
277
- throw new InternalError (throwable );
187
+ long [] javaVMInfo = isolate != null ? new long [4 ] : null ;
188
+ boolean res = runtime ().attachCurrentThread (isDaemon , javaVMInfo );
189
+ if (isolate != null ) {
190
+ isolate [0 ] = javaVMInfo [1 ];
278
191
}
192
+ return res ;
279
193
}
280
194
281
195
/**
@@ -289,16 +203,7 @@ public static boolean attachCurrentThread(boolean isDaemon, long[] isolate) {
289
203
* as a result of this call
290
204
*/
291
205
public static boolean detachCurrentThread (boolean release ) {
292
- try {
293
- if (detachCurrentThread .getParameterCount () == 1 ) {
294
- return (Boolean ) detachCurrentThread .invoke (runtime (), release );
295
- } else {
296
- detachCurrentThread .invoke (runtime ());
297
- return false ;
298
- }
299
- } catch (Throwable throwable ) {
300
- throw new InternalError (throwable );
301
- }
206
+ return runtime ().detachCurrentThread (release );
302
207
}
303
208
304
209
/**
@@ -309,84 +214,7 @@ public static boolean detachCurrentThread(boolean release) {
309
214
* @exception UnsupportedOperationException if unsupported
310
215
*/
311
216
public static long getFailedSpeculationsAddress (HotSpotSpeculationLog log ) {
312
- if (getFailedSpeculationsAddress != null ) {
313
- try {
314
- return (long ) getFailedSpeculationsAddress .invoke (log );
315
- } catch (Throwable e ) {
316
- throw new InternalError (e );
317
- }
318
- }
319
- throw new UnsupportedOperationException ();
320
- }
321
-
322
- /**
323
- * Convenience function for wrapping varargs into an array for use in calls to
324
- * {@link #method(Class, String, Class[][])}.
325
- */
326
- private static Class <?>[] sig (Class <?>... types ) {
327
- return types ;
328
- }
329
-
330
- /**
331
- * Gets the method in {@code declaringClass} with the unique name {@code name}.
332
- *
333
- * @param sigs the signatures the method may have
334
- */
335
- private static Method method (Class <?> declaringClass , String name , Class <?>[]... sigs ) {
336
- if (sigs .length == 1 || sigs .length == 0 ) {
337
- try {
338
- Class <?>[] sig = sigs .length == 1 ? sigs [0 ] : new Class <?>[0 ];
339
- return declaringClass .getDeclaredMethod (name , sig );
340
- } catch (NoSuchMethodException | SecurityException e ) {
341
- throw (NoSuchMethodError ) new NoSuchMethodError (name ).initCause (e );
342
- }
343
- }
344
- Method match = null ;
345
- for (Method m : declaringClass .getDeclaredMethods ()) {
346
- if (m .getName ().equals (name )) {
347
- if (match != null ) {
348
- throw new InternalError (String .format ("Expected single method named %s, found %s and %s" ,
349
- name , match , m ));
350
- }
351
- match = m ;
352
- }
353
- }
354
- if (match == null ) {
355
- throw new NoSuchMethodError ("Cannot find method " + name + " in " + declaringClass .getName ());
356
- }
357
- Class <?>[] parameterTypes = match .getParameterTypes ();
358
- for (Class <?>[] sig : sigs ) {
359
- if (Arrays .equals (parameterTypes , sig )) {
360
- return match ;
361
- }
362
- }
363
- throw new NoSuchMethodError (String .format ("Unexpected signature for %s: %s" , name , Arrays .toString (parameterTypes )));
217
+ return log .getFailedSpeculationsAddress ();
364
218
}
365
219
366
- /**
367
- * Gets the method in {@code declaringClass} with the unique name {@code name} or {@code null}
368
- * if not found.
369
- *
370
- * @param sigs the signatures the method may have
371
- */
372
- private static Method methodOrNull (Class <?> declaringClass , String name , Class <?>[]... sigs ) {
373
- try {
374
- return method (declaringClass , name , sigs );
375
- } catch (NoSuchMethodError e ) {
376
- return null ;
377
- }
378
- }
379
-
380
- /**
381
- * Gets the method in {@code declaringClass} with the unique name {@code name} or {@code null}
382
- * if {@code guard == null}.
383
- *
384
- * @param sigs the signatures the method may have
385
- */
386
- private static Method methodIf (Object guard , Class <?> declaringClass , String name , Class <?>[]... sigs ) {
387
- if (guard == null ) {
388
- return null ;
389
- }
390
- return method (declaringClass , name , sigs );
391
- }
392
220
}
0 commit comments