Skip to content

Commit 40cfa00

Browse files
committed
[GR-55487] GuestGraal: Implement options as per GR-50104.
PullRequest: graal/18303
2 parents c8dcd81 + 9998202 commit 40cfa00

File tree

16 files changed

+422
-331
lines changed

16 files changed

+422
-331
lines changed

compiler/ci/ci_common/gate.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"--kill-with-sigquit",
4444
"gate",
4545
"--strict-mode",
46-
"--extra-vm-argument=-Djdk.graal.DumpOnError=true -Djdk.graal.PrintGraphFile=true -Djdk.graal.PrintBackendCFG=true -DGCUtils.saveHeapDumpTo=." +
46+
"--extra-vm-argument=-Djdk.graal.DumpOnError=true -Djdk.graal.PrintGraph=File -Djdk.graal.PrintBackendCFG=true -DGCUtils.saveHeapDumpTo=." +
4747
(if extra_vm_args == "" then "" else " " + extra_vm_args)
4848
] + (if extra_unittest_args != "" then [
4949
"--extra-unittest-argument=" + extra_unittest_args,

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CheckGraalInvariants.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -206,18 +206,9 @@ protected void updateVerifiers(List<VerifyPhase<CoreProviders>> verifiers) {
206206
* Determines if {@code option} should be checked to ensure it has at least one usage.
207207
*/
208208
public boolean shouldCheckUsage(OptionDescriptor option) {
209-
Class<?> declaringClass = option.getDeclaringClass();
210-
if (declaringClass.getName().equals("jdk.graal.compiler.truffle.TruffleCompilerOptions")) {
211-
/*
212-
* These options are deprecated and will be removed in GraalVM 20.2.0. The
213-
* TruffleIntrinsifyFrameAccess option has no replacement and is unused.
214-
*/
215-
return false;
216-
}
217209
if (option.getOptionKey().getClass().isAnonymousClass()) {
218210
/*
219-
* Probably a derived option such as
220-
* jdk.graal.compiler.debug.DebugOptions.PrintGraphFile.
211+
* A derived option.
221212
*/
222213
return false;
223214
}

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/CompilationWrapperTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ public static void testHelper(List<Probe> initialOutputProbes,
249249
vmArgs.remove("-ea");
250250
vmArgs.add("-Djdk.graal.DumpPath=" + dumpPath);
251251
// Force output to a file even if there's a running IGV instance available.
252-
vmArgs.add("-Djdk.graal.PrintGraphFile=true");
252+
vmArgs.add("-Djdk.graal.PrintGraph=File");
253253
vmArgs.addAll(extraVmArgs);
254254

255255
Subprocess proc = SubprocessUtil.java(vmArgs, mainClassAndArgs);

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugOptions.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
import java.text.SimpleDateFormat;
3434
import java.util.Date;
3535

36-
import org.graalvm.collections.EconomicMap;
37-
3836
import jdk.graal.compiler.options.EnumMultiOptionKey;
3937
import jdk.graal.compiler.options.EnumOptionKey;
4038
import jdk.graal.compiler.options.Option;
@@ -177,23 +175,6 @@ public enum OptimizationLogTarget {
177175
"Change detection is based on adding and deleting nodes or changing inputs.", type = OptionType.Debug)
178176
public static final OptionKey<Boolean> PrintUnmodifiedGraphs = new OptionKey<>(true);
179177

180-
@Option(help = "Setting to true sets PrintGraph=file, setting to false sets PrintGraph=network", type = OptionType.Debug)
181-
public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<>(true) {
182-
@Override
183-
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
184-
PrintGraphTarget v = PrintGraph.getValueOrDefault(values);
185-
if (newValue.booleanValue()) {
186-
if (v != PrintGraphTarget.File) {
187-
PrintGraph.update(values, PrintGraphTarget.File);
188-
}
189-
} else {
190-
if (v != PrintGraphTarget.Network) {
191-
PrintGraph.update(values, PrintGraphTarget.Network);
192-
}
193-
}
194-
}
195-
};
196-
197178
@Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug)
198179
public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1");
199180
@Option(help = "Port part of the address to which graphs are dumped in binary format.", type = OptionType.Debug)

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalOptionValues.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import static jdk.vm.ci.common.InitTimer.timer;
2828

2929
import java.io.PrintStream;
30+
import java.util.HashMap;
3031
import java.util.Map;
3132
import java.util.Set;
3233

@@ -111,7 +112,8 @@ public static EconomicMap<OptionKey<?>, Object> parseOptions() {
111112
Map<String, String> savedProps = GraalServices.getSavedProperties();
112113

113114
EconomicMap<String, String> compilerOptionSettings = EconomicMap.create();
114-
EconomicMap<String, String> vmOptionSettings = EconomicMap.create();
115+
// Need to use Map as it's a shared type between guest and host in GuestGraal.
116+
Map<String, String> vmOptionSettings = new HashMap<>();
115117

116118
for (Map.Entry<String, String> e : savedProps.entrySet()) {
117119
String name = e.getKey();
@@ -149,8 +151,10 @@ public static EconomicMap<OptionKey<?>, Object> parseOptions() {
149151
}
150152
}
151153

154+
if (!vmOptionSettings.isEmpty()) {
155+
notifyLibgraalOptions(vmOptionSettings);
156+
}
152157
OptionsParser.parseOptions(compilerOptionSettings, compilerOptionValues, descriptors);
153-
notifyLibgraalOptions(compilerOptionValues, vmOptionSettings);
154158
return compilerOptionValues;
155159
}
156160
}
@@ -167,13 +171,10 @@ private static String stripPrefix(String name, String prefix) {
167171
* Substituted by
168172
* {@code com.oracle.svm.graal.hotspot.libgraal.Target_jdk_graal_compiler_hotspot_HotSpotGraalOptionValues}.
169173
*
170-
* @param compilerOptionValues parsed compiler option values
171-
* @param vmOptionSettings unparsed libgraal option values
174+
* @param settings unparsed libgraal option values
172175
*/
173-
private static void notifyLibgraalOptions(EconomicMap<OptionKey<?>, Object> compilerOptionValues, EconomicMap<String, String> vmOptionSettings) {
174-
if (!vmOptionSettings.isEmpty()) {
175-
System.err.printf("WARNING: Ignoring the following libgraal VM option(s) while executing jargraal: %s%n", String.join(", ", vmOptionSettings.getKeys()));
176-
}
176+
private static void notifyLibgraalOptions(Map<String, String> settings) {
177+
System.err.printf("WARNING: Ignoring the following libgraal VM option(s) while executing jargraal: %s%n", String.join(", ", settings.keySet()));
177178
}
178179

179180
private static OptionValues initializeOptions() {

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/BuildTime.java

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
import jdk.graal.compiler.hotspot.meta.DefaultHotSpotLoweringProvider;
5555
import jdk.graal.compiler.hotspot.meta.HotSpotInvocationPluginProvider;
5656
import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;
57-
import jdk.graal.compiler.options.OptionDescriptors;
57+
import jdk.graal.compiler.options.OptionDescriptor;
58+
import jdk.graal.compiler.options.OptionKey;
5859
import jdk.graal.compiler.options.OptionsParser;
5960
import jdk.graal.compiler.serviceprovider.GraalServices;
6061
import jdk.graal.compiler.truffle.PartialEvaluatorConfiguration;
@@ -78,19 +79,39 @@ public class BuildTime {
7879
private static final ClassLoader LOADER = BuildTime.class.getClassLoader();
7980

8081
/**
81-
* This method gets called from {@code GuestGraalFeature#afterRegistration()} to ensure static
82-
* field {@code OptionsParser#cachedOptionDescriptors} gets initialized only with
83-
* OptionDescriptors service providers from the classes in the GuestGraalClassLoader.
82+
* Creates and {@linkplain OptionsParser#setLibgraalOptionDescriptors registers} the map used
83+
* for looking up libgraal compiler options.
8484
*/
8585
@SuppressWarnings("unused")
86-
public static void configureOptionsParserCachedOptionDescriptors() {
86+
public static Object initLibgraalOptionDescriptors() {
87+
EconomicMap<String, OptionDescriptor> descriptors = EconomicMap.create();
88+
OptionsParser.setLibgraalOptionDescriptors(descriptors);
89+
return descriptors;
90+
}
91+
92+
/**
93+
* Processes the entries in {@code optionObjects} and adds their
94+
* {@linkplain OptionDescriptor#isServiceLoaded() non-service loaded} descriptors to
95+
* {@code descriptorsObject}.
96+
*
97+
* @param optionObjects a list of {@link OptionKey} objects
98+
* @param descriptorsObject the value returned by {@link #initLibgraalOptionDescriptors()}
99+
* @return the {@link OptionDescriptor} objects added to {@code descriptorsObject}
100+
*/
101+
@SuppressWarnings({"unused", "unchecked"})
102+
public static Iterable<?> finalizeLibgraalOptionDescriptors(List<Object> optionObjects, Object descriptorsObject) {
87103
GraalError.guarantee(VALID_LOADER_NAME.equals(LOADER.getName()),
88104
"Only call this method from classloader " + VALID_LOADER_NAME);
89-
90-
Iterable<OptionDescriptors> optionsLoaderIterable = OptionsParser.getOptionsLoader(LOADER);
91-
List<OptionDescriptors> cachedOptionDescriptors = new ArrayList<>();
92-
optionsLoaderIterable.forEach(cachedOptionDescriptors::add);
93-
OptionsParser.setCachedOptionDescriptors(List.copyOf(cachedOptionDescriptors));
105+
EconomicMap<String, OptionDescriptor> descriptors = (EconomicMap<String, OptionDescriptor>) descriptorsObject;
106+
for (Object optionObject : optionObjects) {
107+
OptionKey<?> option = (OptionKey<?>) optionObject;
108+
OptionDescriptor descriptor = option.getDescriptor();
109+
if (descriptor.isServiceLoaded()) {
110+
String name = option.getName();
111+
descriptors.put(name, descriptor);
112+
}
113+
}
114+
return descriptors.getValues();
94115
}
95116

96117
@SuppressWarnings("unused")
@@ -193,6 +214,10 @@ public static Map<String, MethodHandle> getRuntimeHandles() {
193214
String.class, BiConsumer.class, Supplier.class)),
194215
"getJNIEnv", MHL.findStatic(RunTime.class, "getJNIEnv",
195216
methodType(long.class)),
217+
"attachCurrentThread", MHL.findStatic(RunTime.class, "attachCurrentThread",
218+
methodType(boolean.class, boolean.class, long[].class)),
219+
"detachCurrentThread", MHL.findStatic(RunTime.class, "detachCurrentThread",
220+
methodType(boolean.class, boolean.class)),
196221
"getSavedProperty", MHL.findStatic(GraalServices.class, "getSavedProperty",
197222
methodType(String.class, String.class)),
198223
"ttyPrintf", MHL.findStatic(TTY.class, "printf",

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/guestgraal/RunTime.java

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@
5454
import sun.misc.Unsafe;
5555

5656
/**
57-
* This class provides implementations for {@code @CEntryPoint}s that libgraal has to provide as JVM
58-
* JIT compiler as public methods.
57+
* This class provides implementations for {@code @CEntryPoint}s that libgraal has to provide as a
58+
* JVM JIT compiler as well as handles (created by {@link BuildTime#getRuntimeHandles}) to other
59+
* utility methods needed by {@code GuestGraalFeature}.
5960
*/
6061
public class RunTime {
6162

@@ -112,7 +113,7 @@ public static long compileMethod(long methodHandle, boolean useProfilingInfo,
112113
HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler();
113114

114115
int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
115-
HotSpotResolvedJavaMethod method = HotSpotJVMCIRuntime.runtime().unhand(HotSpotResolvedJavaMethod.class, methodHandle);
116+
HotSpotResolvedJavaMethod method = runtime.unhand(HotSpotResolvedJavaMethod.class, methodHandle);
116117
HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
117118
try (CompilationContext ignored = HotSpotGraalServices.openLocalCompilationContext(request)) {
118119
CompilationTask task = new CompilationTask(runtime, compiler, request, useProfilingInfo, false, eagerResolving, installAsDefault);
@@ -140,7 +141,7 @@ public static long compileMethod(long methodHandle, boolean useProfilingInfo,
140141
metricValues.print(options);
141142
metricValues.clear();
142143
}
143-
return HotSpotJVMCIRuntime.runtime().translate(installedCode);
144+
return runtime.translate(installedCode);
144145
}
145146
}
146147

@@ -165,4 +166,35 @@ static long getJNIEnv() {
165166
long javaThreadAddr = jvmciRuntime.getCurrentJavaThread();
166167
return javaThreadAddr + offset;
167168
}
169+
170+
/**
171+
* Ensures the current thread is attached to the peer runtime.
172+
*
173+
* @param isDaemon if the thread is not yet attached, should it be attached as a daemon
174+
* @param isolate if non-null, the isolate for the current thread is returned in element 0
175+
* @return {@code true} if this call attached the current thread, {@code false} if the current
176+
* thread was already attached
177+
*/
178+
public static boolean attachCurrentThread(boolean isDaemon, long[] isolate) {
179+
long[] javaVMInfo = isolate != null ? new long[4] : null;
180+
boolean res = HotSpotJVMCIRuntime.runtime().attachCurrentThread(isDaemon, javaVMInfo);
181+
if (isolate != null) {
182+
isolate[0] = javaVMInfo[1];
183+
}
184+
return res;
185+
}
186+
187+
/**
188+
* Detaches the current thread from the peer runtime.
189+
*
190+
* @param release if {@code true} and the VM supports releasing the {@code JavaVM} associated
191+
* with libgraal runtimes and this is the last thread attached to a libgraal runtime,
192+
* then this call destroys the associated {@code JavaVM} instance, releasing its
193+
* resources
194+
* @return {@code true} if the {@code JavaVM} associated with the libgraal runtime was destroyed
195+
* as a result of this call
196+
*/
197+
public static boolean detachCurrentThread(boolean release) {
198+
return HotSpotJVMCIRuntime.runtime().detachCurrentThread(release);
199+
}
168200
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionDescriptor.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,16 @@ public boolean isDeprecated() {
196196
return deprecated;
197197
}
198198

199+
/**
200+
* Determines if this descriptor is service loaded.
201+
*
202+
* @see OptionGroup#registerAsService()
203+
*/
204+
public boolean isServiceLoaded() {
205+
OptionGroup group = getDeclaringClass().getAnnotation(OptionGroup.class);
206+
return group == null || !group.registerAsService();
207+
}
208+
199209
/**
200210
* Returns the deprecation reason and the recommended replacement.
201211
*/

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/options/OptionsParser.java

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.ServiceLoader;
3636
import java.util.regex.Pattern;
3737

38+
import jdk.graal.compiler.debug.GraalError;
3839
import org.graalvm.collections.EconomicMap;
3940
import org.graalvm.collections.EconomicSet;
4041
import org.graalvm.collections.MapCursor;
@@ -45,33 +46,46 @@
4546
*/
4647
public class OptionsParser {
4748

48-
private static volatile List<OptionDescriptors> cachedOptionDescriptors;
49+
/**
50+
* The set of compiler options available in libgraal. These correspond to the reachable
51+
* {@link OptionKey}s discovered during Native Image static analysis. This field is only
52+
* non-null when {@link OptionsParser} is loaded by the GuestGraal class loader.
53+
*/
54+
private static EconomicMap<String, OptionDescriptor> libgraalOptionDescriptors;
4955

5056
/**
5157
* Gets an iterable of available {@link OptionDescriptors}.
5258
*/
59+
@ExcludeFromJacocoGeneratedReport("contains libgraal-only path")
5360
public static Iterable<OptionDescriptors> getOptionsLoader() {
54-
return getOptionsLoader(ClassLoader.getSystemClassLoader());
55-
}
56-
57-
@ExcludeFromJacocoGeneratedReport("contains libgraal only path")
58-
public static Iterable<OptionDescriptors> getOptionsLoader(ClassLoader loader) {
59-
if (IS_IN_NATIVE_IMAGE || cachedOptionDescriptors != null) {
60-
return cachedOptionDescriptors;
61+
if (IS_IN_NATIVE_IMAGE) {
62+
GraalError.guarantee(libgraalOptionDescriptors != null, "missing options");
63+
return List.of(new OptionDescriptorsMap(libgraalOptionDescriptors));
64+
}
65+
boolean inGuestGraal = libgraalOptionDescriptors != null;
66+
if (inGuestGraal && IS_BUILDING_NATIVE_IMAGE) {
67+
/*
68+
* Graal code is being run in the context of the GuestGraal loader while building
69+
* libgraal so use the GuestGraal loader to load the OptionDescriptors.
70+
*/
71+
ClassLoader myCL = OptionsParser.class.getClassLoader();
72+
return ServiceLoader.load(OptionDescriptors.class, myCL);
73+
} else {
74+
/*
75+
* The Graal module (i.e., jdk.graal.compiler) is loaded by the platform class loader.
76+
* Modules that depend on and extend Graal are loaded by the app class loader so use it
77+
* (instead of the platform class loader) to load the OptionDescriptors.
78+
*/
79+
ClassLoader loader = ClassLoader.getSystemClassLoader();
80+
return ServiceLoader.load(OptionDescriptors.class, loader);
6181
}
62-
/*
63-
* The Graal module (i.e., jdk.graal.compiler) is loaded by the platform class loader.
64-
* Modules that depend on and extend Graal are loaded by the app class loader. As such, we
65-
* need to start the provider search at the app class loader instead of the platform class
66-
* loader.
67-
*/
68-
return ServiceLoader.load(OptionDescriptors.class, loader);
6982
}
7083

7184
@ExcludeFromJacocoGeneratedReport("only called when building libgraal")
72-
public static void setCachedOptionDescriptors(List<OptionDescriptors> list) {
73-
assert IS_BUILDING_NATIVE_IMAGE : "Used to pre-initialize the option descriptors during native image generation";
74-
OptionsParser.cachedOptionDescriptors = list;
85+
public static void setLibgraalOptionDescriptors(EconomicMap<String, OptionDescriptor> descriptors) {
86+
GraalError.guarantee(IS_BUILDING_NATIVE_IMAGE, "Can only set libgraal compiler options when building libgraal");
87+
GraalError.guarantee(libgraalOptionDescriptors == null, "Libgraal compiler options must be set exactly once");
88+
OptionsParser.libgraalOptionDescriptors = descriptors;
7589
}
7690

7791
/**
@@ -179,13 +193,17 @@ public static void parseOption(String name, Object uncheckedValue, EconomicMap<O
179193

180194
OptionDescriptor desc = lookup(loader, name);
181195
if (desc == null) {
182-
List<OptionDescriptor> matches = fuzzyMatch(loader, name);
183196
Formatter msg = new Formatter();
184-
msg.format("Could not find option %s", name);
185-
if (!matches.isEmpty()) {
186-
msg.format("%nDid you mean one of the following?");
187-
for (OptionDescriptor match : matches) {
188-
msg.format("%n %s=<value>", match.getName());
197+
if (name.equals("PrintGraphFile")) {
198+
msg.format("Option PrintGraphFile has been removed - use PrintGraph=File instead");
199+
} else {
200+
List<OptionDescriptor> matches = fuzzyMatch(loader, name);
201+
msg.format("Could not find option %s", name);
202+
if (!matches.isEmpty()) {
203+
msg.format("%nDid you mean one of the following?");
204+
for (OptionDescriptor match : matches) {
205+
msg.format("%n %s=<value>", match.getName());
206+
}
189207
}
190208
}
191209
throw new IllegalArgumentException(msg.toString());

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/XOptions.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ public static boolean parse(String keyAndValue, EconomicMap<OptionKey<?>, Object
5858
}
5959

6060
/**
61-
* Sets an XOption from a name and a value (e.g., from "mx2g"). Returns true if successful,
62-
* false otherwise. Throws an exception if the option was recognized, but the value was not a
63-
* number.
61+
* Sets an XOption from a name and a value (e.g., from "mx2g"). Returns true if
62+
* {@code keyAndValue} denotes an existing XOption, false otherwise.
63+
*
64+
* @throws IllegalArgumentException if the option was recognized, but the value was not a number
6465
*/
6566
public static boolean setOption(String keyAndValue) {
6667
XFlag xFlag = findXFlag(keyAndValue);

0 commit comments

Comments
 (0)