1 /*
   2  * Copyright (c) 2017, 2018, 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 
  24 
  25 package org.graalvm.compiler.debug;
  26 
  27 import java.io.IOException;
  28 import java.nio.file.Files;
  29 import java.nio.file.Path;
  30 import java.nio.file.Paths;
  31 
  32 import jdk.internal.vm.compiler.collections.EconomicMap;
  33 import org.graalvm.compiler.options.EnumOptionKey;
  34 import org.graalvm.compiler.options.Option;
  35 import org.graalvm.compiler.options.OptionKey;
  36 import org.graalvm.compiler.options.OptionType;
  37 import org.graalvm.compiler.options.OptionValues;
  38 import org.graalvm.compiler.serviceprovider.GraalServices;
  39 
  40 /**
  41  * Options that configure a {@link DebugContext} and related functionality.
  42  */
  43 public class DebugOptions {
  44 
  45     /**
  46      * Values for the {@link DebugOptions#PrintGraph} option denoting where graphs dumped as a
  47      * result of the {@link DebugOptions#Dump} option are sent.
  48      */
  49     public enum PrintGraphTarget {
  50         /**
  51          * Dump graphs to files.
  52          */
  53         File,
  54 
  55         /**
  56          * Dump graphs to the network. The network destination is specified by the
  57          * {@link DebugOptions#PrintGraphHost} and {@link DebugOptions#PrintGraphPort} options. If a
  58          * network connection cannot be opened, dumping falls back to {@link #File} dumping.
  59          */
  60         Network,
  61 
  62         /**
  63          * Do not dump graphs.
  64          */
  65         Disable;
  66     }
  67 
  68     // @formatter:off
  69     @Option(help = "Comma separated names of timers that are enabled irrespective of the value for Time option. " +
  70                    "An empty value enables all timers unconditionally.", type = OptionType.Debug)
  71     public static final OptionKey<String> Timers = new OptionKey<>(null);
  72     @Option(help = "Comma separated names of counters that are enabled irrespective of the value for Count option. " +
  73                    "An empty value enables all counters unconditionally.", type = OptionType.Debug)
  74     public static final OptionKey<String> Counters = new OptionKey<>(null);
  75     @Option(help = "Comma separated names of memory usage trackers that are enabled irrespective of the value for TrackMemUse option. " +
  76                    "An empty value enables all memory usage trackers unconditionally.", type = OptionType.Debug)
  77     public static final OptionKey<String> MemUseTrackers = new OptionKey<>(null);
  78 
  79     @Option(help = "Pattern for specifying scopes in which counters are enabled. " +
  80                    "See the Dump option for the pattern syntax. " +
  81                    "An empty value enables all counters unconditionally.", type = OptionType.Debug)
  82     public static final OptionKey<String> Count = new OptionKey<>(null);
  83     @Option(help = "Pattern for specifying scopes in which memory use tracking is enabled. " +
  84                    "See the Dump option for the pattern syntax. " +
  85                    "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug)
  86     public static final OptionKey<String> TrackMemUse = new OptionKey<>(null);
  87     @Option(help = "Pattern for specifying scopes in which timing is enabled. " +
  88                    "See the Dump option for the pattern syntax. " +
  89                    "An empty value enables all timers unconditionally.", type = OptionType.Debug)
  90     public static final OptionKey<String> Time = new OptionKey<>(null);
  91 
  92     @Option(help = "Pattern for specifying scopes in which logging is enabled. " +
  93                    "See the Dump option for the pattern syntax.", type = OptionType.Debug)
  94     public static final OptionKey<String> Verify = new OptionKey<>(null);
  95     @Option(help = "file:doc-files/DumpHelp.txt", type = OptionType.Debug)
  96     public static final OptionKey<String> Dump = new OptionKey<>(null);
  97     @Option(help = "Pattern for specifying scopes in which logging is enabled. " +
  98                    "See the Dump option for the pattern syntax.", type = OptionType.Debug)
  99     public static final OptionKey<String> Log = new OptionKey<>(null);
 100     @Option(help = "file:doc-files/MethodFilterHelp.txt")
 101     public static final OptionKey<String> MethodFilter = new OptionKey<>(null);
 102     @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug)
 103     public static final OptionKey<Boolean> MethodFilterRootOnly = new OptionKey<>(false);
 104     @Option(help = "Dump a before and after graph if the named phase changes the graph.%n" +
 105                    "The argument is substring matched against the simple name of the phase class", type = OptionType.Debug)
 106     public static final OptionKey<String> DumpOnPhaseChange = new OptionKey<>(null);
 107 
 108     @Option(help = "Lists on the console at VM shutdown the metric names available to the Timers, Counters and MemUseTrackers options. " +
 109                    "Note that this only lists the metrics that were initialized during the VM execution and so " +
 110                    "will not include metrics for compiler code that is not executed.", type = OptionType.Debug)
 111     public static final OptionKey<Boolean> ListMetrics = new OptionKey<>(false);
 112     @Option(help = "file:doc-files/MetricsFileHelp.txt", type = OptionType.Debug)
 113      public static final OptionKey<String> MetricsFile = new OptionKey<>(null);
 114     @Option(help = "File to which aggregated metrics are dumped at shutdown. A CSV format is used if the file ends with .csv " +
 115                     "otherwise a more human readable format is used. If not specified, metrics are dumped to the console.", type = OptionType.Debug)
 116     public static final OptionKey<String> AggregatedMetricsFile = new OptionKey<>(null);
 117 
 118     @Option(help = "Only report metrics for threads whose name matches the regular expression.", type = OptionType.Debug)
 119     public static final OptionKey<String> MetricsThreadFilter = new OptionKey<>(null);
 120     @Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug)
 121     public static final OptionKey<Boolean> DebugStubsAndSnippets = new OptionKey<>(false);
 122     @Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug)
 123     public static final OptionKey<Boolean> DumpOnError = new OptionKey<>(false);
 124     @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug)
 125     public static final OptionKey<Boolean> InterceptBailout = new OptionKey<>(false);
 126     @Option(help = "Enable more verbose log output when available", type = OptionType.Debug)
 127     public static final OptionKey<Boolean> LogVerbose = new OptionKey<>(false);
 128 
 129     @Option(help = "The directory where various Graal dump files are written.")
 130     public static final OptionKey<String> DumpPath = new OptionKey<>("graal_dumps");
 131     @Option(help = "Print the name of each dump file path as it's created.")
 132     public static final OptionKey<Boolean> ShowDumpFiles = new OptionKey<>(false);
 133 
 134     @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug)
 135     public static final OptionKey<Boolean> PrintCFG = new OptionKey<>(false);
 136     @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug)
 137     public static final OptionKey<Boolean> PrintBackendCFG = new OptionKey<>(true);
 138 
 139     @Option(help = "file:doc-files/PrintGraphHelp.txt", type = OptionType.Debug)
 140     public static final EnumOptionKey<PrintGraphTarget> PrintGraph = new EnumOptionKey<>(PrintGraphTarget.File);
 141 
 142     @Option(help = "Setting to true sets PrintGraph=file, setting to false sets PrintGraph=network", type = OptionType.Debug)
 143     public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<Boolean>(true) {
 144         @Override
 145         protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
 146             PrintGraphTarget v = PrintGraph.getValueOrDefault(values);
 147             if (newValue.booleanValue()) {
 148                 if (v != PrintGraphTarget.File) {
 149                     PrintGraph.update(values, PrintGraphTarget.File);
 150                 }
 151             } else {
 152                 if (v != PrintGraphTarget.Network) {
 153                     PrintGraph.update(values, PrintGraphTarget.Network);
 154                 }
 155             }
 156         }
 157     };
 158 
 159     @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug)
 160     public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1");
 161     @Option(help = "Port part of the address to which graphs are dumped in binary format.", type = OptionType.Debug)
 162     public static final OptionKey<Integer> PrintGraphPort = new OptionKey<>(4445);
 163     @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug)
 164     public static final OptionKey<Boolean> PrintGraphWithSchedule = new OptionKey<>(false);
 165 
 166     @Option(help = "Enable dumping Truffle ASTs to the IdealGraphVisualizer.", type = OptionType.Debug)
 167     public static final OptionKey<Boolean> PrintTruffleTrees = new OptionKey<>(true);
 168 
 169     @Option(help = "Treat any exceptions during dumping as fatal.", type = OptionType.Debug)
 170     public static final OptionKey<Boolean> DumpingErrorsAreFatal = new OptionKey<>(false);
 171 
 172     @Option(help = "Enable dumping canonical text from for graphs.", type = OptionType.Debug)
 173     public static final OptionKey<Boolean> PrintCanonicalGraphStrings = new OptionKey<>(false);
 174     @Option(help = "Choose format used when dumping canonical text for graphs: " +
 175             "0 gives a scheduled graph (better for spotting changes involving the schedule) " +
 176             "while 1 gives a CFG containing expressions rooted at fixed nodes (better for spotting small structure differences)", type = OptionType.Debug)
 177     public static final OptionKey<Integer> PrintCanonicalGraphStringFlavor = new OptionKey<>(0);
 178     @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug)
 179     public static final OptionKey<Boolean> CanonicalGraphStringsExcludeVirtuals = new OptionKey<>(true);
 180     @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug)
 181     public static final OptionKey<Boolean> CanonicalGraphStringsCheckConstants = new OptionKey<>(false);
 182     @Option(help = "Attempts to remove object identity hashes when dumping canonical text for graphs.", type = OptionType.Debug)
 183     public static final OptionKey<Boolean> CanonicalGraphStringsRemoveIdentities = new OptionKey<>(true);
 184 
 185     @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug)
 186     public static final OptionKey<Boolean> ClearMetricsAfterBootstrap = new OptionKey<>(false);
 187     @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug)
 188     public static final OptionKey<Boolean> BootstrapInitializeOnly = new OptionKey<>(false);
 189 
 190     /**
 191      * Gets the directory in which {@link DebugDumpHandler}s can generate output. This will be the
 192      * directory specified by {@link #DumpPath} if it has been set otherwise it will be derived from
 193      * the default value of {@link #DumpPath} and {@link GraalServices#getGlobalTimeStamp()}.
 194      *
 195      * This method will ensure the returned directory exists, printing a message to {@link TTY} if
 196      * it creates it.
 197      *
 198      * @return a path as described above whose directories are guaranteed to exist
 199      * @throws IOException if there was an error in {@link Files#createDirectories}
 200      */
 201     public static Path getDumpDirectory(OptionValues options) throws IOException {
 202         Path dumpDir;
 203         if (DumpPath.hasBeenSet(options)) {
 204             dumpDir = Paths.get(DumpPath.getValue(options));
 205         } else {
 206             dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(GraalServices.getGlobalTimeStamp()));
 207         }
 208         dumpDir = dumpDir.toAbsolutePath();
 209         if (!Files.exists(dumpDir)) {
 210             synchronized (DebugConfigImpl.class) {
 211                 if (!Files.exists(dumpDir)) {
 212                     Files.createDirectories(dumpDir);
 213                     if (ShowDumpFiles.getValue(options)) {
 214                         TTY.println("Dumping debug output in %s", dumpDir.toString());
 215                     }
 216                 }
 217             }
 218         }
 219         return dumpDir;
 220     }
 221 }