changeset 16144:af9f3a5f091b

extended Debug API with DebugVerifyHandlers
author Doug Simon <doug.simon@oracle.com>
date Thu, 19 Jun 2014 11:24:16 +0200
parents 4f185700f4b7
children 237508bd73b9 8366c0c9e5c3
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugVerifyHandler.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java
diffstat 10 files changed, 244 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Thu Jun 19 00:45:04 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Thu Jun 19 11:24:16 2014 +0200
@@ -384,7 +384,7 @@
 
     public StructuredGraph visualize(StructuredGraph graph, String title) {
         DebugConfig debugConfig = DebugScope.getConfig();
-        DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, false, debugConfig.dumpHandlers(), debugConfig.output());
+        DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
         try (DebugConfigScope s = Debug.setConfig(fixedConfig)) {
             Debug.dump(graph, title);
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Thu Jun 19 00:45:04 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Thu Jun 19 11:24:16 2014 +0200
@@ -42,6 +42,8 @@
     public static final OptionValue<String> Dump = new OptionValue<>(null);
     @Option(help = "Pattern for scope(s) to in which metering is enabled (see DebugFilter and Debug.metric)")
     public static final OptionValue<String> Meter = new OptionValue<>(null);
+    @Option(help = "Pattern for scope(s) to in which verification is enabled (see DebugFilter and Debug.verify)")
+    public static final OptionValue<String> Verify = new OptionValue<>(null);
     @Option(help = "Pattern for scope(s) to in which memory use tracking is enabled (see DebugFilter and Debug.metric)")
     public static final OptionValue<String> TrackMemUse = new OptionValue<>(null);
     @Option(help = "Pattern for scope(s) to in which timing is enabled (see DebugFilter and Debug.timer)")
@@ -89,18 +91,21 @@
     private final DebugFilter trackMemUseFilter;
     private final DebugFilter timerFilter;
     private final DebugFilter dumpFilter;
+    private final DebugFilter verifyFilter;
     private final MethodFilter[] methodFilter;
     private final List<DebugDumpHandler> dumpHandlers;
+    private final List<DebugVerifyHandler> verifyHandlers;
     private final PrintStream output;
     private final Set<Object> extraFilters = new HashSet<>();
 
-    public GraalDebugConfig(String logFilter, String meterFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output,
-                    List<DebugDumpHandler> dumpHandlers) {
+    public GraalDebugConfig(String logFilter, String meterFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, PrintStream output,
+                    List<DebugDumpHandler> dumpHandlers, List<DebugVerifyHandler> verifyHandlers) {
         this.logFilter = DebugFilter.parse(logFilter);
         this.meterFilter = DebugFilter.parse(meterFilter);
         this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter);
         this.timerFilter = DebugFilter.parse(timerFilter);
         this.dumpFilter = DebugFilter.parse(dumpFilter);
+        this.verifyFilter = DebugFilter.parse(verifyFilter);
         if (methodFilter == null || methodFilter.isEmpty()) {
             this.methodFilter = null;
         } else {
@@ -112,6 +117,7 @@
             // TTY.println(Thread.currentThread().getName() + ": " + toString());
         }
         this.dumpHandlers = dumpHandlers;
+        this.verifyHandlers = verifyHandlers;
         this.output = output;
     }
 
@@ -127,10 +133,6 @@
         return isEnabled(meterFilter);
     }
 
-    public boolean isMetderEnabled() {
-        return isEnabled(meterFilter);
-    }
-
     public boolean isMemUseTrackingEnabled() {
         return isEnabled(trackMemUseFilter);
     }
@@ -143,6 +145,14 @@
         return isEnabledForMethod(dumpFilter);
     }
 
+    public boolean isVerifyEnabled() {
+        return isEnabled(verifyFilter);
+    }
+
+    public boolean isVerifyEnabledForMethod() {
+        return isEnabledForMethod(verifyFilter);
+    }
+
     public boolean isTimeEnabled() {
         return isEnabled(timerFilter);
     }
