Skip to content

Commit 8c608d6

Browse files
committed
[GR-70176] [GR-66234] Refactor standalone points-to analysis feature for project Terminus
PullRequest: graal/22252
2 parents 6102f76 + 53b20dd commit 8c608d6

File tree

11 files changed

+270
-186
lines changed

11 files changed

+270
-186
lines changed

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2745,6 +2745,8 @@ def apply(self, config):
27452745
vmArgs, mainClass, mainClassArgs = config
27462746

27472747
vmArgs.extend(['--add-exports=jdk.graal.compiler/jdk.graal.compiler.options=ALL-UNNAMED'])
2748+
# need to access jdk.graal.compiler.phases.util.Providers
2749+
vmArgs.extend(['--add-exports=jdk.graal.compiler/jdk.graal.compiler.phases.util=ALL-UNNAMED'])
27482750

27492751
# JVMCI is dynamically exported to Graal when JVMCI is initialized. This is too late
27502752
# for the junit harness which uses reflection to find @Test methods. In addition, the

substratevm/src/com.oracle.graal.pointsto.standalone.test/src/com/oracle/graal/pointsto/standalone/test/PointstoAnalyzerTester.java

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2022, 2022, Alibaba Group Holding Limited. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -56,12 +56,10 @@
5656
import com.oracle.graal.pointsto.meta.AnalysisType;
5757
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
5858
import com.oracle.graal.pointsto.standalone.PointsToAnalyzer;
59-
import com.oracle.graal.pointsto.util.AnalysisError;
6059

6160
import jdk.vm.ci.meta.MetaAccessProvider;
6261
import jdk.vm.ci.meta.ResolvedJavaField;
6362
import jdk.vm.ci.meta.ResolvedJavaMethod;
64-
import jdk.vm.ci.meta.ResolvedJavaType;
6563

