gt:         if (ENABLED) {
context: /*
   * Copyright (c) 2012, 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 com.oracle.graal.debug;
  
  import static com.oracle.graal.debug.Debug.Initialization.*;
  import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
  import static java.util.FormattableFlags.*;
  
  import java.io.*;
  import java.util.*;
  import java.util.concurrent.*;
  
  import com.oracle.graal.debug.DelegatingDebugConfig.Level;
  import com.oracle.graal.debug.internal.*;
  
  /**
   * Scope based debugging facility. This facility is {@link #isEnabled()} if assertions are enabled
   * for the {@link Debug} class or the {@value Initialization#INITIALIZER_PROPERTY_NAME} system
   * property is {@code "true"} when {@link Debug} is initialized.
   */
  public class Debug {
  
      /**
       * Class to assist with initialization of {@link Debug}.
       */
      public static class Initialization {
  
          public static final String INITIALIZER_PROPERTY_NAME = "graal.debug.enable";
  
          private static boolean initialized;
  
          /**
           * Determines if {@link Debug} has been initialized.
           */
          public static boolean isDebugInitialized() {
              return initialized;
          }
  
      }
  
      @SuppressWarnings("all")
      private static boolean initialize() {
          boolean assertionsEnabled = false;
          assert assertionsEnabled = true;
          Initialization.initialized = true;
          return assertionsEnabled || Boolean.getBoolean(INITIALIZER_PROPERTY_NAME);
      }
  
      private static final boolean ENABLED = initialize();
  
      public static boolean isEnabled() {
          return ENABLED;
      }
  
      public static boolean isDumpEnabledForMethod() {
          if (!ENABLED) {
              return false;
          }
          DebugConfig config = DebugScope.getConfig();
          if (config == null) {
              return false;
          }
          return config.isDumpEnabledForMethod();
      }
  
      public static final int DEFAULT_LOG_LEVEL = 2;
  
      public static boolean isDumpEnabled() {
          return isDumpEnabled(DEFAULT_LOG_LEVEL);
      }
  
      public static boolean isDumpEnabled(int dumpLevel) {
          return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel);
      }
  
      /**
       * Determines if verification is enabled in the current method, regardless of the
       * {@linkplain Debug#currentScope() current debug scope}.
       *
       * @see Debug#verify(Object, String)
       */
      public static boolean isVerifyEnabledForMethod() {
          if (!ENABLED) {
              return false;
          }
          DebugConfig config = DebugScope.getConfig();
          if (config == null) {
              return false;
          }
          return config.isVerifyEnabledForMethod();
      }
  
      /**
       * Determines if verification is enabled in the {@linkplain Debug#currentScope() current debug
       * scope}.
       *
       * @see Debug#verify(Object, String)
       */
      public static boolean isVerifyEnabled() {
          return ENABLED && DebugScope.getInstance().isVerifyEnabled();
      }
  
      public static boolean isMeterEnabled() {
          return ENABLED && DebugScope.getInstance().isMeterEnabled();
      }
  
      public static boolean isTimeEnabled() {
          return ENABLED && DebugScope.getInstance().isTimeEnabled();
      }
  
      public static boolean isMemUseTrackingEnabled() {
          return ENABLED && DebugScope.getInstance().isMemUseTrackingEnabled();
      }
  
      public static boolean isLogEnabledForMethod() {
          if (!ENABLED) {
              return false;
          }
          DebugConfig config = DebugScope.getConfig();
          if (config == null) {
              return false;
          }
          return config.isLogEnabledForMethod();
      }
  
      public static boolean isLogEnabled() {
          return isLogEnabled(DEFAULT_LOG_LEVEL);
      }
  
      public static boolean isLogEnabled(int logLevel) {
          return ENABLED && DebugScope.getInstance().isLogEnabled(logLevel);
      }
  
      @SuppressWarnings("unused")
      public static Runnable decorateDebugRoot(Runnable runnable, String name, DebugConfig config) {
          return runnable;
      }
  
      @SuppressWarnings("unused")
      public static <T> Callable<T> decorateDebugRoot(Callable<T> callable, String name, DebugConfig config) {
          return callable;
      }
  
      @SuppressWarnings("unused")
      public static Runnable decorateScope(Runnable runnable, String name, Object... context) {
          return runnable;
      }
  
      @SuppressWarnings("unused")
      public static <T> Callable<T> decorateScope(Callable<T> callable, String name, Object... context) {
          return callable;
      }
  
      /**
       * Gets a string composed of the names in the current nesting of debug
       * {@linkplain #scope(Object) scopes} separated by {@code '.'}.
       */
      public static String currentScope() {
          if (ENABLED) {
              return DebugScope.getInstance().getQualifiedName();
          } else {
              return "";
          }
      }
  
      /**
       * Represents a debug scope entered by {@link Debug#scope(Object)} or
       * {@link Debug#sandbox(CharSequence, DebugConfig, Object...)}. Leaving the scope is achieved
       * via {@link #close()}.
       */
      public interface Scope extends AutoCloseable {
          void close();
      }
  
      /**
       * Creates and enters a new debug scope which will be a child of the current debug scope.
       * <p>
       * It is recommended to use the try-with-resource statement for managing entering and leaving
       * debug scopes. For example:
       *
       * <pre>
       * try (Scope s = Debug.scope(&quot;InliningGraph&quot;, inlineeGraph)) {
       *     ...
       * } catch (Throwable e) {
       *     throw Debug.handle(e);
       * }
       * </pre>
       *
       * The {@code name} argument is subject to the following type based conversion before having
       * {@link Object#toString()} called on it:
       *
       * <pre>
       *     Type          | Conversion
       * ------------------+-----------------
       *  java.lang.Class  | arg.getSimpleName()
       *                   |
       * </pre>
       *
       * @param name the name of the new scope
       * @param contextObjects an array of object to be appended to the {@linkplain #context()
       *            current} debug context
       * @throws Throwable used to enforce a catch block.
       * @return the scope entered by this method which will be exited when its {@link Scope#close()}
       *         method is called
       */
      public static Scope scope(Object name, Object[] contextObjects) throws Throwable {
          if (ENABLED) {
              return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, contextObjects);
          } else {
              return null;
          }
      }
  
      /**
       * Similar to {@link #scope(Object, Object[])} but without context objects. Therefore the catch
       * block can be omitted.
       *
       * @see #scope(Object, Object[])
       */
      public static Scope scope(Object name) {
          if (ENABLED) {
              return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null);
          } else {
              return null;
          }
      }
  
      /**
       * @see #scope(Object, Object[])
       * @param context an object to be appended to the {@linkplain #context() current} debug context
       */
      public static Scope scope(Object name, Object context) throws Throwable {
          if (ENABLED) {
              return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context);
          } else {
              return null;
          }
      }
  
      /**
       * @see #scope(Object, Object[])
       * @param context1 first object to be appended to the {@linkplain #context() current} debug
       *            context
       * @param context2 second object to be appended to the {@linkplain #context() current} debug
       *            context
       */
      public static Scope scope(Object name, Object context1, Object context2) throws Throwable {
          if (ENABLED) {
              return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2);
          } else {
              return null;
          }
      }
  
      /**
       * @see #scope(Object, Object[])
       * @param context1 first object to be appended to the {@linkplain #context() current} debug
       *            context
       * @param context2 second object to be appended to the {@linkplain #context() current} debug
       *            context
       * @param context3 third object to be appended to the {@linkplain #context() current} debug
       *            context
       */
      public static Scope scope(Object name, Object context1, Object context2, Object context3) throws Throwable {
          if (ENABLED) {
              return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2, context3);
          } else {
              return null;
          }
      }
  
      /**
       * Creates and enters a new debug scope which will be disjoint from the current debug scope.
       * <p>
       * It is recommended to use the try-with-resource statement for managing entering and leaving
       * debug scopes. For example:
       *
       * <pre>
       * try (Scope s = Debug.sandbox(&quot;CompilingStub&quot;, null, stubGraph)) {
       *     ...
       * } catch (Throwable e) {
       *     throw Debug.handle(e);
       * }
       * </pre>
       *
       * @param name the name of the new scope
       * @param config the debug configuration to use for the new scope
       * @param context objects to be appended to the {@linkplain #context() current} debug context
       * @return the scope entered by this method which will be exited when its {@link Scope#close()}
       *         method is called
       */
      public static Scope sandbox(CharSequence name, DebugConfig config, Object... context) throws Throwable {
          if (ENABLED) {
              DebugConfig sandboxConfig = config == null ? silentConfig() : config;
              return DebugScope.getInstance().scope(name, sandboxConfig, context);
          } else {
              return null;
          }
      }
  
      public static Scope forceLog() throws Throwable {
          ArrayList<Object> context = new ArrayList<>();
          for (Object obj : context()) {
              context.add(obj);
          }
          return Debug.sandbox("forceLog", new DelegatingDebugConfig().override(Level.LOG, Integer.MAX_VALUE).enable(LOG_METHOD), context.toArray());
      }
  
      /**
       * Opens a scope in which exception {@linkplain DebugConfig#interceptException(Throwable)
       * interception} is disabled. It is recommended to use the try-with-resource statement for
       * managing entering and leaving such scopes:
       *
       * <pre>
       * try (DebugConfigScope s = Debug.disableIntercept()) {
       *     ...
       * }
       * </pre>
       *
       * This is particularly useful to suppress extraneous output in JUnit tests that are expected to
       * throw an exception.
       */
      public static DebugConfigScope disableIntercept() {
          return Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT));
      }
  
      /**
       * Handles an exception in the context of the debug scope just exited. The just exited scope
       * must have the current scope as its parent which will be the case if the try-with-resource
       * pattern recommended by {@link #scope(Object)} and
       * {@link #sandbox(CharSequence, DebugConfig, Object...)} is used
       *
       * @see #scope(Object, Object[])
       * @see #sandbox(CharSequence, DebugConfig, Object...)
       */
      public static RuntimeException handle(Throwable exception) {
          if (ENABLED) {
              return DebugScope.getInstance().handle(exception);
          } else {
              if (exception instanceof Error) {
                  throw (Error) exception;
              }
              if (exception instanceof RuntimeException) {
                  throw (RuntimeException) exception;
              }
              throw new RuntimeException(exception);
          }
      }
  
      public static void log(String msg) {
          log(DEFAULT_LOG_LEVEL, msg);
      }
  
      /**
       * Prints a message to the current debug scope's logging stream if logging is enabled.
       *
       * @param msg the message to log
       */
      public static void log(int logLevel, String msg) {
          if (ENABLED) {
              DebugScope.getInstance().log(logLevel, msg);
          }
      }
  
      public static void log(String format, Object arg) {
          log(DEFAULT_LOG_LEVEL, format, arg);
      }
  
      /**
       * Prints a message to the current debug scope's logging stream if logging is enabled.
       *
       * @param format a format string
       * @param arg the argument referenced by the format specifiers in {@code format}
       */
      public static void log(int logLevel, String format, Object arg) {
          if (ENABLED) {
              DebugScope.getInstance().log(logLevel, format, arg);
          }
      }
  
      public static void log(String format, Object arg1, Object arg2) {
          log(DEFAULT_LOG_LEVEL, format, arg1, arg2);
      }
  
      /**
       * @see #log(int, String, Object)
       */
      public static void log(int logLevel, String format, Object arg1, Object arg2) {
          if (ENABLED) {
              DebugScope.getInstance().log(logLevel, format, arg1, arg2);
          }
      }
  
      public static void log(String format, Object arg1, Object arg2, Object arg3) {
          log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3);
      }
  
      /**
       * @see #log(int, String, Object)
       */
      public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3) {
  