diff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleTool.java @ 18987:ac114ad31cdd

Truffle/Tools: a new framework for pluggable tools that gather Truffle execution data - Abstract com.oracle.truffle.api.instrument.TruffleTool defines, documents, and enforces a standard "life cycle": -- includes creation, installation, enabling/disabling, and disposing. -- data retrieval is tool dependent, but each is encouraged to provide a default print() method for demo & debugging - com.oracle.truffle.api.tools contains three instances, all language-agnostic: -- LineToProbesMap: existing utility used by the debugger, adapted to the frameowrk -- CoverageTracker: code coverage, tabulated by line -- NodeExecCounter: raw execution counts, tabulated by node type, can be filtered by SyntaxTag
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Tue, 27 Jan 2015 20:26:41 -0800
parents
children c7e57dffc5ad
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleTool.java	Tue Jan 27 20:26:41 2015 -0800
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.instrument;
+
+/**
+ * {@linkplain Instrument Instrumentation}-based tools that gather data during Guest Language
+ * program execution.
+ * <p>
+ * Tools share a common <em>life cycle</em>:
+ * <ul>
+ * <li>A newly created tool is inert until {@linkplain #install() installed}.</li>
+ * <li>An installed tool becomes <em>enabled</em> and immediately begins installing
+ * {@linkplain Instrument instrumentation} on subsequently created ASTs and collecting data from
+ * those instruments</li>
+ * <li>A tool may only be installed once.</li>
+ * <li>It should be possible to install multiple instances of a tool, possibly (but not necessarily)
+ * configured differently with respect to what data is being collected.</li>
+ * <li>Once installed, a tool can be {@linkplain #setEnabled(boolean) enabled and disabled}
+ * arbitrarily.</li>
+ * <li>A disabled tool:
+ * <ul>
+ * <li>Collects no data;</li>
+ * <li>Retains existing AST instrumentation;</li>
+ * <li>Continues to instrument newly created ASTs; and</li>
+ * <li>Retains previously collected data.</li>
+ * </ul>
+ * </li>
+ * <li>An installed tool may be {@linkplain #reset() reset} at any time, which leaves the tool
+ * installed but with all previously collected data removed.</li>
+ * <li>A {@linkplain #dispose() disposed} tool removes all instrumentation (but not
+ * {@linkplain Probe probes}) and becomes permanently disabled; previously collected data persists.</li>
+ * </ul>
+ * <p>
+ * Tool-specific methods that access data collected by the tool should:
+ * <ul>
+ * <li>Return modification-safe representations of the data; and</li>
+ * <li>Not change the state of the data.</li>
+ * </ul>
+ * <b>Note:</b><br>
+ * Tool installation is currently <em>global</em> to the Truffle Execution environment. When
+ * language-agnostic management of individual execution environments is added to the platform,
+ * installation will be (optionally) specific to a single execution environment.
+ */
+public abstract class TruffleTool {
+
+    private enum ToolState {
+        UNINSTALLED,
+        ENABLED_INSTALLED,
+        DISABLED_INSTALLED,
+        DISPOSED;
+    }
+
+    private ToolState toolState = ToolState.UNINSTALLED;
+
+    protected TruffleTool() {
+
+    }
+
+    /**
+     * Connect the tool to some part of the Truffle runtime, and enable data collection to start.
+     * Instrumentation will only be added to subsequently created ASTs.
+     *
+     * @throws IllegalStateException if the tool has previously been installed.
+     */
+    public final void install() {
+        if (toolState != ToolState.UNINSTALLED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has already been installed");
+        }
+        if (internalInstall()) {
+            toolState = ToolState.ENABLED_INSTALLED;
+        }
+    }
+
+    /**
+     * @return whether the tool is currently collecting data.
+     */
+    public final boolean isEnabled() {
+        return toolState == ToolState.ENABLED_INSTALLED;
+    }
+
+    /**
+     * Switches tool state between <em>enabled</em> (collecting data) and <em>disabled</em> (not
+     * collecting data, but keeping data already collected).
+     *
+     * @throws IllegalStateException if not yet installed or disposed.
+     */
+    public final void setEnabled(boolean isEnabled) {
+        if (toolState == ToolState.UNINSTALLED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " not yet installed");
+        }
+        if (toolState == ToolState.DISPOSED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has been disposed");
+        }
+        internalSetEnabled(isEnabled);
+        toolState = isEnabled ? ToolState.ENABLED_INSTALLED : ToolState.DISABLED_INSTALLED;
+    }
+
+    /**
+     * Clears any data already collected, but otherwise does not change the state of the tool.
+     *
+     * @throws IllegalStateException if not yet installed or disposed.
+     */
+    public final void reset() {
+        if (toolState == ToolState.UNINSTALLED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " not yet installed");
+        }
+        if (toolState == ToolState.DISPOSED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has been disposed");
+        }
+        internalReset();
+    }
+
+    /**
+     * Makes the tool permanently <em>disabled</em>, removes instrumentation, but keeps data already
+     * collected.
+     *
+     * @throws IllegalStateException if not yet installed or disposed.
+     */
+    public final void dispose() {
+        if (toolState == ToolState.UNINSTALLED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " not yet installed");
+        }
+        if (toolState == ToolState.DISPOSED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has been disposed");
+        }
+        internalDispose();
+        toolState = ToolState.DISPOSED;
+    }
+
+    /**
+     * @return whether the installation succeeded.
+     */
+    protected abstract boolean internalInstall();
+
+    /**
+     * No subclass action required.
+     * 
+     * @param isEnabled
+     */
+    protected void internalSetEnabled(boolean isEnabled) {
+    }
+
+    protected abstract void internalReset();
+
+    protected abstract void internalDispose();
+
+}