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