Skip to content

Commit a02d877

Browse files
authored
Merge pull request #62 from luneo7/GR-58531-backport
[Backport] [GR-58531] Eagerly initialize caches in method handle implementation
2 parents 3b370bb + cc16108 commit a02d877

File tree

1 file changed

+39
-84
lines changed

1 file changed

+39
-84
lines changed

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

Lines changed: 39 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,12 @@
2525
package com.oracle.svm.hosted.methodhandles;
2626

2727
import java.lang.invoke.CallSite;
28-
import java.lang.invoke.MethodHandle;
2928
import java.lang.invoke.MethodType;
30-
import java.lang.reflect.Array;
29+
import java.lang.invoke.VarHandle;
3130
import java.lang.reflect.Field;
3231
import java.lang.reflect.InvocationTargetException;
3332
import java.lang.reflect.Member;
3433
import java.lang.reflect.Method;
35-
import java.util.Iterator;
3634
import java.util.Optional;
3735
import java.util.concurrent.ConcurrentHashMap;
3836
import java.util.function.Supplier;
@@ -109,24 +107,24 @@ public class MethodHandleFeature implements InternalFeature {
109107

110108
@Override
111109
public void duringSetup(DuringSetupAccess access) {
112-
Class<?> memberNameClass = access.findClassByName("java.lang.invoke.MemberName");
110+
Class<?> memberNameClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.MemberName");
113111
memberNameIsMethod = ReflectionUtil.lookupMethod(memberNameClass, "isMethod");
114112
memberNameIsConstructor = ReflectionUtil.lookupMethod(memberNameClass, "isConstructor");
115113
memberNameIsField = ReflectionUtil.lookupMethod(memberNameClass, "isField");
116114
memberNameGetMethodType = ReflectionUtil.lookupMethod(memberNameClass, "getMethodType");
117115

118-
Class<?> lambdaFormClass = access.findClassByName("java.lang.invoke.LambdaForm");
116+
Class<?> lambdaFormClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.LambdaForm");
119117
lambdaFormLFIdentity = ReflectionUtil.lookupField(lambdaFormClass, "LF_identity");
120118
lambdaFormLFZero = ReflectionUtil.lookupField(lambdaFormClass, "LF_zero");
121119
lambdaFormNFIdentity = ReflectionUtil.lookupField(lambdaFormClass, "NF_identity");
122120
lambdaFormNFZero = ReflectionUtil.lookupField(lambdaFormClass, "NF_zero");
123121

124-
Class<?> arrayAccessorClass = access.findClassByName("java.lang.invoke.MethodHandleImpl$ArrayAccessor");
122+
Class<?> arrayAccessorClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.MethodHandleImpl$ArrayAccessor");
125123
typedAccessors = ReflectionUtil.lookupField(arrayAccessorClass, "TYPED_ACCESSORS");
126124

127125
if (JDK21u4OrLater.jdk21u4OrLater) {
128126
try {
129-
Class<?> referencedKeySetClass = access.findClassByName("jdk.internal.util.ReferencedKeySet");
127+
Class<?> referencedKeySetClass = ReflectionUtil.lookupClass(false, "jdk.internal.util.ReferencedKeySet");
130128
Method create = ReflectionUtil.lookupMethod(referencedKeySetClass, "create", boolean.class, boolean.class, Supplier.class);
131129
// The following call must match the static initializer of MethodType#internTable.
132130
runtimeMethodTypeInternTable = create.invoke(null,
@@ -136,7 +134,7 @@ public void duringSetup(DuringSetupAccess access) {
136134
throw VMError.shouldNotReachHere(e);
137135
}
138136
} else {
139-
Class<?> concurrentWeakInternSetClass = access.findClassByName("java.lang.invoke.MethodType$ConcurrentWeakInternSet");
137+
Class<?> concurrentWeakInternSetClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.MethodType$ConcurrentWeakInternSet");
140138
runtimeMethodTypeInternTable = ReflectionUtil.newInstance(concurrentWeakInternSetClass);
141139
referencedKeySetAdd = ReflectionUtil.lookupMethod(concurrentWeakInternSetClass, "add", Object.class);
142140
}
@@ -154,43 +152,20 @@ public void duringSetup(DuringSetupAccess access) {
154152

155153
@Override
156154
public void beforeAnalysis(BeforeAnalysisAccess access) {
157-
/* java.lang.invoke functions called through reflection */
158-
Class<?> mhImplClazz = access.findClassByName("java.lang.invoke.MethodHandleImpl");
159-
160-
access.registerReachabilityHandler(MethodHandleFeature::registerMHImplFunctionsForReflection,
161-
ReflectionUtil.lookupMethod(mhImplClazz, "getFunction", byte.class));
162-
163-
access.registerReachabilityHandler(MethodHandleFeature::registerMHImplConstantHandlesForReflection,
164-
ReflectionUtil.lookupMethod(mhImplClazz, "makeConstantHandle", int.class));
165-
166-
access.registerReachabilityHandler(MethodHandleFeature::registerMHImplCountingWrapperFunctionsForReflection,
167-
access.findClassByName("java.lang.invoke.MethodHandleImpl$CountingWrapper"));
168-
169-
access.registerReachabilityHandler(MethodHandleFeature::registerInvokersFunctionsForReflection,
170-
ReflectionUtil.lookupMethod(access.findClassByName("java.lang.invoke.Invokers"), "getFunction", byte.class));
171-
155+
eagerlyInitializeMHImplFunctions();
156+
eagerlyInitializeMHImplConstantHandles();
157+
eagerlyInitializeInvokersFunctions();
172158
eagerlyInitializeValueConversionsCaches();
159+
eagerlyInitializeCallSite();
173160

174-
access.registerClassInitializerReachabilityHandler(MethodHandleFeature::registerDelegatingMHFunctionsForReflection,
175-
access.findClassByName("java.lang.invoke.DelegatingMethodHandle"));
176-
177-
access.registerReachabilityHandler(MethodHandleFeature::registerCallSiteGetTargetForReflection,
178-
ReflectionUtil.lookupMethod(CallSite.class, "getTargetHandle"));
179-
180-
access.registerReachabilityHandler(MethodHandleFeature::registerUninitializedCallSiteForReflection,
181-
ReflectionUtil.lookupMethod(CallSite.class, "uninitializedCallSiteHandle"));
182-
183-
access.registerSubtypeReachabilityHandler(MethodHandleFeature::registerVarHandleMethodsForReflection,
184-
access.findClassByName("java.lang.invoke.VarHandle"));
185-
186-
access.registerSubtypeReachabilityHandler(MethodHandleFeature::scanBoundMethodHandle,
187-
access.findClassByName("java.lang.invoke.BoundMethodHandle"));
161+
access.registerSubtypeReachabilityHandler(MethodHandleFeature::registerVarHandleMethodsForReflection, VarHandle.class);
162+
access.registerSubtypeReachabilityHandler(MethodHandleFeature::scanBoundMethodHandle, ReflectionUtil.lookupClass(false, "java.lang.invoke.BoundMethodHandle"));
188163

189164
AnalysisMetaAccess metaAccess = ((FeatureImpl.BeforeAnalysisAccessImpl) access).getMetaAccess();
190165
access.registerFieldValueTransformer(
191166
ReflectionUtil.lookupField(ReflectionUtil.lookupClass(false, "java.lang.invoke.ClassSpecializer"), "cache"),
192167
new FieldValueTransformerWithAvailability() {
193-
private static final Class<?> speciesDataClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.ClassSpecializer$SpeciesData");
168+
private static final Class<?> SPECIES_DATA_CLASS = ReflectionUtil.lookupClass(false, "java.lang.invoke.ClassSpecializer$SpeciesData");
194169

195170
/*
196171
* The value of the ClassSpecializer.cache is not seen by the analysis
@@ -219,7 +194,7 @@ public Object transform(Object receiver, Object originalValue) {
219194
}
220195

221196
private boolean isSpeciesReachable(Object speciesData) {
222-
Class<?> speciesClass = ReflectionUtil.readField(speciesDataClass, "speciesCode", speciesData);
197+
Class<?> speciesClass = ReflectionUtil.readField(SPECIES_DATA_CLASS, "speciesCode", speciesData);
223198
Optional<AnalysisType> analysisType = metaAccess.optionalLookupJavaType(speciesClass);
224199
return analysisType.isPresent() && analysisType.get().isReachable();
225200
}
@@ -229,43 +204,31 @@ private boolean isSpeciesReachable(Object speciesData) {
229204
(receiver, originalValue) -> runtimeMethodTypeInternTable);
230205
}
231206

232-
private static void registerMHImplFunctionsForReflection(DuringAnalysisAccess access) {
233-
Class<?> mhImplClazz = access.findClassByName("java.lang.invoke.MethodHandleImpl");
234-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "checkSpreadArgument", Object.class, int.class));
235-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "guardWithCatch", MethodHandle.class, Class.class, MethodHandle.class, Object[].class));
236-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "tryFinally", MethodHandle.class, MethodHandle.class, Object[].class));
237-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "loop", access.findClassByName("[Ljava.lang.invoke.LambdaForm$BasicType;"),
238-
access.findClassByName("java.lang.invoke.MethodHandleImpl$LoopClauses"), Object[].class));
239-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "throwException", Throwable.class));
240-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "profileBoolean", boolean.class, int[].class));
241-
}
242-
243-
private static void registerMHImplConstantHandlesForReflection(DuringAnalysisAccess access) {
244-
Class<?> mhImplClazz = access.findClassByName("java.lang.invoke.MethodHandleImpl");
245-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "selectAlternative", boolean.class, MethodHandle.class, MethodHandle.class));
246-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "countedLoopPredicate", int.class, int.class));
247-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "countedLoopStep", int.class, int.class));
248-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "initIterator", Iterable.class));
249-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "iteratePredicate", Iterator.class));
250-
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "iterateNext", Iterator.class));
251-
RuntimeReflection.register(ReflectionUtil.lookupMethod(Array.class, "newInstance", Class.class, int.class));
207+
private static void eagerlyInitializeMHImplFunctions() {
208+
var methodHandleImplClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.MethodHandleImpl");
209+
int count = ((Object[]) ReflectionUtil.readStaticField(methodHandleImplClass, "NFS")).length;
210+
var getFunctionMethod = ReflectionUtil.lookupMethod(methodHandleImplClass, "getFunction", byte.class);
211+
for (int i = 0; i < count; i++) {
212+
ReflectionUtil.invokeMethod(getFunctionMethod, null, (byte) i);
213+
}
252214
}
253215

254-
private static void registerMHImplCountingWrapperFunctionsForReflection(DuringAnalysisAccess access) {
255-
RuntimeReflection.register(ReflectionUtil.lookupMethod(access.findClassByName("java.lang.invoke.MethodHandleImpl$CountingWrapper"), "maybeStopCounting", Object.class));
216+
private static void eagerlyInitializeMHImplConstantHandles() {
217+
var methodHandleImplClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.MethodHandleImpl");
218+
int count = ((Object[]) ReflectionUtil.readStaticField(methodHandleImplClass, "HANDLES")).length;
219+
var getConstantHandleMethod = ReflectionUtil.lookupMethod(methodHandleImplClass, "getConstantHandle", int.class);
220+
for (int i = 0; i < count; i++) {
221+
ReflectionUtil.invokeMethod(getConstantHandleMethod, null, i);
222+
}
256223
}
257224

258-
private static void registerInvokersFunctionsForReflection(DuringAnalysisAccess access) {
259-
Class<?> invokersClazz = access.findClassByName("java.lang.invoke.Invokers");
260-
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkExactType", MethodHandle.class, MethodType.class));
261-
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkGenericType", MethodHandle.class, MethodType.class));
262-
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "getCallSiteTarget", CallSite.class));
263-
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkCustomized", MethodHandle.class));
264-
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkVarHandleGenericType", access.findClassByName("java.lang.invoke.VarHandle"),
265-
access.findClassByName("java.lang.invoke.VarHandle$AccessDescriptor")));
266-
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkVarHandleExactType", access.findClassByName("java.lang.invoke.VarHandle"),
267-
access.findClassByName("java.lang.invoke.VarHandle$AccessDescriptor")));
268-
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "directVarHandleTarget", access.findClassByName("java.lang.invoke.VarHandle")));
225+
private static void eagerlyInitializeInvokersFunctions() {
226+
var invokerksClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.Invokers");
227+
int count = ((Object[]) ReflectionUtil.readStaticField(invokerksClass, "NFS")).length;
228+
var getFunctionMethod = ReflectionUtil.lookupMethod(invokerksClass, "getFunction", byte.class);
229+
for (int i = 0; i < count; i++) {
230+
ReflectionUtil.invokeMethod(getFunctionMethod, null, (byte) i);
231+
}
269232
}
270233

271234
/**
@@ -294,21 +257,13 @@ private static void eagerlyInitializeValueConversionsCaches() {
294257
}
295258
}
296259

297-
private static void registerDelegatingMHFunctionsForReflection(DuringAnalysisAccess access) {
298-
Class<?> delegatingMHClazz = access.findClassByName("java.lang.invoke.DelegatingMethodHandle");
299-
RuntimeReflection.register(ReflectionUtil.lookupMethod(delegatingMHClazz, "getTarget"));
300-
}
301-
302-
private static void registerCallSiteGetTargetForReflection(DuringAnalysisAccess access) {
303-
RuntimeReflection.register(ReflectionUtil.lookupMethod(CallSite.class, "getTarget"));
304-
}
305-
306-
private static void registerUninitializedCallSiteForReflection(DuringAnalysisAccess access) {
307-
RuntimeReflection.register(ReflectionUtil.lookupMethod(CallSite.class, "uninitializedCallSite", Object[].class));
260+
private static void eagerlyInitializeCallSite() {
261+
ReflectionUtil.invokeMethod(ReflectionUtil.lookupMethod(CallSite.class, "getTargetHandle"), null);
262+
ReflectionUtil.invokeMethod(ReflectionUtil.lookupMethod(CallSite.class, "uninitializedCallSiteHandle"), null);
308263
}
309264

310265
private static void registerVarHandleMethodsForReflection(FeatureAccess access, Class<?> subtype) {
311-
if (subtype.getPackage().getName().equals("java.lang.invoke") && subtype != access.findClassByName("java.lang.invoke.VarHandle")) {
266+
if (subtype.getPackage().getName().equals("java.lang.invoke") && subtype != VarHandle.class) {
312267
RuntimeReflection.register(subtype.getDeclaredMethods());
313268
}
314269
}

0 commit comments

Comments
 (0)