# HG changeset patch # User Erik Eckstein # Date 1377066547 -7200 # Node ID 423c53e2fa7ee870a53f41293243148775eed8ec # Parent 001c41b01d139e8b908c4bad0e36534d1133ece7# Parent d7d12ef788ba2aace913b5e5444119e224ba5858 Merge diff -r 001c41b01d13 -r 423c53e2fa7e graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Tue Aug 20 12:48:28 2013 -0700 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Wed Aug 21 08:29:07 2013 +0200 @@ -36,6 +36,10 @@ ENABLED = true; } + public static void disable() { + ENABLED = false; + } + public static boolean isEnabled() { return ENABLED; } @@ -158,12 +162,22 @@ } } + /** + * Prints an indented message to the current DebugLevel's logging stream if logging is enabled. + * + * @param msg The format string of the log message + * @param args The arguments referenced by the log message string + * @see Indent#log + */ public static void log(String msg, Object... args) { - if (ENABLED && DebugScope.getInstance().isLogEnabled()) { + if (ENABLED) { DebugScope.getInstance().log(msg, args); } } + /** + * The same as {@link #log}, but without line termination and without indentation. + */ public static void printf(String msg, Object... args) { if (ENABLED && DebugScope.getInstance().isLogEnabled()) { DebugScope.getInstance().printf(msg, args); @@ -176,6 +190,105 @@ } } + private static final class NoLogger implements Indent { + + @Override + public void log(String msg, Object... args) { + } + + @Override + public void setEnabled(boolean enabled) { + } + + @Override + public Indent indent() { + return this; + } + + @Override + public Indent logIndent(String msg, Object... args) { + return this; + } + + @Override + public Indent outdent() { + return this; + } + + } + + private static final NoLogger noLoggerInstance = new NoLogger(); + + /** + * Creates a new indentation level (by adding some spaces) based on the last used Indent of the + * current DebugScope. + * + * @return The new indentation level + * @see Indent#indent + */ + public static Indent indent() { + if (ENABLED) { + DebugScope scope = DebugScope.getInstance(); + return scope.pushIndentLogger(); + } + return noLoggerInstance; + } + + /** + * Creates a new indentation level based on the last used Indent of the current DebugScope and + * turns on/off logging. + * + * @param enabled If true, logging is enabled, otherwise disabled + * @return The new indentation level + */ + public static Indent indent(boolean enabled) { + if (ENABLED) { + Indent logger = DebugScope.getInstance().pushIndentLogger(); + logger.setEnabled(enabled); + return logger; + } + return noLoggerInstance; + } + + /** + * A convenience function which combines {@link #log} and {@link #indent()}. + * + * @param msg The format string of the log message + * @param args The arguments referenced by the log message string + * @return The new indentation level + * @see Indent#logIndent + */ + public static Indent logIndent(String msg, Object... args) { + if (ENABLED) { + DebugScope scope = DebugScope.getInstance(); + scope.log(msg, args); + return scope.pushIndentLogger(); + } + return noLoggerInstance; + } + + /** + * A convenience function which combines {@link #log} and {@link #indent(boolean)}. + * + * @param enabled If true, logging is enabled, otherwise disabled + * @param msg The format string of the log message + * @param args The arguments referenced by the log message string + * @return The new indentation level + */ + public static Indent logIndent(boolean enabled, String msg, Object... args) { + if (ENABLED) { + DebugScope scope = DebugScope.getInstance(); + boolean saveLogEnabled = scope.isLogEnabled(); + scope.setLogEnabled(enabled); + scope.log(msg, args); + scope.setLogEnabled(saveLogEnabled); + Indent indent = scope.pushIndentLogger(); + indent.setEnabled(enabled); + return indent; + } + return noLoggerInstance; + } + public static Iterable context() { if (ENABLED) { return DebugScope.getInstance().getCurrentContext(); diff -r 001c41b01d13 -r 423c53e2fa7e graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Indent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Indent.java Wed Aug 21 08:29:07 2013 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013, 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; + +/** + * Represents an indentation level for logging. + *

+ * Note that calling the logging/indent/outdent methods of this interface updates the last used + * Indent of the current DebugScope. If no instance of Indent is available (e.g. at the beginning of + * a method), then the corresponding static methods of the Debug class should be used. They perform + * logging and indentation based on the last used Indent of the current DebugScope. + *

+ * Example usage: + * + *

