changeset 22231:59e022cee529

Truffle/Instrumentation: rename InstrumentationTool (abstract parent for CoverageTracker, LineToProbesMap, etc.) to Instrumenter.Tool, eliminating the need for an Accessor instance.
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Sun, 20 Sep 2015 17:19:59 -0700
parents 3f2052afcb6d
children 526de3af756d
files truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineToProbesMap.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationTool.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/LineToProbesMap.java truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java
diffstat 8 files changed, 179 insertions(+), 225 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineToProbesMap.java	Sun Sep 20 16:48:50 2015 -0700
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineToProbesMap.java	Sun Sep 20 17:19:59 2015 -0700
@@ -31,7 +31,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import com.oracle.truffle.api.instrument.InstrumentationTool;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.Probe;
 import com.oracle.truffle.api.instrument.ProbeListener;
@@ -44,7 +43,7 @@
  * An {@link InstrumentationTool} that builds a map of every {@link Probe} attached to some AST,
  * indexed by {@link Source} and line number.
  */
-final class LineToProbesMap extends InstrumentationTool {
+final class LineToProbesMap extends Instrumenter.Tool {
 
     private static final boolean TRACE = false;
     private static final PrintStream OUT = System.out;
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Sun Sep 20 16:48:50 2015 -0700
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Sun Sep 20 17:19:59 2015 -0700
@@ -61,7 +61,6 @@
     private static Accessor NODES;
     private static Accessor INTEROP;
     private static Accessor INSTRUMENT;
-    private static Accessor TOOL;
     private static Accessor DEBUG;
     private static final ThreadLocal<Object> CURRENT_VM = new ThreadLocal<>();
 
@@ -178,11 +177,6 @@
                 throw new IllegalStateException();
             }
             DEBUG = this;
-        } else if (this.getClass().getSimpleName().endsWith("Tool")) {
-            if (TOOL != null) {
-                throw new IllegalStateException();
-            }
-            TOOL = this;
         } else {
             if (SPI != null) {
                 throw new IllegalStateException();
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationTool.java	Sun Sep 20 16:48:50 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
-/*
- * 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;
-
-import com.oracle.truffle.api.impl.Accessor;
-
-/**
- * {@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(Instrumenter) 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 InstrumentationTool {
-    // TODO (mlvdv) still thinking about the most appropriate name for this class of tools
-
-    private enum ToolState {
-
-        /** Not yet installed, inert. */
-        UNINSTALLED,
-
-        /** Installed, collecting data. */
-        ENABLED,
-
-        /** Installed, not collecting data. */
-        DISABLED,
-
-        /** Was installed, but now removed, inactive, and no longer usable. */
-        DISPOSED;
-    }
-
-    private ToolState toolState = ToolState.UNINSTALLED;
-
-    private Instrumenter instrumenter;
-
-    protected InstrumentationTool() {
-    }
-
-    /**
-     * 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(Instrumenter inst) {
-        checkUninstalled();
-        if (inst != null) {
-            this.instrumenter = inst;
-        }
-        if (internalInstall()) {
-            toolState = ToolState.ENABLED;
-        }
-    }
-
-    /**
-     * @return whether the tool is currently collecting data.
-     */
-    public final boolean isEnabled() {
-        return toolState == ToolState.ENABLED;
-    }
-
-    /**
-     * 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) {
-        checkInstalled();
-        internalSetEnabled(isEnabled);
-        toolState = isEnabled ? ToolState.ENABLED : ToolState.DISABLED;
-    }
-
-    /**
-     * 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() {
-        checkInstalled();
-        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() {
-        checkInstalled();
-        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();
-
-    protected final Instrumenter getInstrumenter() {
-        if (instrumenter == null) {
-            instrumenter = ACCESSOR.getInstrumenter(null);
-        }
-        return instrumenter;
-    }
-
-    /**
-     * Ensure that the tool is currently installed.
-     *
-     * @throws IllegalStateException
-     */
-    private void checkInstalled() throws IllegalStateException {
-        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");
-        }
-    }
-
-    /**
-     * Ensure that the tool has not yet been installed.
-     *
-     * @throws IllegalStateException
-     */
-    private void checkUninstalled() {
-        if (toolState != ToolState.UNINSTALLED) {
-            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has already been installed");
-        }
-    }
-
-    static final class AccessorTool extends Accessor {
-
-        @Override
-        protected Instrumenter getInstrumenter(Object vm) {
-            return super.getInstrumenter(null);
-        }
-    }
-
-    static final AccessorTool ACCESSOR = new AccessorTool();
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java	Sun Sep 20 16:48:50 2015 -0700
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java	Sun Sep 20 17:19:59 2015 -0700
@@ -67,8 +67,181 @@
         return visitor.source;
     }
 
