< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java

Print this page




  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 static java.util.FormattableFlags.LEFT_JUSTIFY;
  26 import static java.util.FormattableFlags.UPPERCASE;
  27 import static org.graalvm.compiler.debug.DebugOptions.Count;
  28 import static org.graalvm.compiler.debug.DebugOptions.Counters;
  29 import static org.graalvm.compiler.debug.DebugOptions.Dump;
  30 import static org.graalvm.compiler.debug.DebugOptions.DumpOnError;
  31 import static org.graalvm.compiler.debug.DebugOptions.DumpOnPhaseChange;

  32 import static org.graalvm.compiler.debug.DebugOptions.ListMetrics;
  33 import static org.graalvm.compiler.debug.DebugOptions.Log;
  34 import static org.graalvm.compiler.debug.DebugOptions.MemUseTrackers;

  35 import static org.graalvm.compiler.debug.DebugOptions.Time;
  36 import static org.graalvm.compiler.debug.DebugOptions.Timers;
  37 import static org.graalvm.compiler.debug.DebugOptions.TrackMemUse;
  38 
  39 import java.io.ByteArrayOutputStream;
  40 import java.io.File;
  41 import java.io.IOException;
  42 import java.io.PrintStream;
  43 import java.nio.file.Files;
  44 import java.nio.file.Path;
  45 import java.nio.file.Paths;
  46 import java.nio.file.StandardOpenOption;
  47 import java.util.ArrayList;
  48 import java.util.Arrays;
  49 import java.util.Collection;
  50 import java.util.Collections;
  51 import java.util.Formatter;
  52 import java.util.List;
  53 import java.util.Map;
  54 import java.util.SortedMap;
  55 import java.util.TreeMap;
  56 
  57 import org.graalvm.compiler.options.OptionKey;
  58 import org.graalvm.compiler.options.OptionValues;

  59 import org.graalvm.util.EconomicMap;
  60 import org.graalvm.util.EconomicSet;
  61 import org.graalvm.util.Pair;
  62 
  63 import jdk.vm.ci.meta.JavaMethod;
  64 
  65 /**
  66  * A facility for logging and dumping as well as a container for values associated with
  67  * {@link MetricKey}s.
  68  *
  69  * A {@code DebugContext} object must only be used on the thread that created it. This means it
  70  * needs to be passed around as a parameter. For convenience, it can be encapsulated in a widely
  71  * used object that is in scope wherever a {@code DebugContext} is needed. However, care must be
  72  * taken when such objects can be exposed to multiple threads (e.g., they are in a non-thread-local
  73  * cache).
  74  */
  75 public final class DebugContext implements AutoCloseable {
  76 
  77     public static final Description NO_DESCRIPTION = null;
  78     public static final GlobalMetrics NO_GLOBAL_METRIC_VALUES = null;


  81     public static final PrintStream DEFAULT_LOG_STREAM = TTY.out;
  82 
  83     /**
  84      * Contains the immutable parts of a debug context. This separation allows the immutable parts
  85      * to be shared and reduces the overhead of initialization since most immutable fields are
  86      * configured by parsing options.
  87      */
  88     final Immutable immutable;
  89 
  90     /**
  91      * Determines whether metrics are enabled.
  92      */
  93     boolean metricsEnabled;
  94 
  95     DebugConfig currentConfig;
  96     ScopeImpl currentScope;
  97     CloseableCounter currentTimer;
  98     CloseableCounter currentMemUseTracker;
  99     Scope lastClosedScope;
 100     Throwable lastExceptionThrown;


 101 
 102     /**
 103      * Stores the {@link MetricKey} values.
 104      */
 105     private long[] metricValues;
 106 
 107     /**
 108      * Determines if dynamic scopes are enabled.
 109      */
 110     public boolean areScopesEnabled() {
 111         return immutable.scopesEnabled;
 112     }
 113 













 114     /**
 115      * The immutable configuration that can be shared between {@link DebugContext} objects.
 116      */
 117     static final class Immutable {
 118 
 119         private static final Immutable[] CACHE = new Immutable[5];
 120 
 121         /**
 122          * The options from which this object was configured.
 123          */
 124         final OptionValues options;
 125 
 126         /**
 127          * Specifies if dynamic scopes are enabled.
 128          */
 129         final boolean scopesEnabled;
 130 
 131         final boolean listMetrics;
 132 
 133         /**


 306         /**
 307          * The primary input to the computation.
 308          */
 309         final Object compilable;
 310 
 311         /**
 312          * A runtime based identifier that is most likely to be unique.
 313          */
 314         final String identifier;
 315 
 316         public Description(Object compilable, String identifier) {
 317             this.compilable = compilable;
 318             this.identifier = identifier;
 319         }
 320 
 321         @Override
 322         public String toString() {
 323             String compilableName = compilable instanceof JavaMethod ? ((JavaMethod) compilable).format("%H.%n(%p)%R") : String.valueOf(compilable);
 324             return identifier + ":" + compilableName;
 325         }








 326     }
 327 
 328     private final Description description;
 329 
 330     /**
 331      * Gets a description of the computation associated with this debug context.
 332      *
 333      * @return {@code null} if no description is available
 334      */
 335     public Description getDescription() {
 336         return description;
 337     }
 338 
 339     /**
 340      * Gets the global metrics associated with this debug context.
 341      *
 342      * @return {@code null} if no global metrics are available
 343      */
 344     public GlobalMetrics getGlobalMetrics() {
 345         return globalMetrics;


 377             List<DebugVerifyHandler> verifyHandlers = new ArrayList<>();
 378             for (DebugHandlersFactory factory : factories) {
 379                 for (DebugHandler handler : factory.createHandlers(options)) {
 380                     if (handler instanceof DebugDumpHandler) {
 381                         dumpHandlers.add((DebugDumpHandler) handler);
 382                     } else {
 383                         assert handler instanceof DebugVerifyHandler;
 384                         verifyHandlers.add((DebugVerifyHandler) handler);
 385                     }
 386                 }
 387             }
 388             currentConfig = new DebugConfigImpl(options, logStream, dumpHandlers, verifyHandlers);
 389             currentScope = new ScopeImpl(this, Thread.currentThread());
 390             currentScope.updateFlags(currentConfig);
 391             metricsEnabled = true;
 392         } else {
 393             metricsEnabled = immutable.hasUnscopedMetrics() || immutable.listMetrics;
 394         }
 395     }
 396 














 397     /**
 398      * A special dump level that indicates the dumping machinery is enabled but no dumps will be
 399      * produced except through other options.
 400      */
 401     public static final int ENABLED_LEVEL = 0;
 402 
 403     /**
 404      * Basic debug level.
 405      *
 406      * For HIR dumping, only ~5 graphs per method: after parsing, after inlining, after high tier,
 407      * after mid tier, after low tier.
 408      *
 409      * LIR dumping: After LIR generation, after each pre-allocation, allocation and post allocation
 410      * stage, and after code installation.
 411      */
 412     public static final int BASIC_LEVEL = 1;
 413 
 414     /**
 415      * Informational debug level.
 416      *


2025                         continue;
2026                     }
2027                     valueString = ms + "ms";
2028                 } else {
2029                     valueString = String.valueOf(value);
2030                 }
2031                 res.put(name, valueString);
2032                 maxKeyWidth = Math.max(maxKeyWidth, name.length());
2033             }
2034         }
2035 
2036         String title = String.format("%s [id:%s compilation:%d compilation_id:%s]", compilableName, identity, compilationNr, compilationId);
2037         out.println(new String(new char[title.length()]).replace('\0', '#'));
2038         out.printf("%s%n", title);
2039         out.println(new String(new char[title.length()]).replace('\0', '~'));
2040 
2041         for (Map.Entry<String, String> e : res.entrySet()) {
2042             out.printf("%-" + String.valueOf(maxKeyWidth) + "s = %20s%n", e.getKey(), e.getValue());
2043         }
2044         out.println();





2045     }
2046 }


  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 static java.util.FormattableFlags.LEFT_JUSTIFY;
  26 import static java.util.FormattableFlags.UPPERCASE;
  27 import static org.graalvm.compiler.debug.DebugOptions.Count;
  28 import static org.graalvm.compiler.debug.DebugOptions.Counters;
  29 import static org.graalvm.compiler.debug.DebugOptions.Dump;
  30 import static org.graalvm.compiler.debug.DebugOptions.DumpOnError;
  31 import static org.graalvm.compiler.debug.DebugOptions.DumpOnPhaseChange;
  32 import static org.graalvm.compiler.debug.DebugOptions.DumpPath;
  33 import static org.graalvm.compiler.debug.DebugOptions.ListMetrics;
  34 import static org.graalvm.compiler.debug.DebugOptions.Log;
  35 import static org.graalvm.compiler.debug.DebugOptions.MemUseTrackers;
  36 import static org.graalvm.compiler.debug.DebugOptions.ShowDumpFiles;
  37 import static org.graalvm.compiler.debug.DebugOptions.Time;
  38 import static org.graalvm.compiler.debug.DebugOptions.Timers;
  39 import static org.graalvm.compiler.debug.DebugOptions.TrackMemUse;
  40 
  41 import java.io.ByteArrayOutputStream;
  42 import java.io.File;
  43 import java.io.IOException;
  44 import java.io.PrintStream;
  45 import java.nio.file.Files;
  46 import java.nio.file.Path;
  47 import java.nio.file.Paths;
  48 import java.nio.file.StandardOpenOption;
  49 import java.util.ArrayList;
  50 import java.util.Arrays;
  51 import java.util.Collection;
  52 import java.util.Collections;
  53 import java.util.Formatter;
  54 import java.util.List;
  55 import java.util.Map;
  56 import java.util.SortedMap;
  57 import java.util.TreeMap;
  58 
  59 import org.graalvm.compiler.options.OptionKey;
  60 import org.graalvm.compiler.options.OptionValues;
  61 import org.graalvm.graphio.GraphOutput;
  62 import org.graalvm.util.EconomicMap;
  63 import org.graalvm.util.EconomicSet;
  64 import org.graalvm.util.Pair;
  65 
  66 import jdk.vm.ci.meta.JavaMethod;
  67 
  68 /**
  69  * A facility for logging and dumping as well as a container for values associated with
  70  * {@link MetricKey}s.
  71  *
  72  * A {@code DebugContext} object must only be used on the thread that created it. This means it
  73  * needs to be passed around as a parameter. For convenience, it can be encapsulated in a widely
  74  * used object that is in scope wherever a {@code DebugContext} is needed. However, care must be
  75  * taken when such objects can be exposed to multiple threads (e.g., they are in a non-thread-local
  76  * cache).
  77  */
  78 public final class DebugContext implements AutoCloseable {
  79 
  80     public static final Description NO_DESCRIPTION = null;
  81     public static final GlobalMetrics NO_GLOBAL_METRIC_VALUES = null;


  84     public static final PrintStream DEFAULT_LOG_STREAM = TTY.out;
  85 
  86     /**
  87      * Contains the immutable parts of a debug context. This separation allows the immutable parts
  88      * to be shared and reduces the overhead of initialization since most immutable fields are
  89      * configured by parsing options.
  90      */
  91     final Immutable immutable;
  92 
  93     /**
  94      * Determines whether metrics are enabled.
  95      */
  96     boolean metricsEnabled;
  97 
  98     DebugConfig currentConfig;
  99     ScopeImpl currentScope;
 100     CloseableCounter currentTimer;
 101     CloseableCounter currentMemUseTracker;
 102     Scope lastClosedScope;
 103     Throwable lastExceptionThrown;
 104     private IgvDumpChannel sharedChannel;
 105     private GraphOutput<?, ?> parentOutput;
 106 
 107     /**
 108      * Stores the {@link MetricKey} values.
 109      */
 110     private long[] metricValues;
 111 
 112     /**
 113      * Determines if dynamic scopes are enabled.
 114      */
 115     public boolean areScopesEnabled() {
 116         return immutable.scopesEnabled;
 117     }
 118 
 119     public <G, N, M> GraphOutput<G, M> buildOutput(GraphOutput.Builder<G, N, M> builder) throws IOException {
 120         if (parentOutput != null) {
 121             return builder.build(parentOutput);
 122         } else {
 123             if (sharedChannel == null) {
 124                 sharedChannel = new IgvDumpChannel(() -> getDumpPath(".bgv", false), immutable.options);
 125             }
 126             final GraphOutput<G, M> output = builder.build(sharedChannel);
 127             parentOutput = output;
 128             return output;
 129         }
 130     }
 131 
 132     /**
 133      * The immutable configuration that can be shared between {@link DebugContext} objects.
 134      */
 135     static final class Immutable {
 136 
 137         private static final Immutable[] CACHE = new Immutable[5];
 138 
 139         /**
 140          * The options from which this object was configured.
 141          */
 142         final OptionValues options;
 143 
 144         /**
 145          * Specifies if dynamic scopes are enabled.
 146          */
 147         final boolean scopesEnabled;
 148 
 149         final boolean listMetrics;
 150 
 151         /**


 324         /**
 325          * The primary input to the computation.
 326          */
 327         final Object compilable;
 328 
 329         /**
 330          * A runtime based identifier that is most likely to be unique.
 331          */
 332         final String identifier;
 333 
 334         public Description(Object compilable, String identifier) {
 335             this.compilable = compilable;
 336             this.identifier = identifier;
 337         }
 338 
 339         @Override
 340         public String toString() {
 341             String compilableName = compilable instanceof JavaMethod ? ((JavaMethod) compilable).format("%H.%n(%p)%R") : String.valueOf(compilable);
 342             return identifier + ":" + compilableName;
 343         }
 344 
 345         final String getLabel() {
 346             if (compilable instanceof JavaMethod) {
 347                 JavaMethod method = (JavaMethod) compilable;
 348                 return method.format("%h.%n(%p)%r");
 349             }
 350             return String.valueOf(compilable);
 351         }
 352     }
 353 
 354     private final Description description;
 355 
 356     /**
 357      * Gets a description of the computation associated with this debug context.
 358      *
 359      * @return {@code null} if no description is available
 360      */
 361     public Description getDescription() {
 362         return description;
 363     }
 364 
 365     /**
 366      * Gets the global metrics associated with this debug context.
 367      *
 368      * @return {@code null} if no global metrics are available
 369      */
 370     public GlobalMetrics getGlobalMetrics() {
 371         return globalMetrics;


 403             List<DebugVerifyHandler> verifyHandlers = new ArrayList<>();
 404             for (DebugHandlersFactory factory : factories) {
 405                 for (DebugHandler handler : factory.createHandlers(options)) {
 406                     if (handler instanceof DebugDumpHandler) {
 407                         dumpHandlers.add((DebugDumpHandler) handler);
 408                     } else {
 409                         assert handler instanceof DebugVerifyHandler;
 410                         verifyHandlers.add((DebugVerifyHandler) handler);
 411                     }
 412                 }
 413             }
 414             currentConfig = new DebugConfigImpl(options, logStream, dumpHandlers, verifyHandlers);
 415             currentScope = new ScopeImpl(this, Thread.currentThread());
 416             currentScope.updateFlags(currentConfig);
 417             metricsEnabled = true;
 418         } else {
 419             metricsEnabled = immutable.hasUnscopedMetrics() || immutable.listMetrics;
 420         }
 421     }
 422 
 423     public Path getDumpPath(String extension, boolean directory) {
 424         try {
 425             String id = description == null ? null : description.identifier;
 426             String label = description == null ? null : description.getLabel();
 427             Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, directory);
 428             if (ShowDumpFiles.getValue(immutable.options)) {
 429                 TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString());
 430             }
 431             return result;
 432         } catch (IOException ex) {
 433             throw rethrowSilently(RuntimeException.class, ex);
 434         }
 435     }
 436 
 437     /**
 438      * A special dump level that indicates the dumping machinery is enabled but no dumps will be
 439      * produced except through other options.
 440      */
 441     public static final int ENABLED_LEVEL = 0;
 442 
 443     /**
 444      * Basic debug level.
 445      *
 446      * For HIR dumping, only ~5 graphs per method: after parsing, after inlining, after high tier,
 447      * after mid tier, after low tier.
 448      *
 449      * LIR dumping: After LIR generation, after each pre-allocation, allocation and post allocation
 450      * stage, and after code installation.
 451      */
 452     public static final int BASIC_LEVEL = 1;
 453 
 454     /**
 455      * Informational debug level.
 456      *


2065                         continue;
2066                     }
2067                     valueString = ms + "ms";
2068                 } else {
2069                     valueString = String.valueOf(value);
2070                 }
2071                 res.put(name, valueString);
2072                 maxKeyWidth = Math.max(maxKeyWidth, name.length());
2073             }
2074         }
2075 
2076         String title = String.format("%s [id:%s compilation:%d compilation_id:%s]", compilableName, identity, compilationNr, compilationId);
2077         out.println(new String(new char[title.length()]).replace('\0', '#'));
2078         out.printf("%s%n", title);
2079         out.println(new String(new char[title.length()]).replace('\0', '~'));
2080 
2081         for (Map.Entry<String, String> e : res.entrySet()) {
2082             out.printf("%-" + String.valueOf(maxKeyWidth) + "s = %20s%n", e.getKey(), e.getValue());
2083         }
2084         out.println();
2085     }
2086 
2087     @SuppressWarnings({"unused", "unchecked"})
2088     private static <E extends Exception> E rethrowSilently(Class<E> type, Throwable ex) throws E {
2089         throw (E) ex;
2090     }
2091 }
< prev index next >