Skip to content

Commit 9bdffba

Browse files
committed
Parse pointsto options for standalone pointsto
The standalone pointsto need to take the input options. The options and parsing should follow the same way as native image's hosted options. So we extract the commom part of SubstrateOptionsParser to a new project where both pointsto and svm can share.
1 parent 4d20f4a commit 9bdffba

File tree

21 files changed

+1066
-542
lines changed

21 files changed

+1066
-542
lines changed

substratevm/mx.substratevm/suite.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,19 @@
137137
"checkstyle": "com.oracle.svm.core",
138138
"workingSets": "SVM",
139139
},
140+
"org.graalvm.nativeimage.base": {
141+
"subDir": "src",
142+
"sourceDirs": ["src"],
143+
"dependencies": [
144+
"com.oracle.svm.util"
145+
],
146+
"javaCompliance": "8+",
147+
"annotationProcessors": [
148+
"compiler:GRAAL_PROCESSOR",
149+
],
150+
"checkstyle": "com.oracle.svm.core",
151+
"workingSets": "SVM",
152+
},
140153
"com.oracle.svm.util.jdk11": {
141154
"subDir": "src",
142155
"sourceDirs": ["src"],
@@ -164,7 +177,7 @@
164177
"headers",
165178
],
166179
"dependencies": [
167-
"com.oracle.svm.util",
180+
"org.graalvm.nativeimage.base",
168181
],
169182
"javaCompliance": "8+",
170183
"checkstyleVersion" : "8.36.1",
@@ -361,7 +374,7 @@
361374
"subDir": "src",
362375
"sourceDirs": ["src"],
363376
"dependencies": [
364-
"com.oracle.svm.util",
377+
"org.graalvm.nativeimage.base",
365378
],
366379
"checkstyle": "com.oracle.graal.pointsto",
367380
"javaCompliance": "8+",
@@ -1083,7 +1096,7 @@
10831096
"com.oracle.svm.core.graal.thread to jdk.internal.vm.compiler",
10841097
"com.oracle.svm.core.classinitialization to jdk.internal.vm.compiler",
10851098
"com.oracle.svm.truffle.api to org.graalvm.truffle",
1086-
"* to org.graalvm.nativeimage.driver,org.graalvm.nativeimage.configure,org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.llvm,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.agent.diagnostics,com.oracle.svm.svm_enterprise",
1099+
"* to org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.configure,org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.llvm,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.agent.diagnostics,com.oracle.svm.svm_enterprise",
10871100
],
10881101
"opens" : [
10891102
"com.oracle.svm.core.nodes to jdk.internal.vm.compiler",
@@ -1195,7 +1208,7 @@
11951208
"static hamcrest",
11961209
],
11971210
"exports" : [
1198-
"* to org.graalvm.nativeimage.builder",
1211+
"* to org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.builder",
11991212
],
12001213
},
12011214
},
@@ -1382,6 +1395,7 @@
13821395
"name" : "org.graalvm.nativeimage.pointsto",
13831396
"exports" : [
13841397
"com.oracle.svm.util",
1398+
"org.graalvm.nativeimage.base.option",
13851399
"com.oracle.graal.pointsto",
13861400
"com.oracle.graal.pointsto.api",
13871401
"com.oracle.graal.pointsto.reports",

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/PointstoOptions.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,10 @@ public String value() {
219219
return value;
220220
}
221221
}
222+
223+
@Option(help = "Specify the analysis entry point class. It should be a main Class.")//
224+
public static final OptionKey<String> AnalysisEntryClass = new OptionKey<>(null);
225+
226+
@Option(help = "Configurations used in native image building time can also be used in analysis. Specify the configurations' directory.")//
227+
public static final OptionKey<String> AnalysisConfigDir = new OptionKey<>(null);
222228
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/AnalysisError.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ private static String message(AnalysisMethod context, AnalysisField field, Analy
118118
}
119119
}
120120

