Skip to content

Commit 4819c7f

Browse files
committed
Add dynamic access detection phase
1 parent d5a5114 commit 4819c7f

File tree

11 files changed

+747
-6
lines changed

11 files changed

+747
-6
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ public final void applyResults(AnalysisMethod method) {
252252
return;
253253
}
254254

255+
preStrengthenGraphs(graph, method);
256+
255257
graph.resetDebug(debug);
256258
if (beforeCounters != null) {
257259
beforeCounters.collect(graph);
@@ -279,6 +281,8 @@ public final void applyResults(AnalysisMethod method) {
279281
}
280282
}
281283

284+
protected abstract void preStrengthenGraphs(StructuredGraph graph, AnalysisMethod method);
285+
282286
protected abstract void postStrengthenGraphs(StructuredGraph graph, AnalysisMethod method);
283287

284288
protected abstract void persistStrengthenGraph(AnalysisMethod method);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/NeverInlineTrivial.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
3131
import java.lang.annotation.Retention;
3232
import java.lang.annotation.RetentionPolicy;
3333
import java.lang.annotation.Target;
34+
import java.util.function.BooleanSupplier;
3435

3536
/**
3637
* Every thus annotated method is never trivially inlined by the compiler. Specific inlining to
@@ -45,4 +46,24 @@
4546
* Documents the reason why the annotated code must not be inlined.
4647
*/
4748
String value();
49+
50+
/**
51+
* Avoid inlining only if any of the provided predicates are true (default: class that is never inlined).
52+
*
53+
* The classes must implement {@link BooleanSupplier}.
54+
*/
55+
Class<?>[] onlyWith() default NeverInlined.class;
56+
57+
/**
58+
* The default value for the {@link NeverInlineTrivial#onlyWith()} attribute.*
59+
*/
60+
class NeverInlined implements BooleanSupplier {
61+
NeverInlined() {
62+
}
63+
64+
@Override
65+
public boolean getAsBoolean() {
66+
return true;
67+
}
68+
}
4869
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.nio.file.Paths;
3838
import java.util.List;
3939
import java.util.UUID;
40+
import java.util.function.BooleanSupplier;
4041
import java.util.function.Predicate;
4142

4243
import org.graalvm.collections.EconomicMap;
@@ -1413,4 +1414,12 @@ public static class TruffleStableOptions {
14131414
2. All @CEntryPoint definitions in classes loaded by the custom loader are processed.
14141415
3. All @TargetClass substitutions in classes loaded by the custom loader are processed.""")//
14151416
public static final HostedOptionKey<String> LibGraalClassLoader = new HostedOptionKey<>("");
1417+
1418+
@Option(help = "Serialize all method calls requiring metadata for dynamic access in the reached parts of the project, limited to the provided comma-separated list of class path entries and module or package names.")//
1419+
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> TrackDynamicAccess = new HostedOptionKey<>(
1420+
AccumulatingLocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
1421+
1422+
@Option(help = "Output all method calls requiring metadata for dynamic access found by -H:TrackDynamicAccess to the console.")
1423+
public static final HostedOptionKey<Boolean> ReportDynamicAccessToConsole = new HostedOptionKey<>(
1424+
false);
14161425
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.oracle.svm.core;
2+
3+
import java.util.function.BooleanSupplier;
4+
5+
public class TrackDynamicAccess implements BooleanSupplier {
6+
7+
@Override
8+
public boolean getAsBoolean() {
9+
return SubstrateOptions.TrackDynamicAccess.hasBeenSet();
10+
}
11+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@
8080
import java.util.Optional;
8181
import java.util.StringJoiner;
8282

83+
import com.oracle.svm.core.SubstrateOptions;
84+
import com.oracle.svm.core.TrackDynamicAccess;
8385
import org.graalvm.nativeimage.AnnotationAccess;
8486
import org.graalvm.nativeimage.ImageSingletons;
8587
import org.graalvm.nativeimage.Platform;
@@ -89,6 +91,7 @@
8991
import com.oracle.svm.core.BuildPhaseProvider.AfterHostedUniverse;
9092
import com.oracle.svm.core.BuildPhaseProvider.CompileQueueFinished;
9193
import com.oracle.svm.core.NeverInline;
94+
import com.oracle.svm.core.NeverInlineTrivial;
9295
import com.oracle.svm.core.RuntimeAssertionsSupport;
9396
import com.oracle.svm.core.SubstrateUtil;
9497
import com.oracle.svm.core.Uninterruptible;
@@ -1566,24 +1569,28 @@ private static Constructor<?>[] copyConstructors(Constructor<?>[] original) {
15661569
private native Constructor<?> getEnclosingConstructor();
15671570

15681571
@Substitute
1572+
@NeverInlineTrivial(value = "Used in dynamic access call usage analysis: DynamicAccessDetectionPhase", onlyWith = TrackDynamicAccess.class)
15691573
@CallerSensitive
15701574
private static Class<?> forName(String className) throws Throwable {
15711575
return forName(className, Reflection.getCallerClass());
15721576
}
15731577

15741578
@Substitute
1579+
@NeverInlineTrivial(value = "Used in dynamic access call usage analysis: DynamicAccessDetectionPhase", onlyWith = TrackDynamicAccess.class)
15751580
@CallerSensitiveAdapter
15761581
private static Class<?> forName(String className, Class<?> caller) throws Throwable {
15771582
return forName(className, true, caller == null ? ClassLoader.getSystemClassLoader() : caller.getClassLoader(), caller);
15781583
}
15791584

15801585
@Substitute
1586+
@NeverInlineTrivial(value = "Used in dynamic access call usage analysis: DynamicAccessDetectionPhase", onlyWith = TrackDynamicAccess.class)
15811587
@CallerSensitive
15821588
private static Class<?> forName(Module module, String className) throws Throwable {
15831589
return forName(module, className, Reflection.getCallerClass());
15841590
}
15851591

15861592
@Substitute
1593+
@NeverInlineTrivial(value = "Used in dynamic access call usage analysis: DynamicAccessDetectionPhase", onlyWith = TrackDynamicAccess.class)
15871594
@CallerSensitiveAdapter
15881595
@TargetElement(onlyWith = JDK21OrEarlier.class)
15891596
private static Class<?> forName(@SuppressWarnings("unused") Module module, String className, Class<?> caller) throws Throwable {
@@ -1599,12 +1606,14 @@ private static Class<?> forName(@SuppressWarnings("unused") Module module, Strin
15991606
}
16001607

16011608
@Substitute
1609+
@NeverInlineTrivial(value = "Used in dynamic access call usage analysis: DynamicAccessDetectionPhase", onlyWith = TrackDynamicAccess.class)
16021610
@CallerSensitive
16031611
private static Class<?> forName(String name, boolean initialize, ClassLoader loader) throws Throwable {
16041612
return forName(name, initialize, loader, Reflection.getCallerClass());
16051613
}
16061614

16071615
@Substitute
1616+
@NeverInlineTrivial(value = "Used in dynamic access call usage analysis: DynamicAccessDetectionPhase", onlyWith = TrackDynamicAccess.class)
16081617
@CallerSensitiveAdapter
16091618
@TargetElement(onlyWith = JDK21OrEarlier.class)
16101619
private static Class<?> forName(String name, boolean initialize, ClassLoader loader, @SuppressWarnings("unused") Class<?> caller) throws Throwable {

0 commit comments

Comments
 (0)