--- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java 2017-03-20 17:37:53.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java 2017-03-20 17:37:53.000000000 -0700 @@ -32,119 +32,113 @@ import java.util.Set; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.meta.JavaMethod; public class GraalDebugConfig implements DebugConfig { - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } public static class Options { // @formatter:off @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug) - public static final OptionValue Dump = new OptionValue<>(null); + public static final OptionKey Dump = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which counting is enabled (see DebugFilter and Debug.counter). " + "An empty value enables all counters unconditionally.", type = OptionType.Debug) - public static final OptionValue Count = new OptionValue<>(null); + public static final OptionKey Count = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug) - public static final OptionValue Verify = new OptionValue() { - @Override - protected String defaultValue() { - return assertionsEnabled() ? "" : null; - } - }; + public static final OptionKey Verify = new OptionKey<>(Assertions.ENABLED ? "" : null); @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.counter). " + "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug) - public static final OptionValue TrackMemUse = new OptionValue<>(null); + public static final OptionKey TrackMemUse = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer). " + "An empty value enables all timers unconditionally.", type = OptionType.Debug) - public static final OptionValue Time = new OptionValue<>(null); + public static final OptionKey Time = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug) - public static final OptionValue Log = new OptionValue<>(null); + public static final OptionKey Log = new OptionKey<>(null); @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)", type = OptionType.Debug) - public static final OptionValue MethodFilter = new OptionValue<>(null); + public static final OptionKey MethodFilter = new OptionKey<>(null); @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug) - public static final OptionValue MethodFilterRootOnly = new OptionValue<>(false); + public static final OptionKey MethodFilterRootOnly = new OptionKey<>(false); @Option(help = "How to print counters and timing values:%n" + "Name - aggregate by unqualified name%n" + "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" + "Complete - aggregate by qualified name%n" + "Thread - aggregate by qualified name and thread", type = OptionType.Debug) - public static final OptionValue DebugValueSummary = new OptionValue<>("Name"); + public static final OptionKey DebugValueSummary = new OptionKey<>("Name"); @Option(help = "Print counters and timers in a human readable form.", type = OptionType.Debug) - public static final OptionValue DebugValueHumanReadable = new OptionValue<>(true); + public static final OptionKey DebugValueHumanReadable = new OptionKey<>(true); @Option(help = "Omit reporting 0-value counters", type = OptionType.Debug) - public static final OptionValue SuppressZeroDebugValues = new OptionValue<>(true); + public static final OptionKey SuppressZeroDebugValues = new OptionKey<>(true); @Option(help = "Only report debug values for maps which match the regular expression.", type = OptionType.Debug) - public static final OptionValue DebugValueThreadFilter = new OptionValue<>(null); + public static final OptionKey DebugValueThreadFilter = new OptionKey<>(null); @Option(help = "Write debug values into a file instead of the terminal. " + "If DebugValueSummary is Thread, the thread name will be prepended.", type = OptionType.Debug) - public static final OptionValue DebugValueFile = new OptionValue<>(null); + public static final OptionKey DebugValueFile = new OptionKey<>(null); @Option(help = "Send Graal compiler IR to dump handlers on error", type = OptionType.Debug) - public static final OptionValue DumpOnError = new OptionValue<>(false); + public static final OptionKey DumpOnError = new OptionKey<>(false); @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) - public static final OptionValue InterceptBailout = new OptionValue<>(false); + public static final OptionKey InterceptBailout = new OptionKey<>(false); @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) - public static final OptionValue LogVerbose = new OptionValue<>(false); + public static final OptionKey LogVerbose = new OptionKey<>(false); @Option(help = "The directory where various Graal dump files are written.") - public static final OptionValue DumpPath = new OptionValue<>("."); + public static final OptionKey DumpPath = new OptionKey<>("."); @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug) - public static final OptionValue PrintCFG = new OptionValue<>(false); + public static final OptionKey PrintCFG = new OptionKey<>(false); @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) - public static final OptionValue PrintBackendCFG = new OptionValue<>(true); + public static final OptionKey PrintBackendCFG = new OptionKey<>(true); @Option(help = "Base filename when dumping C1Visualizer output to files.", type = OptionType.Debug) - public static final OptionValue PrintCFGFileName = new OptionValue<>("compilations"); + public static final OptionKey PrintCFGFileName = new OptionKey<>("compilations"); - @Option(help = "Output probabilities for fixed nodes during binary graph dumping", type = OptionType.Debug) - public static final OptionValue PrintGraphProbabilities = new OptionValue<>(false); + @Option(help = "Output probabilities for fixed nodes during binary graph dumping.", type = OptionType.Debug) + public static final OptionKey PrintGraphProbabilities = new OptionKey<>(false); @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraph = new OptionValue<>(true); - @Option(help = "Dump IdealGraphVisualizer output in binary format", type = OptionType.Debug) - public static final OptionValue PrintBinaryGraphs = new OptionValue<>(true); - @Option(help = "Print Ideal graphs as opposed to sending them over the network.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphFile = new OptionValue<>(false); - @Option(help = "Base filename when dumping Ideal graphs to files.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphFileName = new OptionValue<>("runtime-graphs"); - - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphAddress = new OptionValue<>("127.0.0.1"); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphPort = new OptionValue<>(4444); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintBinaryGraphPort = new OptionValue<>(4445); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphSchedule = new OptionValue<>(false); + public static final OptionKey PrintGraph = new OptionKey<>(true); + @Option(help = "Dump graphs in binary format instead of XML format.", type = OptionType.Debug) + public static final OptionKey PrintBinaryGraphs = new OptionKey<>(true); + @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug) + public static final OptionKey PrintGraphFile = new OptionKey<>(false); + @Option(help = "Base filename when dumping graphs to files.", type = OptionType.Debug) + public static final OptionKey PrintGraphFileName = new OptionKey<>("runtime-graphs"); + + @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug) + public static final OptionKey PrintGraphHost = new OptionKey<>("127.0.0.1"); + @Option(help = "Port part of the address to which graphs are dumped in XML format (ignored if PrintBinaryGraphs=true).", type = OptionType.Debug) + public static final OptionKey PrintXmlGraphPort = new OptionKey<>(4444); + @Option(help = "Port part of the address to which graphs are dumped in binary format (ignored if PrintBinaryGraphs=false).", type = OptionType.Debug) + public static final OptionKey PrintBinaryGraphPort = new OptionKey<>(4445); + @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug) + public static final OptionKey PrintGraphWithSchedule = new OptionKey<>(false); @Option(help = "Enable dumping Truffle ASTs to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionValue PrintTruffleTrees = new OptionValue<>(true); + public static final OptionKey PrintTruffleTrees = new OptionKey<>(true); + + @Option(help = "Treat any exceptions during dumping as fatal.", type = OptionType.Debug) + public static final OptionKey DumpingErrorsAreFatal = new OptionKey<>(false); @Option(help = "Enable dumping canonical text from for graphs.", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStrings = new OptionValue<>(false); + public static final OptionKey PrintCanonicalGraphStrings = new OptionKey<>(false); @Option(help = "Base directory when dumping graphs strings to files.", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStringsDirectory = new OptionValue<>("graph-strings"); + public static final OptionKey PrintCanonicalGraphStringsDirectory = new OptionKey<>("graph-strings"); @Option(help = "Choose format used when dumping canonical text for graphs: " + "0 gives a scheduled graph (better for spotting changes involving the schedule)" + "while 1 gives a CFG containing expressions rooted at fixed nodes (better for spotting small structure differences)", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStringFlavor = new OptionValue<>(0); + public static final OptionKey PrintCanonicalGraphStringFlavor = new OptionKey<>(0); @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsExcludeVirtuals = new OptionValue<>(true); + public static final OptionKey CanonicalGraphStringsExcludeVirtuals = new OptionKey<>(true); @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsCheckConstants = new OptionValue<>(false); + public static final OptionKey CanonicalGraphStringsCheckConstants = new OptionKey<>(false); @Option(help = "Attempts to remove object identity hashes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsRemoveIdentities = new OptionValue<>(true); + public static final OptionKey CanonicalGraphStringsRemoveIdentities = new OptionKey<>(true); @Option(help = "Enable per method metrics that are collected across all compilations of a method." + "Pattern for scope(s) in which method metering is enabled (see DebugFilter and Debug.metric).", type = OptionType.Debug) - public static final OptionValue MethodMeter = new OptionValue<>(null); + public static final OptionKey MethodMeter = new OptionKey<>(null); @Option(help = "If a global metric (DebugTimer, DebugCounter or DebugMemUseTracker) is enabled in the same scope as a method metric, " + "use the global metric to update the method metric for the current compilation. " + "This option enables the re-use of global metrics on per-compilation basis. " + @@ -152,36 +146,70 @@ "as the global metric. " + "This option incurs a small but constant overhead due to the context method lookup at each metric update. " + "Format to specify GlobalMetric interception:(Timers|Counters|MemUseTrackers)(,Timers|,Counters|,MemUseTrackers)*", type = OptionType.Debug) - public static final OptionValue GlobalMetricsInterceptedByMethodMetrics = new OptionValue<>(null); + public static final OptionKey GlobalMetricsInterceptedByMethodMetrics = new OptionKey<>(null); @Option(help = "Force-enable debug code paths", type = OptionType.Debug) - public static final OptionValue ForceDebugEnable = new OptionValue<>(false); + public static final OptionKey ForceDebugEnable = new OptionKey<>(false); @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug) - public static final OptionValue ClearMetricsAfterBootstrap = new OptionValue<>(false); + public static final OptionKey ClearMetricsAfterBootstrap = new OptionKey<>(false); @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug) - public static final OptionValue BootstrapInitializeOnly = new OptionValue<>(false); + public static final OptionKey BootstrapInitializeOnly = new OptionKey<>(false); + + // These + @Option(help = "Deprecated - use PrintGraphHost instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphAddress = new DeprecatedOptionKey<>(PrintGraphHost); + @Option(help = "Deprecated - use PrintGraphWithSchedule instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphSchedule = new DeprecatedOptionKey<>(PrintGraphWithSchedule); + @Option(help = "Deprecated - use PrintGraph instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraph = new DeprecatedOptionKey<>(PrintGraph); + @Option(help = "Deprecated - use PrintGraphFile instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphFile = new DeprecatedOptionKey<>(PrintGraphFile); + @Option(help = "Deprecated - use PrintGraphFileName instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphFileName = new DeprecatedOptionKey<>(PrintGraphFileName); + @Option(help = "Deprecated - use PrintXmlGraphPort instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphPort = new DeprecatedOptionKey<>(PrintXmlGraphPort); // @formatter:on } - public static boolean isNotEmpty(OptionValue option) { - return option.getValue() != null && !option.getValue().isEmpty(); + static class DeprecatedOptionKey extends OptionKey { + private final OptionKey replacement; + + DeprecatedOptionKey(OptionKey replacement) { + super(replacement.getDefaultValue()); + this.replacement = replacement; + } + + @Override + protected void onValueUpdate(EconomicMap, Object> values, T oldValue, T newValue) { + // Ideally we'd use TTY here but it may not yet be initialized. + System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName()); + replacement.update(values, newValue); + } + } + + public static boolean isNotEmpty(OptionKey option, OptionValues options) { + return option.getValue(options) != null && !option.getValue(options).isEmpty(); } - public static boolean areDebugScopePatternsEnabled() { - return Options.DumpOnError.getValue() || Options.Dump.getValue() != null || Options.Log.getValue() != null || areScopedGlobalMetricsEnabled(); + public static boolean areDebugScopePatternsEnabled(OptionValues options) { + return Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null || Options.Log.getValue(options) != null || areScopedGlobalMetricsEnabled(options); } - public static boolean isGlobalMetricsInterceptedByMethodMetricsEnabled() { - return isNotEmpty(Options.GlobalMetricsInterceptedByMethodMetrics); + public static boolean isGlobalMetricsInterceptedByMethodMetricsEnabled(OptionValues options) { + return isNotEmpty(Options.GlobalMetricsInterceptedByMethodMetrics, options); } /** * Determines if any of {@link Options#Count}, {@link Options#Time} or * {@link Options#TrackMemUse} has a non-null, non-empty value. + * + * @param options */ - public static boolean areScopedGlobalMetricsEnabled() { - return isNotEmpty(Options.Count) || isNotEmpty(Options.Time) || isNotEmpty(Options.TrackMemUse) || isNotEmpty(Options.MethodMeter); + public static boolean areScopedGlobalMetricsEnabled(OptionValues options) { + return isNotEmpty(Options.Count, options) || isNotEmpty(Options.Time, options) || isNotEmpty(Options.TrackMemUse, options) || isNotEmpty(Options.MethodMeter, options); } + private final OptionValues options; + private final DebugFilter countFilter; private final DebugFilter logFilter; private final DebugFilter methodMetricsFilter; @@ -197,8 +225,9 @@ // Use an identity set to handle context objects that don't support hashCode(). private final Set extraFilters = Collections.newSetFromMap(new IdentityHashMap<>()); - public GraalDebugConfig(String logFilter, String countFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, + public GraalDebugConfig(OptionValues options, String logFilter, String countFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, String methodMetricsFilter, PrintStream output, List dumpHandlers, List verifyHandlers) { + this.options = options; this.logFilter = DebugFilter.parse(logFilter); this.countFilter = DebugFilter.parse(countFilter); this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); @@ -212,16 +241,17 @@ this.methodFilter = org.graalvm.compiler.debug.MethodFilter.parse(methodFilter); } - // Report the filters that have been configured so the user can verify it's what they expect - if (logFilter != null || countFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) { - // TTY.println(Thread.currentThread().getName() + ": " + toString()); - } this.dumpHandlers = dumpHandlers; this.verifyHandlers = verifyHandlers; this.output = output; } @Override + public OptionValues getOptions() { + return options; + } + + @Override public int getLogLevel() { return getLevel(logFilter); } @@ -323,7 +353,7 @@ } else if (methodFilter != null) { JavaMethod method = asJavaMethod(o); if (method != null) { - if (!Options.MethodFilterRootOnly.getValue()) { + if (!Options.MethodFilterRootOnly.getValue(options)) { if (org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, method)) { return true; } @@ -373,17 +403,17 @@ @Override public RuntimeException interceptException(Throwable e) { - if (e instanceof BailoutException && !Options.InterceptBailout.getValue()) { + if (e instanceof BailoutException && !Options.InterceptBailout.getValue(options)) { return null; } - Debug.setConfig(Debug.fixedConfig(Debug.BASIC_LOG_LEVEL, Debug.BASIC_LOG_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); + Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LOG_LEVEL, Debug.BASIC_LOG_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); Debug.log("Exception occurred in scope: %s", Debug.currentScope()); Map firstSeen = new IdentityHashMap<>(); for (Object o : Debug.context()) { // Only dump a context object once. if (!firstSeen.containsKey(o)) { firstSeen.put(o, o); - if (Options.DumpOnError.getValue()) { + if (Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null) { Debug.dump(Debug.BASIC_LOG_LEVEL, o, "Exception: %s", e); } else { Debug.log("Context obj %s", o);