Skip to content

Commit

Permalink
Add reachability handler registration for class initializers
Browse files Browse the repository at this point in the history
  • Loading branch information
loicottet committed Jan 5, 2021
1 parent 8ba9bde commit b8b757c
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 8 deletions.
1 change: 1 addition & 0 deletions sdk/src/org.graalvm.nativeimage/snapshot.sigtest
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ meth public abstract void registerAsUnsafeAccessed(java.lang.reflect.Field)
meth public abstract void registerAsUsed(java.lang.Class<?>)
meth public abstract void registerMethodOverrideReachabilityHandler(java.util.function.BiConsumer<org.graalvm.nativeimage.hosted.Feature$DuringAnalysisAccess,java.lang.reflect.Executable>,java.lang.reflect.Executable)
meth public abstract void registerSubtypeReachabilityHandler(java.util.function.BiConsumer<org.graalvm.nativeimage.hosted.Feature$DuringAnalysisAccess,java.lang.Class<?>>,java.lang.Class<?>)
meth public abstract void registerClassInitializerReachabilityHandler(java.util.function.Consumer<org.graalvm.nativeimage.hosted.Feature$DuringAnalysisAccess>,java.lang.Class<?>)

CLSS public abstract interface static org.graalvm.nativeimage.hosted.Feature$BeforeCompilationAccess
outer org.graalvm.nativeimage.hosted.Feature
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -252,6 +252,14 @@ interface BeforeAnalysisAccess extends FeatureAccess {
* @since 19.3
*/
void registerSubtypeReachabilityHandler(BiConsumer<DuringAnalysisAccess, Class<?>> callback, Class<?> baseClass);

/**
* Registers a callback that is invoked once {@link Feature#duringAnalysis during analysis}
* when the class initializer for the given type is determined to be reachable at run time.
*
* @since 21.0
*/
void registerClassInitializerReachabilityHandler(Consumer<DuringAnalysisAccess> callback, Class<?> clazz);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,11 @@ public void registerMethodOverrideReachabilityHandler(BiConsumer<DuringAnalysisA
public void registerSubtypeReachabilityHandler(BiConsumer<DuringAnalysisAccess, Class<?>> callback, Class<?> baseClass) {
ReachabilityHandlerFeature.singleton().registerSubtypeReachabilityHandler(this, callback, baseClass);
}

@Override
public void registerClassInitializerReachabilityHandler(Consumer<DuringAnalysisAccess> callback, Class<?> clazz) {
ReachabilityHandlerFeature.singleton().registerClassInitializerReachabilityHandler(this, callback, clazz);
}
}

public static class DuringAnalysisAccessImpl extends BeforeAnalysisAccessImpl implements Feature.DuringAnalysisAccess {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,22 @@ public static ReachabilityHandlerFeature singleton() {
}

public void registerMethodOverrideReachabilityHandler(BeforeAnalysisAccessImpl a, BiConsumer<DuringAnalysisAccess, Executable> callback, Executable baseMethod) {
registerReachabilityHandler(a, callback, new Executable[]{baseMethod});
registerReachabilityHandler(a, callback, new Executable[]{baseMethod}, false);
}

public void registerSubtypeReachabilityHandler(BeforeAnalysisAccess a, BiConsumer<DuringAnalysisAccess, Class<?>> callback, Class<?> baseClass) {
registerReachabilityHandler(a, callback, new Class<?>[]{baseClass});
registerReachabilityHandler(a, callback, new Class<?>[]{baseClass}, false);
}

public void registerClassInitializerReachabilityHandler(BeforeAnalysisAccess a, Consumer<DuringAnalysisAccess> callback, Class<?> clazz) {
registerReachabilityHandler(a, callback, new Class<?>[]{clazz}, true);
}

public void registerReachabilityHandler(BeforeAnalysisAccess a, Consumer<DuringAnalysisAccess> callback, Object[] triggers) {
registerReachabilityHandler(a, (Object) callback, triggers);
registerReachabilityHandler(a, callback, triggers, false);
}

private void registerReachabilityHandler(BeforeAnalysisAccess a, Object callback, Object[] triggers) {
private void registerReachabilityHandler(BeforeAnalysisAccess a, Object callback, Object[] triggers, boolean triggerOnClassInitializer) {
if (triggeredHandlers.containsKey(callback)) {
/* Handler has already been triggered from another registration, so nothing to do. */
return;
Expand All @@ -83,7 +87,8 @@ private void registerReachabilityHandler(BeforeAnalysisAccess a, Object callback

for (Object trigger : triggers) {
if (trigger instanceof Class) {
triggerSet.add(metaAccess.lookupJavaType((Class<?>) trigger));
AnalysisType aType = metaAccess.lookupJavaType((Class<?>) trigger);
triggerSet.add(triggerOnClassInitializer ? aType.getClassInitializer() : aType);
} else if (trigger instanceof Field) {
triggerSet.add(metaAccess.lookupJavaField((Field) trigger));
} else if (trigger instanceof Executable) {
Expand Down Expand Up @@ -140,7 +145,11 @@ private static boolean isTriggered(DuringAnalysisAccessImpl access, Set<Object>
return true;
}
} else if (trigger instanceof AnalysisMethod) {
if (access.isReachable((AnalysisMethod) trigger)) {
AnalysisMethod triggerMethod = (AnalysisMethod) trigger;
if (access.isReachable(triggerMethod)) {
return true;
}
if (triggerMethod.isClassInitializer() && triggerMethod.getDeclaringClass().isInitialized()) {
return true;
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
access.registerReachabilityHandler(MethodHandleFeature::registerValueConversionIgnoreForReflection,
ReflectionUtil.lookupMethod(ValueConversions.class, "ignore"));

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

access.registerReachabilityHandler(MethodHandleFeature::registerCallSiteGetTargetForReflection,
Expand Down

0 comments on commit b8b757c

Please sign in to comment.