Skip to content

Commit a84ef58

Browse files
committed
Refactor Libgraal and avoid reflection to improve startup.
1 parent 2e1ae42 commit a84ef58

File tree

1 file changed

+26
-198
lines changed
  • truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/hotspot/libgraal

1 file changed

+26
-198
lines changed

truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/hotspot/libgraal/LibGraal.java

Lines changed: 26 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@
4242

4343
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
4444

45-
import java.lang.reflect.InvocationTargetException;
46-
import java.lang.reflect.Method;
47-
import java.util.Arrays;
48-
45+
import org.graalvm.nativeimage.ImageInfo;
4946
import org.graalvm.nativeimage.IsolateThread;
5047
import org.graalvm.nativeimage.c.function.CEntryPoint;
5148
import org.graalvm.word.PointerBase;
@@ -58,62 +55,44 @@
5855
import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
5956
import jdk.vm.ci.hotspot.HotSpotSpeculationLog;
6057
import jdk.vm.ci.services.Services;
61-
import org.graalvm.nativeimage.ImageInfo;
6258

6359
/**
6460
* Access to libgraal, a shared library containing an AOT compiled version of Graal produced by
6561
* GraalVM Native Image. The libgraal library is only available if the HotSpot
6662
* {@code UseJVMCINativeLibrary} flag is true and the current runtime includes the relevant JVMCI
6763
* API additions for accessing libgraal.
6864
*
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-
*
7865
* The typical usage of this class is to {@linkplain #registerNativeMethods link} and call
7966
* {@link CEntryPoint}s in libgraal. Each call to a {@link CEntryPoint} requires an
8067
* {@link IsolateThread} argument which can be {@linkplain LibGraalScope#getIsolateThread obtained}
8168
* from a {@link LibGraalScope}.
8269
*/
8370
public class LibGraal {
8471

85-
// NOTE: The use of reflection to access JVMCI API is to support
86-
// compiling on JDKs with varying versions of JVMCI.
87-
8872
static {
8973
// Initialize JVMCI to ensure JVMCI opens its packages to Graal.
9074
ModulesSupport.exportJVMCI(LibGraal.class);
9175
Services.initializeJVMCI();
9276
}
9377

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;
10180

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+
}
10490

10591
/**
10692
* Determines if libgraal is available for use.
10793
*/
10894
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;
11796
}
11897

11998
/**
@@ -136,13 +115,7 @@ public static void registerNativeMethods(Class<?> clazz) {
136115
if (!isAvailable()) {
137116
throw new IllegalStateException();
138117
}
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);
146119
}
147120

148121
/**
@@ -160,11 +133,7 @@ public static long translate(Object obj) {
160133
if (!isAvailable()) {
161134
throw new IllegalStateException();
162135
}
163-
try {
164-
return (long) translate.invoke(runtime(), obj);
165-
} catch (Throwable throwable) {
166-
throw new InternalError(throwable);
167-
}
136+
return runtime().translate(obj);
168137
}
169138

170139
/**
@@ -181,73 +150,29 @@ public static <T> T unhand(Class<T> type, long handle) {
181150
if (!isAvailable()) {
182151
throw new IllegalStateException();
183152
}
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);
189154
}
190155

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-
213156
/**
214157
* Determines if the current thread is {@linkplain #attachCurrentThread attached} to the peer
215158
* runtime.
216159
*/
217160
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();
223162
}
224163

225164
/**
226165
* @see HotSpotJVMCIRuntime#getJObjectValue(HotSpotObjectConstant)
227166
*/
228167
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));
237169
}
238170

239171
/**
240172
* @see HotSpotJVMCIRuntime#asResolvedJavaType(long)
241173
*/
242174
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());
251176
}
252177

253178
/**
@@ -259,23 +184,12 @@ public static HotSpotResolvedJavaType asResolvedJavaType(PointerBase pointer) {
259184
* thread was already attached
260185
*/
261186
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];
278191
}
192+
return res;
279193
}
280194

281195
/**
@@ -289,16 +203,7 @@ public static boolean attachCurrentThread(boolean isDaemon, long[] isolate) {
289203
* as a result of this call
290204
*/
291205
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);
302207
}
303208

304209
/**
@@ -309,84 +214,7 @@ public static boolean detachCurrentThread(boolean release) {
309214
* @exception UnsupportedOperationException if unsupported
310215
*/
311216
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();
364218
}
365219

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-
}
392220
}

0 commit comments

Comments
 (0)