@@ -231,7 +241,7 @@
         if (e instanceof BailoutException) {
             return null;
         }
-        Debug.setConfig(Debug.fixedConfig(true, true, false, false, false, dumpHandlers, output));
+        Debug.setConfig(Debug.fixedConfig(true, true, false, false, false, false, dumpHandlers, verifyHandlers, output));
         Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope()));
         for (Object o : Debug.context()) {
             if (o instanceof Graph) {
@@ -269,6 +279,11 @@
     }
 
     @Override
+    public Collection<DebugVerifyHandler> verifyHandlers() {
+        return verifyHandlers;
+    }
+
+    @Override
     public void addToContext(Object o) {
         extraFilters.add(o);
     }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Thu Jun 19 00:45:04 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Thu Jun 19 11:24:16 2014 +0200
@@ -86,6 +86,33 @@
         return ENABLED && DebugScope.getInstance().isDumpEnabled();
     }
 
+    /**
+     * 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();
     }
@@ -460,6 +487,65 @@
     }
 
     /**
+     * Calls all {@link DebugVerifyHandler}s in the current {@linkplain DebugScope#getConfig()
+     * config} to perform verification on a given object.
+     *
+     * @param object the object to be verified
+     * @param msg denoting context of verification
+     */
+    public static void verify(Object object, String msg) {
+        if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) {
+            DebugScope.getInstance().verify(object, msg);
+        }
+    }
+
+    /**
+     * Calls all {@link DebugVerifyHandler}s in the current {@linkplain DebugScope#getConfig()
+     * config} to perform verification on a given object.
+     *
+     * @param object the object to be verified
+     * @param format format string for message denoting context of verification
+     * @param arg argument to format string
+     */
+    public static void verify(Object object, String format, Object arg) {
+        if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) {
+            DebugScope.getInstance().verify(object, format, arg);
+        }
+    }
+
+    /**
+     * @see Debug#verify(Object, String, Object)
+     */
+    public static void verify(Object object, String format, Object arg1, Object arg2) {
+        if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) {
+            DebugScope.getInstance().verify(object, format, arg1, arg2);
+        }
+    }
+
+    /**
+     * @see Debug#verify(Object, String, Object)
+     */
+    public static void verify(Object object, String format, Object arg1, Object arg2, Object arg3) {
+        if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) {
+            DebugScope.getInstance().verify(object, format, arg1, arg2, arg3);
+        }
+    }
+
+    /**
+     * This override exists to catch cases when {@link #verify(Object, String, Object)} is called
+     * with one argument bound to a varargs method parameter. It will bind to this method instead of
+     * the single arg variant and produce a deprecation warning instead of silently wrapping the
+     * Object[] inside of another Object[].
+     */
+    @Deprecated
+    public static void verify(Object object, String format, Object[] args) {
+        assert false : "shouldn't use this";
+        if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) {
+            DebugScope.getInstance().verify(object, format, args);
+        }
+    }
+
+    /**
      * Opens a new indentation level (by adding some spaces) based on the current indentation level.
      * This should be used in a {@linkplain Indent try-with-resources} pattern.
      *
@@ -773,11 +859,11 @@
     }
 
     public static DebugConfig silentConfig() {
-        return fixedConfig(false, false, false, false, false, Collections.<DebugDumpHandler> emptyList(), System.out);
+        return fixedConfig(false, false, false, false, false, false, Collections.<DebugDumpHandler> emptyList(), Collections.<DebugVerifyHandler> emptyList(), System.out);
     }
 
     public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isMemUseTrackingEnabled, final boolean isTimerEnabled,
-                    final Collection<DebugDumpHandler> dumpHandlers, final PrintStream output) {
+                    final boolean isVerifyEnabled, final Collection<DebugDumpHandler> dumpHandlers, final Collection<DebugVerifyHandler> verifyHandlers, final PrintStream output) {
         return new DebugConfig() {
 
             @Override
@@ -809,6 +895,15 @@
             }
 
             @Override
+            public boolean isVerifyEnabled() {
+                return isVerifyEnabled;
+            }
+
+            public boolean isVerifyEnabledForMethod() {
+                return isVerifyEnabled;
+            }
+
+            @Override
             public boolean isTimeEnabled() {
                 return isTimerEnabled;
             }
@@ -824,6 +919,11 @@
             }
 
             @Override
+            public Collection<DebugVerifyHandler> verifyHandlers() {
+                return verifyHandlers;
+            }
+
+            @Override
             public PrintStream output() {
                 return output;
             }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java	Thu Jun 19 00:45:04 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java	Thu Jun 19 11:24:16 2014 +0200
@@ -69,6 +69,16 @@
     boolean isDumpEnabledForMethod();
 
     /**
+     * @see Debug#isVerifyEnabled()
+     */
+    boolean isVerifyEnabled();
+
+    /**
+     * @see Debug#isVerifyEnabledForMethod()
+     */
+    boolean isVerifyEnabledForMethod();
+
+    /**
      * Adds an object the context used by this configuration to do filtering.
      */
     void addToContext(Object o);