+    private enum ToolState {
+
+        /** Not yet installed, inert. */
+        UNINSTALLED,
+
+        /** Installed, collecting data. */
+        ENABLED,
+
+        /** Installed, not collecting data. */
+        DISABLED,
+
+        /** Was installed, but now removed, inactive, and no longer usable. */
+        DISPOSED;
+    }
+
+    /**
+     * {@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(Instrumenter) 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 static class Tool {
+        // TODO (mlvdv) still thinking about the most appropriate name for this class of tools
+
+        private ToolState toolState = ToolState.UNINSTALLED;
+
+        private Instrumenter instrumenter;
+
+        protected Tool() {
+        }
+
+        /**
+         * 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(Instrumenter inst) {
+            checkUninstalled();
+            this.instrumenter = inst;
+
+            if (internalInstall()) {
+                toolState = ToolState.ENABLED;
+            }
+            instrumenter.tools.add(this);
+        }
+
+        /**
+         * @return whether the tool is currently collecting data.
+         */
+        public final boolean isEnabled() {
+            return toolState == ToolState.ENABLED;
+        }
+
+        /**
+         * 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) {
+            checkInstalled();
+            internalSetEnabled(isEnabled);
+            toolState = isEnabled ? ToolState.ENABLED : ToolState.DISABLED;
+        }
+
+        /**
+         * 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() {
+            checkInstalled();
+            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() {
+            checkInstalled();
+            internalDispose();
+            toolState = ToolState.DISPOSED;
+            instrumenter.tools.remove(this);
+        }
+
+        /**
+         * @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();
+
+        protected final Instrumenter getInstrumenter() {
+            return instrumenter;
+        }
+
+        /**
+         * Ensure that the tool is currently installed.
+         *
+         * @throws IllegalStateException
+         */
+        private void checkInstalled() throws IllegalStateException {
+            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");
+            }
+        }
+
+        /**
+         * Ensure that the tool has not yet been installed.
+         *
+         * @throws IllegalStateException
+         */
+        private void checkUninstalled() {
+            if (toolState != ToolState.UNINSTALLED) {
+                throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has already been installed");
+            }
+        }
+    }
+
     private final Object vm;
 
+    /** Tools that have been created, but not yet disposed. */
+    private final Set<Tool> tools = Collections.synchronizedSet(new LinkedHashSet<Tool>());
+
     private final Set<ASTProber> astProbers = Collections.synchronizedSet(new LinkedHashSet<ASTProber>());
 
     private final List<ProbeListener> probeListeners = new ArrayList<>();
@@ -395,6 +568,7 @@
         return afterTagTrap;
     }
 
+    // TODO (mlvdv) build this in as a VM event?
     /**
      * Enables instrumentation in a newly created AST by applying all registered instances of
      * {@link ASTProber}.
--- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java	Sun Sep 20 16:48:50 2015 -0700
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java	Sun Sep 20 17:19:59 2015 -0700
@@ -31,7 +31,6 @@
 
 import org.junit.Test;
 
-import com.oracle.truffle.api.instrument.InstrumentationTool;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.vm.TruffleVM;
 
@@ -131,7 +130,7 @@
         return instrumenter;
     }
 
-    private static final class DummyTruffleTool extends InstrumentationTool {
+    private static final class DummyTruffleTool extends Instrumenter.Tool {
 
         @Override
         protected boolean internalInstall() {
--- a/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java	Sun Sep 20 16:48:50 2015 -0700
+++ b/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java	Sun Sep 20 17:19:59 2015 -0700
@@ -34,7 +34,6 @@
 import java.util.TreeSet;
 
 import com.oracle.truffle.api.instrument.Instrument;
-import com.oracle.truffle.api.instrument.InstrumentationTool;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.Probe;
 import com.oracle.truffle.api.instrument.ProbeListener;
@@ -83,7 +82,7 @@
  * @see Instrument
  * @see SyntaxTag
  */
-public final class CoverageTracker extends InstrumentationTool {
+public final class CoverageTracker extends Instrumenter.Tool {
 
     /** Counting data. */
     private final Map<LineLocation, CoverageRecord> coverageMap = new HashMap<>();
--- a/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/LineToProbesMap.java	Sun Sep 20 16:48:50 2015 -0700
+++ b/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/LineToProbesMap.java	Sun Sep 20 17:19:59 2015 -0700
@@ -31,7 +31,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import com.oracle.truffle.api.instrument.InstrumentationTool;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.Probe;
 import com.oracle.truffle.api.instrument.ProbeListener;
@@ -44,7 +43,7 @@
  * An {@link InstrumentationTool} that builds a map of every {@link Probe} attached to some AST,
  * indexed by {@link Source} and line number.
  */
-public final class LineToProbesMap extends InstrumentationTool {
+public final class LineToProbesMap extends Instrumenter.Tool {
 
     private static final boolean TRACE = false;
     private static final PrintStream OUT = System.out;
--- a/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java	Sun Sep 20 16:48:50 2015 -0700
+++ b/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java	Sun Sep 20 17:19:59 2015 -0700
@@ -38,7 +38,6 @@
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.instrument.ASTProber;
 import com.oracle.truffle.api.instrument.Instrument;
-import com.oracle.truffle.api.instrument.InstrumentationTool;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.Probe;
 import com.oracle.truffle.api.instrument.ProbeException;
@@ -97,7 +96,7 @@
  * @see SyntaxTag
  * @see ProbeFailure
  */
-public final class NodeExecCounter extends InstrumentationTool {
+public final class NodeExecCounter extends Instrumenter.Tool {
 
     /**
      * Execution count for AST nodes of a particular type.