Skip to content

Commit b339df9

Browse files
author
Christian Wimmer
committed
[GR-55593] Eagerly initialize caches in ValueConversions.
PullRequest: graal/18680
2 parents 5823a62 + fb9b6c0 commit b339df9

File tree

2 files changed

+20
-44
lines changed

2 files changed

+20
-44
lines changed

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import java.lang.reflect.Member;
3434
import java.lang.reflect.Method;
3535
import java.util.Iterator;
36-
import java.util.Locale;
3736
import java.util.Optional;
3837
import java.util.concurrent.ConcurrentHashMap;
3938
import java.util.function.Supplier;
@@ -163,17 +162,7 @@ public void beforeAnalysis(BeforeAnalysisAccess a) {
163162
access.registerReachabilityHandler(MethodHandleFeature::registerInvokersFunctionsForReflection,
164163
ReflectionUtil.lookupMethod(access.findClassByName("java.lang.invoke.Invokers"), "getFunction", byte.class));
165164

166-
access.registerReachabilityHandler(MethodHandleFeature::registerValueConversionBoxFunctionsForReflection,
167-
ReflectionUtil.lookupMethod(ValueConversions.class, "boxExact", Wrapper.class));
168-
169-
access.registerReachabilityHandler(MethodHandleFeature::registerValueConversionUnboxFunctionsForReflection,
170-
ReflectionUtil.lookupMethod(ValueConversions.class, "unbox", Wrapper.class, int.class));
171-
172-
access.registerReachabilityHandler(MethodHandleFeature::registerValueConversionConvertFunctionsForReflection,
173-
ReflectionUtil.lookupMethod(ValueConversions.class, "convertPrimitive", Wrapper.class, Wrapper.class));
174-
175-
access.registerReachabilityHandler(MethodHandleFeature::registerValueConversionIgnoreForReflection,
176-
ReflectionUtil.lookupMethod(ValueConversions.class, "ignore"));
165+
eagerlyInitializeValueConversionsCaches();
177166

178167
access.registerClassInitializerReachabilityHandler(MethodHandleFeature::registerDelegatingMHFunctionsForReflection,
179168
access.findClassByName("java.lang.invoke.DelegatingMethodHandle"));
@@ -328,44 +317,32 @@ private static void registerInvokersFunctionsForReflection(DuringAnalysisAccess
328317
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "directVarHandleTarget", access.findClassByName("java.lang.invoke.VarHandle")));
329318
}
330319

331-
private static void registerValueConversionBoxFunctionsForReflection(DuringAnalysisAccess access) {
332-
for (Wrapper type : Wrapper.values()) {
333-
if (type.primitiveType().isPrimitive() && type != Wrapper.VOID) {
334-
RuntimeReflection.register(ReflectionUtil.lookupMethod(ValueConversions.class, "box" + type.wrapperSimpleName(), type.primitiveType()));
335-
}
336-
}
337-
}
320+
/**
321+
* Eagerly initialize method handle caches in {@link ValueConversions} so that 1) we avoid
322+
* reflection registration for conversion methods, and 2) the static analysis already sees a
323+
* consistent snapshot that does not change after analysis when the JDK needs more conversions.
324+
*/
325+
private static void eagerlyInitializeValueConversionsCaches() {
326+
ValueConversions.ignore();
338327

339-
private static void registerValueConversionUnboxFunctionsForReflection(DuringAnalysisAccess access) {
340-
for (Wrapper type : Wrapper.values()) {
341-
if (type.primitiveType().isPrimitive() && type != Wrapper.VOID) {
342-
RuntimeReflection.register(ReflectionUtil.lookupMethod(ValueConversions.class, "unbox" + type.wrapperSimpleName(), type.wrapperType()));
343-
RuntimeReflection.register(ReflectionUtil.lookupMethod(ValueConversions.class, "unbox" + type.wrapperSimpleName(), Object.class, boolean.class));
328+
for (Wrapper src : Wrapper.values()) {
329+
if (src != Wrapper.VOID && src.primitiveType().isPrimitive()) {
330+
ValueConversions.boxExact(src);
331+
332+
ValueConversions.unboxExact(src, false);
333+
ValueConversions.unboxExact(src, true);
334+
ValueConversions.unboxWiden(src);
335+
ValueConversions.unboxCast(src);
344336
}
345-
}
346-
}
347337

348-
private static void registerValueConversionConvertFunctionsForReflection(DuringAnalysisAccess access) {
349-
for (Wrapper src : Wrapper.values()) {
350-
for (Wrapper dest : Wrapper.values()) {
351-
if (src != dest && src.primitiveType().isPrimitive() && src != Wrapper.VOID && dest.primitiveType().isPrimitive() && dest != Wrapper.VOID) {
352-
RuntimeReflection.register(ReflectionUtil.lookupMethod(ValueConversions.class, valueConverterName(src, dest), src.primitiveType()));
338+
for (Wrapper dst : Wrapper.values()) {
339+
if (src != Wrapper.VOID && dst != Wrapper.VOID && (src == dst || (src.primitiveType().isPrimitive() && dst.primitiveType().isPrimitive()))) {
340+
ValueConversions.convertPrimitive(src, dst);
353341
}
354342
}
355343
}
356344
}
357345

358-
private static String valueConverterName(Wrapper src, Wrapper dest) {
359-
String srcType = src.primitiveSimpleName();
360-
String destType = dest.primitiveSimpleName();
361-
/* Capitalize first letter of destination type */
362-
return srcType + "To" + destType.substring(0, 1).toUpperCase(Locale.ROOT) + destType.substring(1);
363-
}
364-
365-
private static void registerValueConversionIgnoreForReflection(DuringAnalysisAccess access) {
366-
RuntimeReflection.register(ReflectionUtil.lookupMethod(ValueConversions.class, "ignore", Object.class));
367-
}
368-
369346
private static void registerDelegatingMHFunctionsForReflection(DuringAnalysisAccess access) {
370347
Class<?> delegatingMHClazz = access.findClassByName("java.lang.invoke.DelegatingMethodHandle");
371348
RuntimeReflection.register(ReflectionUtil.lookupMethod(delegatingMHClazz, "getTarget"));

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@
8686
import com.oracle.svm.core.hub.ClassForNameSupport;
8787
import com.oracle.svm.core.hub.DynamicHub;
8888
import com.oracle.svm.core.reflect.SubstrateAccessor;
89-
import com.oracle.svm.core.util.UserError;
9089
import com.oracle.svm.core.util.VMError;
9190
import com.oracle.svm.hosted.ConditionalConfigurationRegistry;
9291
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
@@ -178,7 +177,7 @@ public void beforeAnalysis(BeforeAnalysisAccessImpl beforeAnalysisAccess) {
178177

179178
private void runConditionalInAnalysisTask(ConfigurationCondition condition, Consumer<ConfigurationCondition> task) {
180179
if (sealed) {
181-
throw UserError.abort("Too late to add classes, methods, and fields for reflective access. Registration must happen in a Feature before the analysis has finished.");
180+
throw new UnsupportedFeatureException("Too late to add classes, methods, and fields for reflective access. Registration must happen in a Feature before the analysis has finished.");
182181
}
183182

184183
if (universe != null) {

0 commit comments

Comments
 (0)