121+
public static class InterruptAnalysis extends AnalysisError {
122+
private static final long serialVersionUID = 7126612141948542452L;
123+
124+
InterruptAnalysis(String msg) {
125+
super(msg);
126+
}
127+
}
128+
121129
public static TypeNotFoundError typeNotFound(ResolvedJavaType type) {
122130
throw new TypeNotFoundError(type);
123131
}
@@ -159,4 +167,8 @@ public static void guarantee(boolean condition, String format, Object... args) {
159167
// Checkstyle: resume
160168
}
161169
}
170+
171+
public static RuntimeException interruptAnalysis(String msg) {
172+
throw new InterruptAnalysis(msg);
173+
}
162174
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2021, 2021, Alibaba Group Holding Limited. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.graal.pointsto.util;
28+
29+
import java.io.File;
30+
import java.io.IOException;
31+
import java.nio.file.FileVisitResult;
32+
import java.nio.file.Files;
33+
import java.nio.file.Path;
34+
import java.nio.file.SimpleFileVisitor;
35+
import java.nio.file.attribute.BasicFileAttributes;
36+
import java.util.Enumeration;
37+
import java.util.function.Consumer;
38+
import java.util.jar.JarEntry;
39+
import java.util.jar.JarFile;
40+
41+
public class ClassPathSearcher {
42+
43+
public static void search(Consumer<String> matchClass) {
44+
String classpath = System.getProperty("java.class.path");
45+
String[] classPathEntries = classpath.split(File.pathSeparator);
46+
for (String entry : classPathEntries) {
47+
File file = new File(entry);
48+
if (file.isFile() && file.getName().endsWith(".jar")) {
49+
scanJar(file, matchClass);
50+
} else if (file.isDirectory()) {
51+
scanDir(file, matchClass);
52+
} else if (file.isFile()) {
53+
matchClass.accept(file.toString());
54+
}
55+
}
56+
}
57+
58+
private static void scanDir(File p, Consumer<String> matchClass) {
59+
try {
60+
Files.walkFileTree(p.toPath(), new SimpleFileVisitor<Path>() {
61+
@Override
62+
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
63+
Path relativePath = p.toPath().relativize(file);
64+
matchClass.accept(relativePath.toString());
65+
return FileVisitResult.CONTINUE;
66+
}
67+
68+
});
69+
} catch (IOException e) {
70+
e.printStackTrace();
71+
}
72+
}
73+
74+
private static void scanJar(File file, Consumer<String> matchClass) {
75+
try {
76+
JarFile jf = new JarFile(file);
77+
Enumeration<JarEntry> entries = jf.entries();
78+
while (entries.hasMoreElements()) {
79+
matchClass.accept(entries.nextElement().getName());
80+
}
81+
} catch (IOException e) {
82+
e.printStackTrace();
83+
}
84+
}
85+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2021, 2021, Alibaba Group Holding Limited. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.graal.pointsto.util;
28+
29+
import org.graalvm.nativeimage.base.option.CommonOptionParser;
30+
import org.graalvm.nativeimage.base.option.CommonOptionParser.BooleanOptionFormat;
31+
import org.graalvm.nativeimage.base.option.CommonOptionParser.OptionParseResult;
32+
import org.graalvm.nativeimage.base.option.OptionParsingException;
33+
import org.graalvm.nativeimage.base.option.UnsupportedOptionClassException;
34+
import org.graalvm.collections.EconomicMap;
35+
import org.graalvm.compiler.options.OptionDescriptor;
36+
import org.graalvm.compiler.options.OptionDescriptors;
37+
import org.graalvm.compiler.options.OptionKey;
38+
import org.graalvm.compiler.options.OptionValues;
39+
40+
import java.io.PrintStream;
41+
import java.util.ArrayList;
42+
import java.util.Arrays;
43+
import java.util.HashSet;
44+
import java.util.List;
45+
import java.util.Set;
46+
import java.util.function.Predicate;
47+
48+
import static org.graalvm.nativeimage.base.option.CommonOptionParser.BooleanOptionFormat.PLUS_MINUS;
49+
50+
public final class PointsToOptionParser {
51+
52+
private static PointsToOptionParser instance = new PointsToOptionParser();
53+
54+
private OptionValues optionValues = null;
55+
private EconomicMap<OptionKey<?>, Object> analysisValues = OptionValues.newOptionMap();
56+
private EconomicMap<String, OptionDescriptor> allAnalysisOptions = EconomicMap.create();
57+
58+
public static PointsToOptionParser getInstance() {
59+
return instance;
60+
}
61+
62+
@SuppressWarnings("unchecked")
63+
private PointsToOptionParser() {
64+
List<Class<? extends OptionDescriptors>> optionDescriptorsList = new ArrayList<>();
65+
try {
66+
ClassLoader appClassLoader = ClassPathSearcher.class.getClassLoader();
67+
// Search the classpath to find out the OptionDescriptors classes
68+
ClassPathSearcher.search(entryName -> {
69+
if (entryName.endsWith(".class")) {
70+
// replace the "/" to "." and remove the ".class" postfix to get the qualified
71+
// class name
72+
String className = entryName.replace('/', '.').substring(0, entryName.length() - 6);
73+
try {
74+
Class<?> c = Class.forName(className, false, appClassLoader);
75+
if (OptionDescriptors.class.isAssignableFrom(c)) {
76+
optionDescriptorsList.add((Class<? extends OptionDescriptors>) c);
77+
}
78+
} catch (NoClassDefFoundError | ClassNotFoundException | IllegalAccessError e) {
79+
// ClassName may be not correct, ignore
80+
}
81+
}
82+
});
83+
CommonOptionParser.collectOptions(optionDescriptorsList, descriptor -> {
84+
String name = descriptor.getName();
85+
if (descriptor.getOptionKey() instanceof OptionKey) {
86+
OptionDescriptor existing = allAnalysisOptions.put(name, descriptor);
87+
if (existing != null) {
88+
AnalysisError.shouldNotReachHere("Option name \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + descriptor.getLocation());
89+
}
90+
}
91+
});
92+
} catch (OptionParsingException e) {
93+
AnalysisError.shouldNotReachHere(e);
94+
}
95+
}
96+
97+
public void setOptionValue(OptionKey<?> optionKey, Object value) {
98+
if (optionValues == null) {
99+
parse(new String[0]);
100+
}
101+
optionKey.update((EconomicMap<OptionKey<?>, Object>) optionValues.getMap(), value);
102+
}
103+
104+
public OptionValues parse(String[] args) {
105+
List<String> remainingArgs = new ArrayList<>();
106+
Set<String> errors = new HashSet<>();
107+
for (String arg : args) {
108+
boolean isAnalysisOption = false;
109+
isAnalysisOption |= parseOption(CommonOptionParser.HOSTED_OPTION_PREFIX, allAnalysisOptions, analysisValues, PLUS_MINUS, errors, arg, System.out);
110+
if (!isAnalysisOption) {
111+
remainingArgs.add(arg);
112+
}
113+
}
114+
optionValues = new OptionValues(analysisValues);
115+
if (!remainingArgs.isEmpty()) {
116+
AnalysisError.interruptAnalysis(String.format("Unknown options: %s", Arrays.toString(remainingArgs.toArray(new String[0]))));
117+
}
118+
if (!errors.isEmpty()) {
119+
StringBuilder errMsg = new StringBuilder("Option format error:\n");
120+
for (String err : errors) {
121+
errMsg.append(err).append("\n");
122+
}
123+
AnalysisError.interruptAnalysis(errMsg.toString());
124+
}
125+
return optionValues;
126+
}
127+
128+
private static boolean parseOption(String optionPrefix, EconomicMap<String, OptionDescriptor> options, EconomicMap<OptionKey<?>, Object> valuesMap,
129+
BooleanOptionFormat booleanOptionFormat, Set<String> errors, String arg, PrintStream out) {
130+
if (!arg.startsWith(optionPrefix)) {
131+
return false;
132+
}
133+
try {
134+
Predicate<OptionKey<?>> optionKeyPredicate = optionKey -> {
135+
Class<?> clazz = optionKey.getClass();
136+
// All classes from com.oracle.graal.pointsto.api.PointstoOptions are taken as non-hosted options.
137+
if (clazz.getName().startsWith("com.oracle.graal.pointsto.api.PointstoOptions")) {
138+
return false;
139+
}
140+
if (!clazz.equals(OptionKey.class) && OptionKey.class.isAssignableFrom(clazz)) {
141+
return true;
142+
} else {
143+
return false;
144+
}
145+
};
146+
OptionParseResult optionParseResult = CommonOptionParser.parseOption(options, optionKeyPredicate, arg.substring(optionPrefix.length()), valuesMap,
147+
optionPrefix, booleanOptionFormat);
148+
if (optionParseResult.printFlags() || optionParseResult.printFlagsWithExtraHelp()) {
149+
CommonOptionParser.printFlags(d -> optionParseResult.matchesFlags(d, () -> true), options, optionPrefix, out, optionParseResult.printFlagsWithExtraHelp());
150+
System.out.println("Abort analysis due to print flags are requested");
151+
System.exit(1);
152+
}
153+
if (!optionParseResult.isValid()) {
154+
errors.add(optionParseResult.getError());
155+
}
156+
} catch (UnsupportedOptionClassException e) {
157+
AnalysisError.shouldNotReachHere(e);
158+
}
159+
return true;
160+
}
161+
}

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,6 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean o
124124
private static ValueUpdateHandler optimizeValueUpdateHandler;
125125
private static ValueUpdateHandler debugInfoValueUpdateHandler = SubstrateOptions::defaultDebugInfoValueUpdateHandler;
126126

127-
@Option(help = "Show available options based on comma-separated option-types (allowed categories: User, Expert, Debug).")//
128-
public static final OptionKey<String> PrintFlags = new OptionKey<>(null);
129-
130-
@Option(help = "Print extra help, if available, based on comma-separated option names. Pass * to show all options that contain extra help.")//
131-
public static final OptionKey<String> PrintFlagsWithExtraHelp = new OptionKey<>(null);
132-
133127
@Option(help = "Control native-image code optimizations: 0 - no optimizations, 1 - basic optimizations, 2 - aggressive optimizations.", type = OptionType.User)//
134128
public static final HostedOptionKey<Integer> Optimize = new HostedOptionKey<Integer>(2) {
135129
@Override

0 commit comments

Comments
 (0)