+ *      void method() {
+ *      
+ *          Indent in = Debug.logIndent("header message");
+ *          ...
+ *          in.log("message");
+ *          ...
+ *          Indent in2 = in.logIndent("sub-header message");
+ *          ...
+ *          {
+ *              in2.log("inner message");
+ *          }
+ *          ...
+ *          in.outdent();
+ *      }
+ * 
+ */ +public interface Indent { + + /** + * Prints an indented message to the DebugLevel's logging stream if logging is enabled. + * + * @param msg The format string of the log message + * @param args The arguments referenced by the log message string + * @see Debug#log + */ + void log(String msg, Object... args); + + /** + * Turns on/off logging for this indentation level. + * + * @param enabled If true, logging is enabled, otherwise disabled + */ + void setEnabled(boolean enabled); + + /** + * Creates a new indentation level (by adding some spaces). + * + * @return The new indentation level + * @see Debug#indent + */ + Indent indent(); + + /** + * A convenience function which combines {@link #log} and {@link #indent}. + * + * @param msg The format string of the log message + * @param args The arguments referenced by the log message string + * @return The new indentation level + * @see Debug#logIndent + */ + Indent logIndent(String msg, Object... args); + + /** + * Restores the previous indent level. Calling this method is important to restore the correct + * last used Indent in the current DebugScope. + * + * @return The indent level from which this Indent was created. + */ + Indent outdent(); +} diff -r 001c41b01d13 -r 423c53e2fa7e graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Tue Aug 20 12:48:28 2013 -0700 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Wed Aug 21 08:29:07 2013 +0200 @@ -30,13 +30,64 @@ public final class DebugScope { + private final class IndentImpl implements Indent { + + final String indent; + boolean enabled; + final IndentImpl parentIndent; + + IndentImpl(IndentImpl parentIndent, boolean enabled) { + this.parentIndent = parentIndent; + this.indent = (parentIndent == null ? "" : parentIndent.indent + " "); + this.enabled = enabled; + } + + @Override + public void log(String msg, Object... args) { + if (enabled) { + if (logScopeName) { + output.println(indent + "scope: " + qualifiedName); + logScopeName = false; + } + output.println(indent + String.format(msg, args)); + lastUsedIndent = this; + } + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + public Indent indent() { + lastUsedIndent = new IndentImpl(this, enabled); + return lastUsedIndent; + } + + @Override + public Indent logIndent(String msg, Object... args) { + log(msg, args); + return indent(); + } + + @Override + public Indent outdent() { + if (parentIndent != null) { + lastUsedIndent = parentIndent; + } + return lastUsedIndent; + } + } + private static ThreadLocal instanceTL = new ThreadLocal<>(); private static ThreadLocal configTL = new ThreadLocal<>(); private static ThreadLocal lastExceptionThrownTL = new ThreadLocal<>(); - private static ThreadLocal lastLogScope = new ThreadLocal<>(); private static DebugTimer scopeTime = Debug.timer("ScopeTime"); private final DebugScope parent; + private IndentImpl lastUsedIndent = null; + private boolean logScopeName = false; private Object[] context; @@ -45,7 +96,6 @@ private static final char SCOPE_SEP = '.'; - private boolean logEnabled; private boolean meterEnabled; private boolean timeEnabled; private boolean dumpEnabled; @@ -72,6 +122,17 @@ this.parent = parent; this.context = context; this.qualifiedName = qualifiedName; + if (parent != null) { + this.lastUsedIndent = new IndentImpl(parent.lastUsedIndent, parent.isLogEnabled()); + logScopeName = !parent.qualifiedName.equals(qualifiedName); + } else { + this.lastUsedIndent = new IndentImpl(null, false); + logScopeName = true; + } + + // Be pragmatic: provide a default log stream to prevent a crash if the stream is not + // set while logging + this.output = System.out; assert context != null; if (parent != null) { @@ -93,7 +154,11 @@ } public boolean isLogEnabled() { - return logEnabled; + return lastUsedIndent.enabled; + } + + public void setLogEnabled(boolean enabled) { + lastUsedIndent.setEnabled(enabled); } public boolean isMeterEnabled() { @@ -105,20 +170,14 @@ } public void log(String msg, Object... args) { - if (isLogEnabled()) { - if (lastLogScope.get() == null || !lastLogScope.get().qualifiedName.equals(this.qualifiedName)) { - output.println("scope: " + qualifiedName); - lastLogScope.set(this); - } - output.println(String.format(msg, args)); - } + lastUsedIndent.log(msg, args); } public void printf(String msg, Object... args) { if (isLogEnabled()) { - if (lastLogScope.get() == null || !lastLogScope.get().qualifiedName.equals(this.qualifiedName)) { + if (logScopeName) { output.println("scope: " + qualifiedName); - lastLogScope.set(this); + logScopeName = false; } output.printf(msg, args); } @@ -164,6 +223,7 @@ public T scope(String newName, Runnable runnable, Callable callable, boolean sandbox, DebugConfig sandboxConfig, Object[] newContext) { DebugScope oldContext = getInstance(); DebugConfig oldConfig = getConfig(); + boolean oldLogEnabled = oldContext.isLogEnabled(); DebugScope newChild = null; if (sandbox) { newChild = new DebugScope(newName, newName, null, newContext); @@ -173,12 +233,14 @@ } instanceTL.set(newChild); newChild.updateFlags(); + newChild.setLogEnabled(oldContext.isLogEnabled()); try (TimerCloseable a = scopeTime.start()) { return executeScope(runnable, callable); } finally { newChild.context = null; instanceTL.set(oldContext); setConfig(oldConfig); + setLogEnabled(oldLogEnabled); } } @@ -211,13 +273,14 @@ private void updateFlags() { DebugConfig config = getConfig(); if (config == null) { - logEnabled = false; meterEnabled = false; timeEnabled = false; dumpEnabled = false; - output = null; + + // Be pragmatic: provide a default log stream to prevent a crash if the stream is not + // set while logging + output = System.out; } else { - logEnabled = config.isLogEnabled(); meterEnabled = config.isMeterEnabled(); timeEnabled = config.isTimeEnabled(); dumpEnabled = config.isDumpEnabled(); @@ -321,9 +384,15 @@ public void setConfig(DebugConfig newConfig) { configTL.set(newConfig); updateFlags(); + setLogEnabled(newConfig != null && newConfig.isLogEnabled()); } public String getQualifiedName() { return qualifiedName; } + + public Indent pushIndentLogger() { + lastUsedIndent = (IndentImpl) lastUsedIndent.indent(); + return lastUsedIndent; + } }