@@ -94,9 +104,14 @@
     RuntimeException interceptException(Throwable e);
 
     /**
-     * Gets the modifiable collection dump handlers registered with this configuration.
+     * Gets the modifiable collection of dump handlers registered with this configuration.
      */
     Collection<DebugDumpHandler> dumpHandlers();
 
     PrintStream output();
+
+    /**
+     * Gets the modifiable collection of verify handlers registered with this configuration.
+     */
+    Collection<DebugVerifyHandler> verifyHandlers();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugVerifyHandler.java	Thu Jun 19 11:24:16 2014 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * Performs some kind of verification on an object.
+ */
+public interface DebugVerifyHandler {
+
+    /**
+     * Verifies that a given object satisfies some invariants.
+     */
+    void verify(Object object, String message);
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Thu Jun 19 00:45:04 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Thu Jun 19 11:24:16 2014 +0200
@@ -55,6 +55,14 @@
          */
         DUMP_METHOD,
         /**
+         * @see Debug#isVerifyEnabled()
+         */
+        VERIFY,
+        /**
+         * @see Debug#isVerifyEnabledForMethod()
+         */
+        VERIFY_METHOD,
+        /**
          * @see Debug#isMeterEnabled()
          */
         METER,
@@ -155,6 +163,23 @@
     }
 
     @Override
+    public boolean isVerifyEnabled() {
+        Boolean fs = featureState.get(Feature.VERIFY);
+        if (fs == null) {
+            return delegate.isVerifyEnabled();
+        }
+        return fs.booleanValue();
+    }
+
+    public boolean isVerifyEnabledForMethod() {
+        Boolean fs = featureState.get(Feature.VERIFY_METHOD);
+        if (fs == null) {
+            return delegate.isVerifyEnabledForMethod();
+        }
+        return fs.booleanValue();
+    }
+
+    @Override
     public boolean isTimeEnabled() {
         Boolean fs = featureState.get(Feature.TIME);
         if (fs == null) {
@@ -178,6 +203,11 @@
     }
 
     @Override
+    public Collection<DebugVerifyHandler> verifyHandlers() {
+        return delegate.verifyHandlers();
+    }
+
+    @Override
     public PrintStream output() {
         return delegate.output();
     }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Thu Jun 19 00:45:04 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Thu Jun 19 11:24:16 2014 +0200
@@ -95,6 +95,7 @@
     private boolean timeEnabled;
     private boolean memUseTrackingEnabled;
     private boolean dumpEnabled;
+    private boolean verifyEnabled;
     private boolean logEnabled;
 
     private PrintStream output;
@@ -158,6 +159,10 @@
         return dumpEnabled;
     }
 