6664
public class PointstoAnalyzerTester {
6765
private Set<Executable> expectedReachableMethods = new HashSet<>();
@@ -153,7 +151,12 @@ public void runAnalysisAndAssert() {
153151
* analysis is supposed to fail.
154152
*/
155153
public void runAnalysisAndAssert(boolean expectPass) {
156-
PointsToAnalyzer pointstoAnalyzer = PointsToAnalyzer.createAnalyzer(arguments);
154+
/*
155+
* Use the same class loader that has loaded the test classes to prevent from loading the
156+
* same classes twice and having to convert between them.
157+
*/
158+
PointsToAnalyzer.HostClassLoaderAccess classLoaderAccess = new PointsToAnalyzer.HostClassLoaderAccess(testClass.getClassLoader());
159+
PointsToAnalyzer pointstoAnalyzer = PointsToAnalyzer.createAnalyzer(arguments, classLoaderAccess);
157160
UnsupportedFeatureException unsupportedFeatureException = null;
158161
try {
159162
try {
@@ -166,7 +169,6 @@ public void runAnalysisAndAssert(boolean expectPass) {
166169
} catch (UnsupportedFeatureException e) {
167170
unsupportedFeatureException = e;
168171
}
169-
ClassLoader analysisClassLoader = pointstoAnalyzer.getClassLoader();
170172
if (!expectPass) {
171173
return;
172174
}
@@ -175,39 +177,19 @@ public void runAnalysisAndAssert(boolean expectPass) {
175177
assertNotNull(universe);
176178

177179
assertReachable("Method", expectedReachableMethods, expectedUnreachableMethods, reflectionMethod -> {
178-
try {
179-
Executable actualMethod = reflectionMethod;
180-
Class<?> declaringClass = reflectionMethod.getDeclaringClass();
181-
if (!analysisClassLoader.equals(declaringClass.getClassLoader())) {
182-
Class<?> c = Class.forName(declaringClass.getName(), false, analysisClassLoader);
183-
actualMethod = c.getDeclaredMethod(reflectionMethod.getName(), reflectionMethod.getParameterTypes());
184-
}
185-
ResolvedJavaMethod m = universe.getOriginalMetaAccess().lookupJavaMethod(actualMethod);
186-
return universe.getMethod(m);
187-
} catch (ReflectiveOperationException e) {
188-
throw AnalysisError.shouldNotReachHere(e);
189-
}
180+
ResolvedJavaMethod m = universe.getOriginalMetaAccess().lookupJavaMethod(reflectionMethod);
181+
return universe.getMethod(m);
190182
},
191183
reflectionMethod -> reflectionMethod.getDeclaringClass().getName() + "." + reflectionMethod.getName());
192184
assertReachable("<clinit>", expectedReachableClinits, expectedUnreachableClinits, clazz -> {
193-
AnalysisType t = classToAnalysisType(analysisClassLoader, universe, originalMetaAccess, clazz);
185+
AnalysisType t = classToAnalysisType(universe, originalMetaAccess, clazz);
194186
return t.getClassInitializer();
195187
}, clazz -> clazz.getName() + ".<clinit>");
196-
assertReachable("Type", expectedReachableTypes, expectedUnreachableTypes, clazz -> classToAnalysisType(analysisClassLoader, universe, originalMetaAccess, clazz),
188+
assertReachable("Type", expectedReachableTypes, expectedUnreachableTypes, clazz -> classToAnalysisType(universe, originalMetaAccess, clazz),
197189
clazz -> clazz.getName());
198190
assertReachable("Field", expectedReachableFields, expectedUnreachableFields, reflectionField -> {
199-
try {
200-
Field actualField = reflectionField;
201-
Class<?> declaringClass = actualField.getDeclaringClass();
202-
if (!analysisClassLoader.equals(declaringClass.getClassLoader())) {
203-
Class<?> c = Class.forName(declaringClass.getName(), false, analysisClassLoader);
204-
actualField = c.getDeclaredField(reflectionField.getName());
205-
}
206-
ResolvedJavaField resolvedJavaField = originalMetaAccess.lookupJavaField(actualField);
207-
return universe.getField(resolvedJavaField);
208-
} catch (ReflectiveOperationException e) {
209-
throw AnalysisError.shouldNotReachHere(e);
210-
}
191+
ResolvedJavaField resolvedJavaField = originalMetaAccess.lookupJavaField(reflectionField);
192+
return universe.getField(resolvedJavaField);
211193
},
212194
reflectionField -> reflectionField.getDeclaringClass().getName() + "." + reflectionField.getName());
213195

@@ -221,17 +203,8 @@ public void runAnalysisAndAssert(boolean expectPass) {
221203
}
222204
}
223205

224-
private static AnalysisType classToAnalysisType(ClassLoader analysisClassLoader, AnalysisUniverse universe, MetaAccessProvider originalMetaAccess, Class<?> clazz) {
225-
try {
226-
Class<?> actualClass = clazz;
227-
if (!analysisClassLoader.equals(clazz.getClassLoader())) {
228-
actualClass = Class.forName(clazz.getName(), false, analysisClassLoader);
229-
}
230-
ResolvedJavaType resolvedJavaType = originalMetaAccess.lookupJavaType(actualClass);
231-
return universe.optionalLookup(resolvedJavaType);
232-
} catch (ReflectiveOperationException e) {
233-
throw AnalysisError.shouldNotReachHere(e);
234-
}
206+
private static AnalysisType classToAnalysisType(AnalysisUniverse universe, MetaAccessProvider originalMetaAccess, Class<?> clazz) {
207+
return universe.optionalLookup(originalMetaAccess.lookupJavaType(clazz));
235208
}
236209

237210
public Object runAnalysisForFeatureResult(Class<? extends Feature> feature) {

substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/MethodConfigReader.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2022, 2022, Alibaba Group Holding Limited. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -47,7 +47,6 @@
4747
import jdk.graal.compiler.debug.DebugContext;
4848
import jdk.graal.compiler.debug.DebugOptions;
4949
import jdk.graal.compiler.debug.MethodFilter;
50-
import jdk.vm.ci.meta.MetaAccessProvider;
5150
import jdk.vm.ci.meta.ResolvedJavaMethod;
5251
import jdk.vm.ci.meta.ResolvedJavaType;
5352

@@ -68,10 +67,10 @@ public class MethodConfigReader {
6867
*
6968
* @param file the configuration file to read.
7069
* @param bigbang
71-
* @param classLoader analysis classloader
70+
* @param classLoaderAccess for loading classes
7271
* @param actionForEachMethod the action to take for each resolved method.
7372
*/
74-
public static void readMethodFromFile(String file, BigBang bigbang, ClassLoader classLoader, Consumer<AnalysisMethod> actionForEachMethod) {
73+
public static void readMethodFromFile(String file, BigBang bigbang, PointsToAnalyzer.ClassLoaderAccess classLoaderAccess, Consumer<AnalysisMethod> actionForEachMethod) {
7574
List<String> methodNameList = new ArrayList<>();
7675
Path entryFilePath = Paths.get(file);
7776
File entryFile = entryFilePath.toFile();
@@ -85,7 +84,7 @@ public static void readMethodFromFile(String file, BigBang bigbang, ClassLoader
8584
AnalysisError.shouldNotReachHere(e);
8685
}
8786
int totalSize = methodNameList.size();
88-
int num = forMethodList(bigbang.getDebug(), methodNameList, bigbang, classLoader, actionForEachMethod);
87+
int num = forMethodList(bigbang.getDebug(), methodNameList, bigbang, classLoaderAccess, actionForEachMethod);
8988
StringBuilder sb = new StringBuilder();
9089
sb.append("==Reading analysis entry points status==").append(System.lineSeparator());
9190
sb.append(num).append(" out of ").append(totalSize).append(" methods are read from ").append(file).append(System.lineSeparator());
@@ -97,13 +96,13 @@ public static void readMethodFromFile(String file, BigBang bigbang, ClassLoader
9796
}
9897

9998
@SuppressWarnings("try")
100-
public static int forMethodList(DebugContext debug, List<String> methods, BigBang bigbang, ClassLoader classLoader, Consumer<AnalysisMethod> actionForEachMethod) {
99+
public static int forMethodList(DebugContext debug, List<String> methods, BigBang bigbang, PointsToAnalyzer.ClassLoaderAccess classLoaderAccess, Consumer<AnalysisMethod> actionForEachMethod) {
101100
AtomicInteger validMethodsNum = new AtomicInteger(0);
102101
try (DebugContext.Scope s = debug.scope(READ_ENTRY_POINTS)) {
103102
methods.stream().forEach(method -> {
104103
if (!method.isBlank()) {
105104
try {
106-
workWithMethod(method, bigbang, classLoader, actionForEachMethod);
105+
workWithMethod(method, bigbang, classLoaderAccess, actionForEachMethod);
107106
validMethodsNum.incrementAndGet();
108107
} catch (Throwable t) {
109108
// Checkstyle: Allow raw info or warning printing - begin
@@ -116,7 +115,8 @@ public static int forMethodList(DebugContext debug, List<String> methods, BigBan
116115
return validMethodsNum.get();
117116
}
118117

119-
private static void workWithMethod(String method, BigBang bigbang, ClassLoader classLoader, Consumer<AnalysisMethod> actionForEachMethod) throws ClassNotFoundException {
118+
private static void workWithMethod(String method, BigBang bigbang, PointsToAnalyzer.ClassLoaderAccess classLoaderAccess, Consumer<AnalysisMethod> actionForEachMethod)
119+
throws ClassNotFoundException {
120120
int pos = method.indexOf('(');
121121
int dotAfterClassNamePos;
122122
if (pos == -1) {
@@ -128,12 +128,13 @@ private static void workWithMethod(String method, BigBang bigbang, ClassLoader c
128128
AnalysisError.shouldNotReachHere("The the given method's name " + method + " doesn't contain the declaring class name.");
129129
}
130130
String className = method.substring(0, dotAfterClassNamePos);
131-
Class<?> c = Class.forName(className, false, classLoader);
131+
ResolvedJavaType t = classLoaderAccess.forName(className);
132+
if (t == null) {
133+
throw new ClassNotFoundException(className);
134+
}
132135
// MethodFilter.parse requires ResolvedJavaMethod as input
133-
MetaAccessProvider originalMetaAccess = bigbang.getUniverse().getOriginalMetaAccess();
134-
List<ResolvedJavaMethod> methodCandidates = Arrays.stream(c.getDeclaredMethods()).map(m -> originalMetaAccess.lookupJavaMethod(m)).filter(m -> !m.isNative()).collect(Collectors.toList());
135-
methodCandidates.addAll(Arrays.stream(c.getDeclaredConstructors()).map(m -> originalMetaAccess.lookupJavaMethod(m)).collect(Collectors.toList()));
136-
ResolvedJavaType t = originalMetaAccess.lookupJavaType(c);
136+
List<ResolvedJavaMethod> methodCandidates = Arrays.stream(t.getDeclaredMethods()).filter(m -> !m.isNative()).collect(Collectors.toList());
137+
methodCandidates.addAll(Arrays.stream(t.getDeclaredConstructors()).toList());
137138
if (t.getClassInitializer() != null) {
138139
methodCandidates.add(t.getClassInitializer());
139140
}

0 commit comments

Comments
 (0)