1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.debug;
  24 
  25 import java.io.IOException;
  26 import java.nio.file.Files;
  27 import java.nio.file.Path;
  28 import java.nio.file.Paths;
  29 
  30 import org.graalvm.compiler.options.Option;
  31 import org.graalvm.compiler.options.OptionKey;
  32 import org.graalvm.compiler.options.OptionType;
  33 import org.graalvm.compiler.options.OptionValues;
  34 import org.graalvm.util.EconomicMap;
  35 
  36 /**
  37  * Options that configure a {@link DebugContext} and related functionality.
  38  */
  39 public class DebugOptions {
  40     static class DeprecatedOptionKey<T> extends OptionKey<T> {
  41         private final OptionKey<T> replacement;
  42 
  43         DeprecatedOptionKey(OptionKey<T> replacement) {
  44             super(replacement.getDefaultValue());
  45             this.replacement = replacement;
  46         }
  47 
  48         @Override
  49         protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, T oldValue, T newValue) {
  50             // Ideally we'd use TTY here but it may not yet be initialized.
  51             System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName());
  52             replacement.update(values, newValue);
  53         }
  54     }
  55 
  56     // @formatter:off
  57     @Option(help = "Comma separated names of timers that are enabled irrespective of the value for Time option. " +
  58                    "An empty value enables all timers unconditionally.", type = OptionType.Debug)
  59     public static final OptionKey<String> Timers = new OptionKey<>(null);
  60     @Option(help = "Comma separated names of counters that are enabled irrespective of the value for Count option. " +
  61                    "An empty value enables all counters unconditionally.", type = OptionType.Debug)
  62     public static final OptionKey<String> Counters = new OptionKey<>(null);
  63     @Option(help = "Comma separated names of memory usage trackers that are enabled irrespective of the value for TrackMemUse option. " +
  64                    "An empty value enables all memory usage trackers unconditionally.", type = OptionType.Debug)
  65     public static final OptionKey<String> MemUseTrackers = new OptionKey<>(null);
  66 
  67     @Option(help = "Pattern for specifying scopes in which counters are enabled. " +
  68                    "See the Dump option for the pattern syntax. " +
  69                    "An empty value enables all counters unconditionally.", type = OptionType.Debug)
  70     public static final OptionKey<String> Count = new OptionKey<>(null);
  71     @Option(help = "Pattern for specifying scopes in which memory use tracking is enabled. " +
  72                    "See the Dump option for the pattern syntax. " +
  73                    "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug)
  74     public static final OptionKey<String> TrackMemUse = new OptionKey<>(null);
  75     @Option(help = "Pattern for specifying scopes in which timing is enabled. " +
  76                    "See the Dump option for the pattern syntax. " +
  77                    "An empty value enables all timers unconditionally.", type = OptionType.Debug)
  78     public static final OptionKey<String> Time = new OptionKey<>(null);
  79 
  80     @Option(help = "Pattern for specifying scopes in which logging is enabled. " +
  81                    "See the Dump option for the pattern syntax.", type = OptionType.Debug)
  82     public static final OptionKey<String> Verify = new OptionKey<>(null);
  83     @Option(help = "file:doc-files/DumpHelp.txt", type = OptionType.Debug)
  84     public static final OptionKey<String> Dump = new OptionKey<>(null);
  85     @Option(help = "Pattern for specifying scopes in which logging is enabled. " +
  86                    "See the Dump option for the pattern syntax.", type = OptionType.Debug)
  87     public static final OptionKey<String> Log = new OptionKey<>(null);
  88     @Option(help = "file:doc-files/MethodFilterHelp.txt")
  89     public static final OptionKey<String> MethodFilter = new OptionKey<>(null);
  90     @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug)
  91     public static final OptionKey<Boolean> MethodFilterRootOnly = new OptionKey<>(false);
  92     @Option(help = "Dump a before and after graph if the named phase changes the graph.%n" +
  93                    "The argument is substring matched against the simple name of the phase class", type = OptionType.Debug)
  94     public static final OptionKey<String> DumpOnPhaseChange = new OptionKey<>(null);
  95 
  96     @Option(help = "Lists on the console at VM shutdown the metric names available to the Timers, Counters and MemUseTrackers options. " +
  97                    "Note that this only lists the metrics that were initialized during the VM execution and so " +
  98                    "will not include metrics for compiler code that is not executed.", type = OptionType.Debug)
  99     public static final OptionKey<Boolean> ListMetrics = new OptionKey<>(false);
 100     @Option(help = "file:doc-files/MetricsFileHelp.txt", type = OptionType.Debug)
 101      public static final OptionKey<String> MetricsFile = new OptionKey<>(null);
 102     @Option(help = "File to which aggregated metrics are dumped at shutdown. A CSV format is used if the file ends with .csv " +
 103                     "otherwise a more human readable format is used. If not specified, metrics are dumped to the console.", type = OptionType.Debug)
 104     public static final OptionKey<String> AggregatedMetricsFile = new OptionKey<>(null);
 105 
 106     @Option(help = "Only report metrics for threads whose name matches the regular expression.", type = OptionType.Debug)
 107     public static final OptionKey<String> MetricsThreadFilter = new OptionKey<>(null);
 108     @Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug)
 109     public static final OptionKey<Boolean> DebugStubsAndSnippets = new OptionKey<>(false);
 110     @Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug)
 111     public static final OptionKey<Boolean> DumpOnError = new OptionKey<>(false);
 112     @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug)
 113     public static final OptionKey<Boolean> InterceptBailout = new OptionKey<>(false);
 114     @Option(help = "Enable more verbose log output when available", type = OptionType.Debug)
 115     public static final OptionKey<Boolean> LogVerbose = new OptionKey<>(false);
 116 
 117     @Option(help = "The directory where various Graal dump files are written.")
 118     public static final OptionKey<String> DumpPath = new OptionKey<>("dumps");
 119     @Option(help = "Print the name of each dump file path as it's created.")
 120     public static final OptionKey<Boolean> ShowDumpFiles = new OptionKey<>(false);
 121 
 122     @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug)
 123     public static final OptionKey<Boolean> PrintCFG = new OptionKey<>(false);
 124     @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug)
 125     public static final OptionKey<Boolean> PrintBackendCFG = new OptionKey<>(true);
 126 
 127     @Option(help = "Output probabilities for fixed nodes during binary graph dumping.", type = OptionType.Debug)
 128     public static final OptionKey<Boolean> PrintGraphProbabilities = new OptionKey<>(false);
 129     @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug)
 130     public static final OptionKey<Boolean> PrintGraph = new OptionKey<>(true);
 131     @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug)
 132     public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<>(false);
 133 
 134     @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug)
 135     public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1");
 136     @Option(help = "Port part of the address to which graphs are dumped in XML format (ignored if PrintBinaryGraphs=true).", type = OptionType.Debug)
 137     public static final OptionKey<Integer> PrintXmlGraphPort = new OptionKey<>(4444);
 138     @Option(help = "Port part of the address to which graphs are dumped in binary format (ignored if PrintBinaryGraphs=false).", type = OptionType.Debug)
 139     public static final OptionKey<Integer> PrintBinaryGraphPort = new OptionKey<>(4445);
 140     @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug)
 141     public static final OptionKey<Boolean> PrintGraphWithSchedule = new OptionKey<>(false);
 142 
 143     @Option(help = "Enable dumping Truffle ASTs to the IdealGraphVisualizer.", type = OptionType.Debug)
 144     public static final OptionKey<Boolean> PrintTruffleTrees = new OptionKey<>(true);
 145 
 146     @Option(help = "Treat any exceptions during dumping as fatal.", type = OptionType.Debug)
 147     public static final OptionKey<Boolean> DumpingErrorsAreFatal = new OptionKey<>(false);
 148 
 149     @Option(help = "Enable dumping canonical text from for graphs.", type = OptionType.Debug)
 150     public static final OptionKey<Boolean> PrintCanonicalGraphStrings = new OptionKey<>(false);
 151     @Option(help = "Choose format used when dumping canonical text for graphs: " +
 152             "0 gives a scheduled graph (better for spotting changes involving the schedule) " +
 153             "while 1 gives a CFG containing expressions rooted at fixed nodes (better for spotting small structure differences)", type = OptionType.Debug)
 154     public static final OptionKey<Integer> PrintCanonicalGraphStringFlavor = new OptionKey<>(0);
 155     @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug)
 156     public static final OptionKey<Boolean> CanonicalGraphStringsExcludeVirtuals = new OptionKey<>(true);
 157     @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug)
 158     public static final OptionKey<Boolean> CanonicalGraphStringsCheckConstants = new OptionKey<>(false);
 159     @Option(help = "Attempts to remove object identity hashes when dumping canonical text for graphs.", type = OptionType.Debug)
 160     public static final OptionKey<Boolean> CanonicalGraphStringsRemoveIdentities = new OptionKey<>(true);
 161 
 162     @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug)
 163     public static final OptionKey<Boolean> ClearMetricsAfterBootstrap = new OptionKey<>(false);
 164     @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug)
 165     public static final OptionKey<Boolean> BootstrapInitializeOnly = new OptionKey<>(false);
 166 
 167     // These will be removed at some point
 168     @Option(help = "Deprecated - use PrintGraphHost instead.", type = OptionType.Debug)
 169     static final OptionKey<String> PrintIdealGraphAddress = new DebugOptions.DeprecatedOptionKey<>(PrintGraphHost);
 170     @Option(help = "Deprecated - use PrintGraphWithSchedule instead.", type = OptionType.Debug)
 171     static final OptionKey<Boolean> PrintIdealGraphSchedule = new DebugOptions.DeprecatedOptionKey<>(PrintGraphWithSchedule);
 172     @Option(help = "Deprecated - use PrintGraph instead.", type = OptionType.Debug)
 173     static final OptionKey<Boolean> PrintIdealGraph = new DebugOptions.DeprecatedOptionKey<>(PrintGraph);
 174     @Option(help = "Deprecated - use PrintGraphFile instead.", type = OptionType.Debug)
 175     static final OptionKey<Boolean> PrintIdealGraphFile = new DebugOptions.DeprecatedOptionKey<>(PrintGraphFile);
 176     @Option(help = "Deprecated - use PrintXmlGraphPort instead.", type = OptionType.Debug)
 177     static final OptionKey<Integer> PrintIdealGraphPort = new DebugOptions.DeprecatedOptionKey<>(PrintXmlGraphPort);
 178     // @formatter:on
 179 
 180     /**
 181      * Gets the directory in which {@link DebugDumpHandler}s can generate output. This will be the
 182      * directory specified by {@link #DumpPath} if it has been set otherwise it will be derived from
 183      * the default value of {@link #DumpPath} and {@link PathUtilities#getGlobalTimeStamp()}.
 184      *
 185      * This method will ensure the returned directory exists, printing a message to {@link TTY} if
 186      * it creates it.
 187      *
 188      * @return a path as described above whose directories are guaranteed to exist
 189      * @throws IOException if there was an error in {@link Files#createDirectories}
 190      */
 191     public static Path getDumpDirectory(OptionValues options) throws IOException {
 192         Path dumpDir;
 193         if (DumpPath.hasBeenSet(options)) {
 194             dumpDir = Paths.get(DumpPath.getValue(options));
 195         } else {
 196             dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(PathUtilities.getGlobalTimeStamp()));
 197         }
 198         dumpDir = dumpDir.toAbsolutePath();
 199         if (!Files.exists(dumpDir)) {
 200             synchronized (DebugConfigImpl.class) {
 201                 if (!Files.exists(dumpDir)) {
 202                     Files.createDirectories(dumpDir);
 203                     TTY.println("Dumping debug output in %s", dumpDir.toString());
 204                 }
 205             }
 206         }
 207         return dumpDir;
 208     }
 209 }