Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,11 @@
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.lang.reflect.Array;
import java.lang.invoke.VarHandle;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
Expand Down Expand Up @@ -108,20 +107,20 @@ public class MethodHandleFeature implements InternalFeature {

@Override
public void duringSetup(DuringSetupAccess access) {
Class<?> memberNameClass = access.findClassByName("java.lang.invoke.MemberName");
Class<?> memberNameClass = ReflectionUtil.lookupClass("java.lang.invoke.MemberName");
memberNameIsMethod = ReflectionUtil.lookupMethod(memberNameClass, "isMethod");
memberNameIsConstructor = ReflectionUtil.lookupMethod(memberNameClass, "isConstructor");
memberNameIsField = ReflectionUtil.lookupMethod(memberNameClass, "isField");
memberNameGetMethodType = ReflectionUtil.lookupMethod(memberNameClass, "getMethodType");

Class<?> arrayAccessorClass = access.findClassByName("java.lang.invoke.MethodHandleImpl$ArrayAccessor");
Class<?> arrayAccessorClass = ReflectionUtil.lookupClass("java.lang.invoke.MethodHandleImpl$ArrayAccessor");
typedAccessors = ReflectionUtil.lookupField(arrayAccessorClass, "TYPED_ACCESSORS");
Class<?> methodHandleImplClass = access.findClassByName("java.lang.invoke.MethodHandleImpl$Makers");
typedCollectors = ReflectionUtil.lookupField(methodHandleImplClass, "TYPED_COLLECTORS");
Class<?> makersClass = ReflectionUtil.lookupClass("java.lang.invoke.MethodHandleImpl$Makers");
typedCollectors = ReflectionUtil.lookupField(makersClass, "TYPED_COLLECTORS");

if (JavaVersionUtil.JAVA_SPEC >= 22) {
try {
Class<?> referencedKeySetClass = access.findClassByName("jdk.internal.util.ReferencedKeySet");
Class<?> referencedKeySetClass = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeySet");
Method create = ReflectionUtil.lookupMethod(referencedKeySetClass, "create", boolean.class, boolean.class, Supplier.class);
// The following call must match the static initializer of MethodType#internTable.
runtimeMethodTypeInternTable = create.invoke(null,
Expand All @@ -131,7 +130,7 @@ public void duringSetup(DuringSetupAccess access) {
throw VMError.shouldNotReachHere(e);
}
} else {
Class<?> concurrentWeakInternSetClass = access.findClassByName("java.lang.invoke.MethodType$ConcurrentWeakInternSet");
Class<?> concurrentWeakInternSetClass = ReflectionUtil.lookupClass("java.lang.invoke.MethodType$ConcurrentWeakInternSet");
runtimeMethodTypeInternTable = ReflectionUtil.newInstance(concurrentWeakInternSetClass);
referencedKeySetAdd = ReflectionUtil.lookupMethod(concurrentWeakInternSetClass, "add", Object.class);
}
Expand All @@ -148,45 +147,22 @@ public void duringSetup(DuringSetupAccess access) {
public void beforeAnalysis(BeforeAnalysisAccess a) {
var access = (BeforeAnalysisAccessImpl) a;

/* java.lang.invoke functions called through reflection */
Class<?> mhImplClazz = access.findClassByName("java.lang.invoke.MethodHandleImpl");

access.registerReachabilityHandler(MethodHandleFeature::registerMHImplFunctionsForReflection,
ReflectionUtil.lookupMethod(mhImplClazz, "getFunction", byte.class));

access.registerReachabilityHandler(MethodHandleFeature::registerMHImplConstantHandlesForReflection,
ReflectionUtil.lookupMethod(mhImplClazz, "makeConstantHandle", int.class));

access.registerReachabilityHandler(MethodHandleFeature::registerMHImplCountingWrapperFunctionsForReflection,
access.findClassByName("java.lang.invoke.MethodHandleImpl$CountingWrapper"));

access.registerReachabilityHandler(MethodHandleFeature::registerInvokersFunctionsForReflection,
ReflectionUtil.lookupMethod(access.findClassByName("java.lang.invoke.Invokers"), "getFunction", byte.class));

eagerlyInitializeMHImplFunctions();
eagerlyInitializeMHImplConstantHandles();
eagerlyInitializeInvokersFunctions();
eagerlyInitializeValueConversionsCaches();
eagerlyInitializeCallSite();

access.registerClassInitializerReachabilityHandler(MethodHandleFeature::registerDelegatingMHFunctionsForReflection,
access.findClassByName("java.lang.invoke.DelegatingMethodHandle"));

access.registerReachabilityHandler(MethodHandleFeature::registerCallSiteGetTargetForReflection,
ReflectionUtil.lookupMethod(CallSite.class, "getTargetHandle"));

access.registerReachabilityHandler(MethodHandleFeature::registerUninitializedCallSiteForReflection,
ReflectionUtil.lookupMethod(CallSite.class, "uninitializedCallSiteHandle"));

access.registerSubtypeReachabilityHandler(MethodHandleFeature::registerVarHandleMethodsForReflection,
access.findClassByName("java.lang.invoke.VarHandle"));

access.registerSubtypeReachabilityHandler(MethodHandleFeature::scanBoundMethodHandle,
access.findClassByName("java.lang.invoke.BoundMethodHandle"));
access.registerSubtypeReachabilityHandler(MethodHandleFeature::registerVarHandleMethodsForReflection, VarHandle.class);
access.registerSubtypeReachabilityHandler(MethodHandleFeature::scanBoundMethodHandle, ReflectionUtil.lookupClass("java.lang.invoke.BoundMethodHandle"));

AnalysisMetaAccess metaAccess = access.getMetaAccess();
ImageHeapScanner heapScanner = access.getUniverse().getHeapScanner();

access.registerFieldValueTransformer(
ReflectionUtil.lookupField(ReflectionUtil.lookupClass(false, "java.lang.invoke.ClassSpecializer"), "cache"),
ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.invoke.ClassSpecializer"), "cache"),
new FieldValueTransformerWithAvailability() {
private static final Class<?> speciesDataClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.ClassSpecializer$SpeciesData");
private static final Class<?> SPECIES_DATA_CLASS = ReflectionUtil.lookupClass("java.lang.invoke.ClassSpecializer$SpeciesData");

/*
* The value of the ClassSpecializer.cache is not seen by the analysis
Expand Down Expand Up @@ -215,16 +191,16 @@ public Object transform(Object receiver, Object originalValue) {
}

private boolean isSpeciesTypeInstantiated(Object speciesData) {
Class<?> speciesClass = ReflectionUtil.readField(speciesDataClass, "speciesCode", speciesData);
Class<?> speciesClass = ReflectionUtil.readField(SPECIES_DATA_CLASS, "speciesCode", speciesData);
Optional<AnalysisType> analysisType = metaAccess.optionalLookupJavaType(speciesClass);
return analysisType.isPresent() && analysisType.get().isInstantiated();
}
});
access.registerFieldValueTransformer(
ReflectionUtil.lookupField(ReflectionUtil.lookupClass(false, "java.lang.invoke.DirectMethodHandle"), "ACCESSOR_FORMS"),
ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.invoke.DirectMethodHandle"), "ACCESSOR_FORMS"),
NewEmptyArrayFieldValueTransformer.INSTANCE);
access.registerFieldValueTransformer(
ReflectionUtil.lookupField(ReflectionUtil.lookupClass(false, "java.lang.invoke.MethodType"), "internTable"),
ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.invoke.MethodType"), "internTable"),
(receiver, originalValue) -> runtimeMethodTypeInternTable);

/*
Expand All @@ -236,7 +212,7 @@ private boolean isSpeciesTypeInstantiated(Object speciesData) {
* be made reachable after analysis.
*/
access.registerFieldValueTransformer(
ReflectionUtil.lookupField(ReflectionUtil.lookupClass(false, "java.lang.invoke.ClassSpecializer$SpeciesData"), "transformHelpers"),
ReflectionUtil.lookupField(ReflectionUtil.lookupClass("java.lang.invoke.ClassSpecializer$SpeciesData"), "transformHelpers"),
new FieldValueTransformerWithAvailability() {
@Override
public boolean isAvailable() {
Expand Down Expand Up @@ -267,8 +243,8 @@ public Object transform(Object receiver, Object originalValue) {
* method Feature.beforeCompilation()), thereby registering new elements into the image heap
* (elements that were not tracked in the analysis).
*/
Class<?> lambdaFormClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.LambdaForm");
Class<?> basicTypeClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.LambdaForm$BasicType");
Class<?> lambdaFormClass = ReflectionUtil.lookupClass("java.lang.invoke.LambdaForm");
Class<?> basicTypeClass = ReflectionUtil.lookupClass("java.lang.invoke.LambdaForm$BasicType");
Method createFormsForMethod = ReflectionUtil.lookupMethod(lambdaFormClass, "createFormsFor", basicTypeClass);
try {
for (Object type : (Object[]) ReflectionUtil.readStaticField(basicTypeClass, "ALL_TYPES")) {
Expand All @@ -279,43 +255,31 @@ public Object transform(Object receiver, Object originalValue) {
}
}

private static void registerMHImplFunctionsForReflection(DuringAnalysisAccess access) {
Class<?> mhImplClazz = access.findClassByName("java.lang.invoke.MethodHandleImpl");
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "checkSpreadArgument", Object.class, int.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "guardWithCatch", MethodHandle.class, Class.class, MethodHandle.class, Object[].class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "tryFinally", MethodHandle.class, MethodHandle.class, Object[].class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "loop", access.findClassByName("[Ljava.lang.invoke.LambdaForm$BasicType;"),
access.findClassByName("java.lang.invoke.MethodHandleImpl$LoopClauses"), Object[].class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "throwException", Throwable.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "profileBoolean", boolean.class, int[].class));
}

private static void registerMHImplConstantHandlesForReflection(DuringAnalysisAccess access) {
Class<?> mhImplClazz = access.findClassByName("java.lang.invoke.MethodHandleImpl");
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "selectAlternative", boolean.class, MethodHandle.class, MethodHandle.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "countedLoopPredicate", int.class, int.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "countedLoopStep", int.class, int.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "initIterator", Iterable.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "iteratePredicate", Iterator.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "iterateNext", Iterator.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(Array.class, "newInstance", Class.class, int.class));
private static void eagerlyInitializeMHImplFunctions() {
var methodHandleImplClass = ReflectionUtil.lookupClass("java.lang.invoke.MethodHandleImpl");
int count = ((Object[]) ReflectionUtil.readStaticField(methodHandleImplClass, "NFS")).length;
var getFunctionMethod = ReflectionUtil.lookupMethod(methodHandleImplClass, "getFunction", byte.class);
for (int i = 0; i < count; i++) {
ReflectionUtil.invokeMethod(getFunctionMethod, null, (byte) i);
}
}

private static void registerMHImplCountingWrapperFunctionsForReflection(DuringAnalysisAccess access) {
RuntimeReflection.register(ReflectionUtil.lookupMethod(access.findClassByName("java.lang.invoke.MethodHandleImpl$CountingWrapper"), "maybeStopCounting", Object.class));
private static void eagerlyInitializeMHImplConstantHandles() {
var methodHandleImplClass = ReflectionUtil.lookupClass("java.lang.invoke.MethodHandleImpl");
int count = ((Object[]) ReflectionUtil.readStaticField(methodHandleImplClass, "HANDLES")).length;
var getConstantHandleMethod = ReflectionUtil.lookupMethod(methodHandleImplClass, "getConstantHandle", int.class);
for (int i = 0; i < count; i++) {
ReflectionUtil.invokeMethod(getConstantHandleMethod, null, i);
}
}

private static void registerInvokersFunctionsForReflection(DuringAnalysisAccess access) {
Class<?> invokersClazz = access.findClassByName("java.lang.invoke.Invokers");
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkExactType", MethodHandle.class, MethodType.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkGenericType", MethodHandle.class, MethodType.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "getCallSiteTarget", CallSite.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkCustomized", MethodHandle.class));
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkVarHandleGenericType", access.findClassByName("java.lang.invoke.VarHandle"),
access.findClassByName("java.lang.invoke.VarHandle$AccessDescriptor")));
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "checkVarHandleExactType", access.findClassByName("java.lang.invoke.VarHandle"),
access.findClassByName("java.lang.invoke.VarHandle$AccessDescriptor")));
RuntimeReflection.register(ReflectionUtil.lookupMethod(invokersClazz, "directVarHandleTarget", access.findClassByName("java.lang.invoke.VarHandle")));
private static void eagerlyInitializeInvokersFunctions() {
var invokerksClass = ReflectionUtil.lookupClass("java.lang.invoke.Invokers");
int count = ((Object[]) ReflectionUtil.readStaticField(invokerksClass, "NFS")).length;
var getFunctionMethod = ReflectionUtil.lookupMethod(invokerksClass, "getFunction", byte.class);
for (int i = 0; i < count; i++) {
ReflectionUtil.invokeMethod(getFunctionMethod, null, (byte) i);
}
}

/**
Expand Down Expand Up @@ -344,21 +308,13 @@ private static void eagerlyInitializeValueConversionsCaches() {
}
}

private static void registerDelegatingMHFunctionsForReflection(DuringAnalysisAccess access) {
Class<?> delegatingMHClazz = access.findClassByName("java.lang.invoke.DelegatingMethodHandle");
RuntimeReflection.register(ReflectionUtil.lookupMethod(delegatingMHClazz, "getTarget"));
}

private static void registerCallSiteGetTargetForReflection(DuringAnalysisAccess access) {
RuntimeReflection.register(ReflectionUtil.lookupMethod(CallSite.class, "getTarget"));
}

private static void registerUninitializedCallSiteForReflection(DuringAnalysisAccess access) {
RuntimeReflection.register(ReflectionUtil.lookupMethod(CallSite.class, "uninitializedCallSite", Object[].class));
private static void eagerlyInitializeCallSite() {
ReflectionUtil.invokeMethod(ReflectionUtil.lookupMethod(CallSite.class, "getTargetHandle"), null);
ReflectionUtil.invokeMethod(ReflectionUtil.lookupMethod(CallSite.class, "uninitializedCallSiteHandle"), null);
}

private static void registerVarHandleMethodsForReflection(FeatureAccess access, Class<?> subtype) {
if (subtype.getPackage().getName().equals("java.lang.invoke") && subtype != access.findClassByName("java.lang.invoke.VarHandle")) {
if (subtype.getPackage().getName().equals("java.lang.invoke") && subtype != VarHandle.class) {
RuntimeReflection.register(subtype.getDeclaredMethods());
}
}
Expand Down