--- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java 2017-07-07 09:32:18.000000000 -0700 +++ /dev/null 2017-07-07 09:32:18.000000000 -0700 @@ -1,452 +0,0 @@ -/* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug; - -import java.io.PrintStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -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.OptionValues; -import org.graalvm.util.EconomicMap; - -import jdk.vm.ci.code.BailoutException; -import jdk.vm.ci.meta.JavaMethod; - -public class GraalDebugConfig implements DebugConfig { - - 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 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 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 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 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 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 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 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 OptionKey MethodFilterRootOnly = new OptionKey<>(false); - @Option(help = "Dump a before and after graph if the named phase changes the graph.%n" + - "The argument is substring matched against the simple name of the phase class", type = OptionType.Debug) - public static final OptionKey DumpOnPhaseChange = new OptionKey<>(null); - - @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 OptionKey DebugValueSummary = new OptionKey<>("Name"); - @Option(help = "Print counters and timers in a human readable form.", type = OptionType.Debug) - public static final OptionKey DebugValueHumanReadable = new OptionKey<>(true); - @Option(help = "Omit reporting 0-value counters", type = OptionType.Debug) - 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 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 OptionKey DebugValueFile = new OptionKey<>(null); - @Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug) - public static final OptionKey DebugStubsAndSnippets = new OptionKey<>(false); - @Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug) - public static final OptionKey DumpOnError = new OptionKey<>(false); - @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) - public static final OptionKey InterceptBailout = new OptionKey<>(false); - @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) - public static final OptionKey LogVerbose = new OptionKey<>(false); - - @Option(help = "The directory where various Graal dump files are written.") - 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 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 OptionKey PrintBackendCFG = new OptionKey<>(true); - @Option(help = "Base filename when dumping C1Visualizer output to files.", type = OptionType.Debug) - 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 OptionKey PrintGraphProbabilities = new OptionKey<>(false); - @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) - 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 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 OptionKey PrintCanonicalGraphStrings = new OptionKey<>(false); - @Option(help = "Base directory when dumping graphs strings to files.", type = OptionType.Debug) - 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 OptionKey PrintCanonicalGraphStringFlavor = new OptionKey<>(0); - @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - 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 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 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 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. " + - "Whenever a value is added to a global metric, the value is also added to a MethodMetric under the same name " + - "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 OptionKey GlobalMetricsInterceptedByMethodMetrics = new OptionKey<>(null); - @Option(help = "Force-enable debug code paths", type = OptionType.Debug) - public static final OptionKey ForceDebugEnable = new OptionKey<>(false); - @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug) - 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 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 - } - - 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(OptionValues options) { - return Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null || Options.Log.getValue(options) != null || areScopedGlobalMetricsEnabled(options); - } - - 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(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; - private final DebugFilter trackMemUseFilter; - private final DebugFilter timerFilter; - private final DebugFilter dumpFilter; - private final DebugFilter verifyFilter; - private final MethodFilter[] methodFilter; - private final List dumpHandlers; - private final List verifyHandlers; - private final PrintStream output; - - // Use an identity set to handle context objects that don't support hashCode(). - private final Set extraFilters = Collections.newSetFromMap(new IdentityHashMap<>()); - - 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); - this.timerFilter = DebugFilter.parse(timerFilter); - this.dumpFilter = DebugFilter.parse(dumpFilter); - this.verifyFilter = DebugFilter.parse(verifyFilter); - this.methodMetricsFilter = DebugFilter.parse(methodMetricsFilter); - if (methodFilter == null || methodFilter.isEmpty()) { - this.methodFilter = null; - } else { - this.methodFilter = org.graalvm.compiler.debug.MethodFilter.parse(methodFilter); - } - - this.dumpHandlers = dumpHandlers; - this.verifyHandlers = verifyHandlers; - this.output = output; - } - - @Override - public OptionValues getOptions() { - return options; - } - - @Override - public int getLogLevel() { - return getLevel(logFilter); - } - - @Override - public boolean isLogEnabledForMethod() { - return isEnabledForMethod(logFilter); - } - - @Override - public boolean isCountEnabled() { - return isEnabled(countFilter); - } - - @Override - public boolean isMemUseTrackingEnabled() { - return isEnabled(trackMemUseFilter); - } - - @Override - public int getDumpLevel() { - return getLevel(dumpFilter); - } - - @Override - public boolean isDumpEnabledForMethod() { - return isEnabledForMethod(dumpFilter); - } - - @Override - public boolean isVerifyEnabled() { - return isEnabled(verifyFilter); - } - - @Override - public boolean isVerifyEnabledForMethod() { - return isEnabledForMethod(verifyFilter); - } - - @Override - public boolean isMethodMeterEnabled() { - return isEnabled(methodMetricsFilter); - } - - @Override - public boolean isTimeEnabled() { - return isEnabled(timerFilter); - } - - @Override - public PrintStream output() { - return output; - } - - private boolean isEnabled(DebugFilter filter) { - return getLevel(filter) > 0; - } - - private int getLevel(DebugFilter filter) { - int level; - if (filter == null) { - level = 0; - } else { - level = filter.matchLevel(Debug.currentScope()); - } - if (level >= 0 && !checkMethodFilter()) { - level = -1; - } - return level; - } - - private boolean isEnabledForMethod(DebugFilter filter) { - return filter != null && checkMethodFilter(); - } - - /** - * Extracts a {@link JavaMethod} from an opaque debug context. - * - * @return the {@link JavaMethod} represented by {@code context} or null - */ - public static JavaMethod asJavaMethod(Object context) { - if (context instanceof JavaMethodContext) { - return ((JavaMethodContext) context).asJavaMethod(); - } - if (context instanceof JavaMethod) { - return (JavaMethod) context; - } - return null; - } - - private boolean checkMethodFilter() { - if (methodFilter == null && extraFilters.isEmpty()) { - return true; - } else { - JavaMethod lastMethod = null; - for (Object o : Debug.context()) { - if (extraFilters.contains(o)) { - return true; - } else if (methodFilter != null) { - JavaMethod method = asJavaMethod(o); - if (method != null) { - if (!Options.MethodFilterRootOnly.getValue(options)) { - if (org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, method)) { - return true; - } - } else { - /* - * The context values operate as a stack so if we want MethodFilter to - * only apply to the root method we have to check only the last method - * seen. - */ - lastMethod = method; - } - } - } - } - if (lastMethod != null && org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, lastMethod)) { - return true; - } - return false; - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Debug config:"); - add(sb, "Log", logFilter); - add(sb, "Count", countFilter); - add(sb, "MethodMeter", methodMetricsFilter); - add(sb, "Time", timerFilter); - add(sb, "Dump", dumpFilter); - add(sb, "MethodFilter", methodFilter); - return sb.toString(); - } - - private static void add(StringBuilder sb, String name, Object filter) { - if (filter != null) { - sb.append(' '); - sb.append(name); - sb.append('='); - if (filter instanceof Object[]) { - sb.append(Arrays.toString((Object[]) filter)); - } else { - sb.append(String.valueOf(filter)); - } - } - } - - @Override - public RuntimeException interceptException(Throwable e) { - if (e instanceof BailoutException && !Options.InterceptBailout.getValue(options)) { - return null; - } - Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LEVEL, Debug.BASIC_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(options) || Options.Dump.getValue(options) != null) { - Debug.dump(Debug.BASIC_LEVEL, o, "Exception: %s", e); - } else { - Debug.log("Context obj %s", o); - } - } - } - return null; - } - - @Override - public Collection dumpHandlers() { - return dumpHandlers; - } - - @Override - public Collection verifyHandlers() { - return verifyHandlers; - } - - @Override - public void addToContext(Object o) { - extraFilters.add(o); - } - - @Override - public void removeFromContext(Object o) { - extraFilters.remove(o); - } - -}