+    public boolean isVerifyEnabled() {
+        return verifyEnabled;
+    }
+
     public boolean isLogEnabled() {
         return logEnabled;
     }
@@ -213,6 +218,21 @@
     }
 
     /**
+     * @see Debug#verify(Object, String, Object)
+     */
+    public void verify(Object object, String formatString, Object... args) {
+        if (isVerifyEnabled()) {
+            DebugConfig config = getConfig();
+            if (config != null) {
+                String message = String.format(formatString, args);
+                for (DebugVerifyHandler handler : config.verifyHandlers()) {
+                    handler.verify(object, message);
+                }
+            }
+        }
+    }
+
+    /**
      * Creates and enters a new debug scope which is either a child of the current scope or a
      * disjoint top level scope.
      *
@@ -269,6 +289,7 @@
             memUseTrackingEnabled = false;
             timeEnabled = false;
             dumpEnabled = false;
+            verifyEnabled = false;
 
             // Be pragmatic: provide a default log stream to prevent a crash if the stream is not
             // set while logging
@@ -278,6 +299,7 @@
             memUseTrackingEnabled = config.isMemUseTrackingEnabled();
             timeEnabled = config.isTimeEnabled();
             dumpEnabled = config.isDumpEnabled();
+            verifyEnabled = config.isVerifyEnabled();
             logEnabled = config.isLogEnabled();
             output = config.output();
         }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Thu Jun 19 00:45:04 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Thu Jun 19 11:24:16 2014 +0200
@@ -692,7 +692,7 @@
             };
 
             DebugConfig debugConfig = DebugScope.getConfig();
-            DebugConfig fixedConfig = Debug.fixedConfig(false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.output());
+            DebugConfig fixedConfig = Debug.fixedConfig(false, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
             try (DebugConfigScope s = Debug.setConfig(fixedConfig)) {
                 ReentrantNodeIterator.apply(closure, graph.start(), false);
                 new WriteBarrierVerificationPhase().apply(graph);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Jun 19 00:45:04 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Jun 19 11:24:16 2014 +0200
@@ -123,9 +123,9 @@
 
         TTY.initialize(Options.LogFile.getStream());
 
-        if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null) {
+        if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null && Verify.getValue() == null) {
             if (MethodFilter.getValue() != null) {
-                TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time and Dump options are all null");
+                TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, Dump and Verify options are all null");
             }
         }
 
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Thu Jun 19 00:45:04 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Thu Jun 19 11:24:16 2014 +0200
@@ -34,6 +34,13 @@
 
 public class DebugEnvironment {
 
+    @SuppressWarnings("all")
+    private static boolean assertionsEnabled() {
+        boolean assertionsEnabled = false;
+        assert assertionsEnabled = true;
+        return assertionsEnabled;
+    }
+
     public static GraalDebugConfig initialize(PrintStream log) {
 
         // Ensure Graal runtime is initialized prior to Debug being initialized as the former
@@ -55,7 +62,13 @@
         if (DecompileAfterPhase.getValue() != null) {
             dumpHandlers.add(new DecompilerDebugDumpHandler());
         }
-        GraalDebugConfig debugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), TrackMemUse.getValue(), Time.getValue(), Dump.getValue(), MethodFilter.getValue(), log, dumpHandlers);
+        List<DebugVerifyHandler> verifyHandlers = new ArrayList<>();
+        String verifyFilter = Verify.getValue();
+        if (verifyFilter == null && assertionsEnabled()) {
+            verifyFilter = "";
+        }
+        GraalDebugConfig debugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), TrackMemUse.getValue(), Time.getValue(), Dump.getValue(), verifyFilter, MethodFilter.getValue(), log,
+                        dumpHandlers, verifyHandlers);
         Debug.setConfig(debugConfig);
         return debugConfig;
     }