# HG changeset patch # User Michael Van De Vanter # Date 1443218315 25200 # Node ID e7643754d982888fe1dfbd7a6ec21001638050e8 # Parent 7ec5eef84ecfbcaaaec4e0129711e9aa58b44243 Truffle/Instrumentation: rename Instrument to ProbeInstrument to distinguish from another kind to be added. diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Fri Sep 25 14:58:35 2015 -0700 @@ -33,7 +33,7 @@ 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.ProbeInstrument; import com.oracle.truffle.api.instrument.Instrumenter; import com.oracle.truffle.api.instrument.Probe; import com.oracle.truffle.api.instrument.SimpleInstrumentListener; @@ -58,7 +58,7 @@ * * Instrumentation allows the insertion into Truffle ASTs language-specific instances of * {@link WrapperNode} that propagate execution events through a {@link Probe} to any instances of - * {@link Instrument} that might be attached to the particular probe by tools. + * {@link ProbeInstrument} that might be attached to the particular probe by tools. */ public class InstrumentationTest { @@ -210,7 +210,7 @@ public int enterCount = 0; public int leaveCount = 0; public Instrumenter instrumenter; - private Instrument instrument; + private ProbeInstrument instrument; public TestSimpleInstrumentCounter(Instrumenter instrumenter) { this.instrumenter = instrumenter; @@ -263,7 +263,7 @@ public int enterCount = 0; public int leaveCount = 0; public final Instrumenter instrumenter; - public Instrument instrument; + public ProbeInstrument instrument; public TestStandardInstrumentCounter(Instrumenter instrumenter) { this.instrumenter = instrumenter; diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Breakpoint.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Breakpoint.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Breakpoint.java Fri Sep 25 14:58:35 2015 -0700 @@ -24,10 +24,12 @@ */ package com.oracle.truffle.api.debug; -import com.oracle.truffle.api.instrument.Instrument; +import java.io.IOException; + +import javax.sound.midi.Instrument; + import com.oracle.truffle.api.instrument.Probe; import com.oracle.truffle.api.source.Source; -import java.io.IOException; /** * Breakpoint in a {@link com.oracle.truffle.api.vm.TruffleVM} with diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java Fri Sep 25 14:58:35 2015 -0700 @@ -48,7 +48,7 @@ import com.oracle.truffle.api.debug.Debugger.WarningLog; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener; -import com.oracle.truffle.api.instrument.Instrument; +import com.oracle.truffle.api.instrument.ProbeInstrument; import com.oracle.truffle.api.instrument.Instrumenter; import com.oracle.truffle.api.instrument.Probe; import com.oracle.truffle.api.instrument.StandardSyntaxTag; @@ -70,8 +70,8 @@ *
    *
  1. Line breakpoints can only be set at nodes tagged as {@link StandardSyntaxTag#STATEMENT}.
  2. *
  3. A newly created breakpoint looks for probes matching the location, attaches to them if found - * by installing an {@link Instrument} that calls back to the breakpoint.
  4. - *
  5. When Truffle "splits" or otherwise copies an AST, any attached {@link Instrument} will be + * by installing an {@link ProbeInstrument} that calls back to the breakpoint.
  6. + *
  7. When Truffle "splits" or otherwise copies an AST, any attached {@link ProbeInstrument} will be * copied along with the rest of the AST and will call back to the same breakpoint.
  8. *
  9. When notification is received of a new Node being tagged as a statement, and if a * breakpoint's line location matches the Probe's line location, then the breakpoint will attach a @@ -291,7 +291,7 @@ * The instrument(s) that this breakpoint currently has attached to a {@link Probe}: * {@code null} if not attached. */ - private List instruments = new ArrayList<>(); + private List instruments = new ArrayList<>(); public LineBreakpointImpl(int ignoreCount, LineLocation lineLocation, boolean oneShot) { super(ENABLED_UNRESOLVED, ignoreCount, oneShot); @@ -346,7 +346,7 @@ if (this.conditionExpr != null || expr != null) { // De-instrument the Probes instrumented by this breakpoint final ArrayList probes = new ArrayList<>(); - for (Instrument instrument : instruments) { + for (ProbeInstrument instrument : instruments) { probes.add(instrument.getProbe()); instrument.dispose(); } @@ -368,7 +368,7 @@ @Override public void dispose() { if (getState() != DISPOSED) { - for (Instrument instrument : instruments) { + for (ProbeInstrument instrument : instruments) { instrument.dispose(); } changeState(DISPOSED); @@ -380,7 +380,7 @@ if (getState() == DISPOSED) { throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME); } - Instrument newInstrument = null; + ProbeInstrument newInstrument = null; final Instrumenter instrumenter = debugger.getInstrumenter(); if (conditionExpr == null) { newInstrument = instrumenter.attach(newProbe, new UnconditionalLineBreakInstrumentListener(), BREAKPOINT_NAME); diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java Fri Sep 25 14:58:35 2015 -0700 @@ -46,7 +46,7 @@ import com.oracle.truffle.api.debug.Debugger.WarningLog; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener; -import com.oracle.truffle.api.instrument.Instrument; +import com.oracle.truffle.api.instrument.ProbeInstrument; import com.oracle.truffle.api.instrument.Instrumenter; import com.oracle.truffle.api.instrument.Probe; import com.oracle.truffle.api.instrument.SyntaxTag; @@ -72,8 +72,8 @@ *
      *
    1. Only one Tag Breakpoint can be active for a specific {@linkplain SyntaxTag Tag}.
    2. *
    3. A newly created breakpoint looks for probes matching the tag, attaches to them if found by - * installing an {@link Instrument}.
    4. - *
    5. When Truffle "splits" or otherwise copies an AST, any attached {@link Instrument} will be + * installing an {@link ProbeInstrument}.
    6. + *
    7. When Truffle "splits" or otherwise copies an AST, any attached {@link ProbeInstrument} will be * copied along with the rest of the AST and will call back to the same breakpoint.
    8. *
    9. When notification is received that the breakpoint's Tag has been newly added to a Node, then * the breakpoint will attach a new Instrument at the probe to activate the breakpoint at that @@ -260,7 +260,7 @@ * The instrument(s) that this breakpoint currently has attached to a {@link Probe}: * {@code null} if not attached. */ - private List instruments = new ArrayList<>(); + private List instruments = new ArrayList<>(); private TagBreakpointImpl(int ignoreCount, SyntaxTag tag, boolean oneShot) { super(ENABLED, ignoreCount, oneShot); @@ -307,7 +307,7 @@ if (this.conditionExpr != null || expr != null) { // De-instrument the Probes instrumented by this breakpoint final ArrayList probes = new ArrayList<>(); - for (Instrument instrument : instruments) { + for (ProbeInstrument instrument : instruments) { probes.add(instrument.getProbe()); instrument.dispose(); } @@ -329,7 +329,7 @@ @Override public void dispose() { if (getState() != DISPOSED) { - for (Instrument instrument : instruments) { + for (ProbeInstrument instrument : instruments) { instrument.dispose(); } changeState(DISPOSED); @@ -341,7 +341,7 @@ if (getState() == DISPOSED) { throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME); } - Instrument newInstrument = null; + ProbeInstrument newInstrument = null; final Instrumenter instrumenter = debugger.getInstrumenter(); if (conditionExpr == null) { newInstrument = instrumenter.attach(newProbe, new UnconditionalTagBreakInstrumentListener(), BREAKPOINT_NAME); diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java Fri Sep 25 14:58:35 2015 -0700 @@ -37,7 +37,7 @@ * Notification is fully synchronous, so overrides have performance implications. Non-trivial * methods should be coded with Truffle guidelines and cautions in mind. * - * @see Instrument + * @see ProbeInstrument * @see AdvancedInstrumentRoot * @see AdvancedInstrumentRootFactory */ diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java Fri Sep 25 14:58:35 2015 -0700 @@ -33,14 +33,14 @@ * {@linkplain Instrumenter#attach(Probe, AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String) * Advanced Instrument}. * - * @see Instrument + * @see ProbeInstrument * @see AdvancedInstrumentRootFactory * @see AdvancedInstrumentResultListener */ public abstract class AdvancedInstrumentRoot extends Node implements InstrumentationNode { /** - * Executes this AST fragment on behalf of a client {@link Instrument}, just before the + * Executes this AST fragment on behalf of a client {@link ProbeInstrument}, just before the * guest-language AST node to which the {@link Probe} holding the Instrument is executed. * * @param node the guest-language AST node to which the host Instrument's Probe is attached diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java Fri Sep 25 14:58:35 2015 -0700 @@ -32,7 +32,7 @@ * {@linkplain Instrumenter#attach(Probe, AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String) * Advanced Instrument}. * - * @see Instrument + * @see ProbeInstrument * @see AdvancedInstrumentRoot */ public interface AdvancedInstrumentRootFactory { diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Fri Sep 25 14:16:21 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,619 +0,0 @@ -/* - * Copyright (c) 2013, 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.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.nodes.NodeCost; -import com.oracle.truffle.api.nodes.NodeInfo; -import com.oracle.truffle.api.source.SourceSection; - -/** - * A binding between: - *
        - *
      1. A {@link Probe}: a source of execution events taking place at a program location in - * an executing Truffle AST, and
      2. - *
      3. A listener: a consumer of execution events on behalf of an external client. - *
      - *

      - * Client-oriented documentation for the use of Instruments is available online at https:// - * wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events - * - * @see Probe - * @see EventHandlerNode - */ -public abstract class Instrument { - - /** - * Has this instrument been disposed? stays true once set. - */ - private boolean isDisposed = false; - - protected Probe probe = null; - - /** - * Optional documentation, mainly for debugging. - */ - private final String instrumentInfo; - - /** - *

      Implementation Notes

      - *

      - * The implementation of Instruments is complicated by the requirement that Truffle be able to - * clone ASTs at any time. In particular, any instrumentation-supporting Nodes that have been - * attached to an AST must be cloned along with the AST: AST clones are not permitted to share - * Nodes. - *

      - * AST cloning is intended to be as transparent as possible to clients. This is - * encouraged by providing the {@link SimpleInstrumentListener} for clients that need know - * nothing more than the properties associated with a Probe: its {@link SourceSection} and any - * associated instances of {@link SyntaxTag}. - *

      - * AST cloning is not transparent to clients that use the - * {@link StandardInstrumentListener}, since those event methods identify the concrete Node - * instance (and thus the AST instance) where the event takes place. - *

      - *

      Implementation Notes: the Life Cycle of an {@link Instrument} at a {@link Probe}

      - *

      - *

        - *
      • A new Instrument is created in permanent association with a client-provided - * listener.
      • - * - *
      • Multiple Instruments may share a single listener.
      • - * - *
      • An Instrument does nothing until it is {@linkplain Probe#attach(Instrument) attached} to - * a Probe, at which time the Instrument begins routing execution events from the Probe's AST - * location to the Instrument's listener.
      • - * - *
      • Neither Instruments nor Probes are {@link Node}s.
      • - * - *
      • A Probe has a single source-based location in an AST, but manages a separate - * instrumentation chain of Nodes at the equivalent location in each clone of the AST.
      • - *
      • When a probed AST is cloned, the instrumentation chain associated with each Probe is - * cloned along with the rest of the AST.
      • - * - *
      • When a new Instrument is attached to a Probe, the Instrument inserts a new instance of - * its private Node type into each of the instrument chains managed by the Probe, i.e. - * one node instance per existing clone of the AST.
      • - * - *
      • If an Instrument is attached to a Probe in an AST that subsequently gets cloned, then the - * Instrument's private Node type will be cloned along with the rest of the the AST.
      • - *
      • Each Instrument's private Node type is a dynamic inner class whose only state is in the - * shared (outer) Instrument instance; that state includes a reference to the Instrument's - * listener.
      • - * - *
      • When an Instrument that has been attached to a Probe is {@linkplain #dispose() disposed}, - * the Instrument searches every instrument chain associated with the Probe and removes the - * instance of its private Node type.
      • - * - *
      • Attaching or disposing an Instrument at a Probe deoptimizes any compilations of - * the AST.
      • - * - *
      - */ - private Instrument(String instrumentInfo) { - this.instrumentInfo = instrumentInfo; - } - - /** - * Gets the {@link Probe} to which this Instrument is currently attached: {@code null} if not - * yet attached to a Probe or if this Instrument has been {@linkplain #dispose() disposed}. - */ - public Probe getProbe() { - return probe; - } - - /** - * Removes this Instrument from the Probe to which it attached and renders this Instrument - * inert. - * - * @throws IllegalStateException if this instrument has already been disposed - */ - public void dispose() throws IllegalStateException { - if (isDisposed) { - throw new IllegalStateException("Attempt to dispose an already disposed Instrumennt"); - } - if (probe != null) { - // It's attached - probe.disposeInstrument(this); - probe = null; - } - this.isDisposed = true; - } - - /** - * For internal implementation only. - */ - void setAttachedTo(Probe probe) { - this.probe = probe; - } - - /** - * Has this instrument been disposed and rendered unusable? - */ - boolean isDisposed() { - return isDisposed; - } - - abstract AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode); - - /** - * Removes this instrument from an instrument chain. - */ - abstract AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode); - - /** - * An instrument that propagates events to an instance of {@link SimpleInstrumentListener}. - */ - static final class SimpleInstrument extends Instrument { - - /** - * Tool-supplied listener for events. - */ - private final SimpleInstrumentListener simpleListener; - - SimpleInstrument(SimpleInstrumentListener simpleListener, String instrumentInfo) { - super(instrumentInfo); - this.simpleListener = simpleListener; - } - - @Override - AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { - return new SimpleInstrumentNode(nextNode); - } - - @Override - AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { - boolean found = false; - if (instrumentNode != null) { - if (instrumentNode.getInstrument() == this) { - // Found the match at the head of the chain - return instrumentNode.nextInstrumentNode; - } - // Match not at the head of the chain; remove it. - found = instrumentNode.removeFromChain(SimpleInstrument.this); - } - if (!found) { - throw new IllegalStateException("Couldn't find instrument node to remove: " + this); - } - return instrumentNode; - } - - /** - * Node that implements a {@link SimpleInstrument} in a particular AST. - */ - @NodeInfo(cost = NodeCost.NONE) - private final class SimpleInstrumentNode extends AbstractInstrumentNode { - - private SimpleInstrumentNode(AbstractInstrumentNode nextNode) { - super(nextNode); - } - - @Override - public void enter(Node node, VirtualFrame vFrame) { - SimpleInstrument.this.simpleListener.onEnter(SimpleInstrument.this.probe); - if (nextInstrumentNode != null) { - nextInstrumentNode.enter(node, vFrame); - } - } - - @Override - public void returnVoid(Node node, VirtualFrame vFrame) { - SimpleInstrument.this.simpleListener.onReturnVoid(SimpleInstrument.this.probe); - if (nextInstrumentNode != null) { - nextInstrumentNode.returnVoid(node, vFrame); - } - } - - @Override - public void returnValue(Node node, VirtualFrame vFrame, Object result) { - SimpleInstrument.this.simpleListener.onReturnValue(SimpleInstrument.this.probe, result); - if (nextInstrumentNode != null) { - nextInstrumentNode.returnValue(node, vFrame, result); - } - } - - @Override - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { - SimpleInstrument.this.simpleListener.onReturnExceptional(SimpleInstrument.this.probe, exception); - if (nextInstrumentNode != null) { - nextInstrumentNode.returnExceptional(node, vFrame, exception); - } - } - - @Override - public String instrumentationInfo() { - final String info = getInstrumentInfo(); - return info != null ? info : simpleListener.getClass().getSimpleName(); - } - } - } - - /** - * An instrument that propagates events to an instance of {@link StandardInstrumentListener}. - */ - static final class StandardInstrument extends Instrument { - - /** - * Tool-supplied listener for AST events. - */ - private final StandardInstrumentListener standardListener; - - StandardInstrument(StandardInstrumentListener standardListener, String instrumentInfo) { - super(instrumentInfo); - this.standardListener = standardListener; - } - - @Override - AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { - return new StandardInstrumentNode(nextNode); - } - - @Override - AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { - boolean found = false; - if (instrumentNode != null) { - if (instrumentNode.getInstrument() == this) { - // Found the match at the head of the chain - return instrumentNode.nextInstrumentNode; - } - // Match not at the head of the chain; remove it. - found = instrumentNode.removeFromChain(StandardInstrument.this); - } - if (!found) { - throw new IllegalStateException("Couldn't find instrument node to remove: " + this); - } - return instrumentNode; - } - - /** - * Node that implements a {@link StandardInstrument} in a particular AST. - */ - @NodeInfo(cost = NodeCost.NONE) - private final class StandardInstrumentNode extends AbstractInstrumentNode { - - private StandardInstrumentNode(AbstractInstrumentNode nextNode) { - super(nextNode); - } - - @Override - public void enter(Node node, VirtualFrame vFrame) { - standardListener.onEnter(StandardInstrument.this.probe, node, vFrame); - if (nextInstrumentNode != null) { - nextInstrumentNode.enter(node, vFrame); - } - } - - @Override - public void returnVoid(Node node, VirtualFrame vFrame) { - standardListener.onReturnVoid(StandardInstrument.this.probe, node, vFrame); - if (nextInstrumentNode != null) { - nextInstrumentNode.returnVoid(node, vFrame); - } - } - - @Override - public void returnValue(Node node, VirtualFrame vFrame, Object result) { - standardListener.onReturnValue(StandardInstrument.this.probe, node, vFrame, result); - if (nextInstrumentNode != null) { - nextInstrumentNode.returnValue(node, vFrame, result); - } - } - - @Override - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { - standardListener.onReturnExceptional(StandardInstrument.this.probe, node, vFrame, exception); - if (nextInstrumentNode != null) { - nextInstrumentNode.returnExceptional(node, vFrame, exception); - } - } - - @Override - public String instrumentationInfo() { - final String info = getInstrumentInfo(); - return info != null ? info : standardListener.getClass().getSimpleName(); - } - } - } - - /** - * An instrument that allows clients to provide an AST fragment to be executed directly from - * within a Probe's instrumentation chain, and thus directly in the executing Truffle - * AST with potential for full optimization. - */ - static final class AdvancedInstrument extends Instrument { - - private final AdvancedInstrumentResultListener resultListener; - private final AdvancedInstrumentRootFactory rootFactory; - private final Class requiredResultType; - - AdvancedInstrument(AdvancedInstrumentResultListener resultListener, AdvancedInstrumentRootFactory rootFactory, Class requiredResultType, String instrumentInfo) { - super(instrumentInfo); - this.resultListener = resultListener; - this.rootFactory = rootFactory; - this.requiredResultType = requiredResultType; - } - - @Override - AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { - return new AdvancedInstrumentNode(nextNode); - } - - @Override - AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { - boolean found = false; - if (instrumentNode != null) { - if (instrumentNode.getInstrument() == this) { - // Found the match at the head of the chain - return instrumentNode.nextInstrumentNode; - } - // Match not at the head of the chain; remove it. - found = instrumentNode.removeFromChain(AdvancedInstrument.this); - } - if (!found) { - throw new IllegalStateException("Couldn't find instrument node to remove: " + this); - } - return instrumentNode; - } - - /** - * Node that implements a {@link AdvancedInstrument} in a particular AST. - */ - @NodeInfo(cost = NodeCost.NONE) - private final class AdvancedInstrumentNode extends AbstractInstrumentNode { - - @Child private AdvancedInstrumentRoot instrumentRoot; - - private AdvancedInstrumentNode(AbstractInstrumentNode nextNode) { - super(nextNode); - } - - @Override - public void enter(Node node, VirtualFrame vFrame) { - if (instrumentRoot == null) { - try { - final AdvancedInstrumentRoot newInstrumentRoot = AdvancedInstrument.this.rootFactory.createInstrumentRoot(AdvancedInstrument.this.probe, node); - if (newInstrumentRoot != null) { - instrumentRoot = newInstrumentRoot; - adoptChildren(); - AdvancedInstrument.this.probe.invalidateProbeUnchanged(); - } - } catch (RuntimeException ex) { - if (resultListener != null) { - resultListener.onFailure(node, vFrame, ex); - } - } - } - if (instrumentRoot != null) { - try { - final Object result = instrumentRoot.executeRoot(node, vFrame); - if (resultListener != null) { - checkResultType(result); - resultListener.onExecution(node, vFrame, result); - } - } catch (RuntimeException ex) { - if (resultListener != null) { - resultListener.onFailure(node, vFrame, ex); - } - } - } - if (nextInstrumentNode != null) { - nextInstrumentNode.enter(node, vFrame); - } - } - - private void checkResultType(Object result) { - if (requiredResultType == null) { - return; - } - if (result == null) { - throw instrumentResultNull(); - } - if (!(requiredResultType.isAssignableFrom(result.getClass()))) { - throw instrumentResultWrongType(result); - } - } - - @TruffleBoundary - private RuntimeException instrumentResultNull() { - return new RuntimeException("Instrument result null: " + requiredResultType.getSimpleName() + " is required"); - } - - @TruffleBoundary - private RuntimeException instrumentResultWrongType(Object result) { - return new RuntimeException("Instrument result " + result.toString() + " not assignable to " + requiredResultType.getSimpleName()); - } - - @Override - public void returnVoid(Node node, VirtualFrame vFrame) { - if (nextInstrumentNode != null) { - nextInstrumentNode.returnVoid(node, vFrame); - } - } - - @Override - public void returnValue(Node node, VirtualFrame vFrame, Object result) { - if (nextInstrumentNode != null) { - nextInstrumentNode.returnValue(node, vFrame, result); - } - } - - @Override - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { - if (nextInstrumentNode != null) { - nextInstrumentNode.returnExceptional(node, vFrame, exception); - } - } - - @Override - public String instrumentationInfo() { - final String info = getInstrumentInfo(); - return info != null ? info : rootFactory.getClass().getSimpleName(); - } - } - } - - // TODO (mlvdv) experimental - public interface TruffleOptListener { - void notifyIsCompiled(boolean isCompiled); - } - - @SuppressWarnings("unused") - private static final class TruffleOptInstrument extends Instrument { - - private final TruffleOptListener toolOptListener; - - private TruffleOptInstrument(TruffleOptListener listener, String instrumentInfo) { - super(instrumentInfo); - this.toolOptListener = listener; - } - - @Override - AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { - return new TruffleOptInstrumentNode(nextNode); - } - - @Override - AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { - boolean found = false; - if (instrumentNode != null) { - if (instrumentNode.getInstrument() == this) { - // Found the match at the head of the chain - return instrumentNode.nextInstrumentNode; - } - // Match not at the head of the chain; remove it. - found = instrumentNode.removeFromChain(TruffleOptInstrument.this); - } - if (!found) { - throw new IllegalStateException("Couldn't find instrument node to remove: " + this); - } - return instrumentNode; - } - - @NodeInfo(cost = NodeCost.NONE) - private final class TruffleOptInstrumentNode extends AbstractInstrumentNode { - - private boolean isCompiled; - - private TruffleOptInstrumentNode(AbstractInstrumentNode nextNode) { - super(nextNode); - this.isCompiled = CompilerDirectives.inCompiledCode(); - } - - @Override - public void enter(Node node, VirtualFrame vFrame) { - if (this.isCompiled != CompilerDirectives.inCompiledCode()) { - this.isCompiled = CompilerDirectives.inCompiledCode(); - TruffleOptInstrument.this.toolOptListener.notifyIsCompiled(this.isCompiled); - } - if (nextInstrumentNode != null) { - nextInstrumentNode.enter(node, vFrame); - } - } - - @Override - public void returnVoid(Node node, VirtualFrame vFrame) { - if (nextInstrumentNode != null) { - nextInstrumentNode.returnVoid(node, vFrame); - } - } - - @Override - public void returnValue(Node node, VirtualFrame vFrame, Object result) { - if (nextInstrumentNode != null) { - nextInstrumentNode.returnValue(node, vFrame, result); - } - } - - @Override - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { - if (nextInstrumentNode != null) { - nextInstrumentNode.returnExceptional(node, vFrame, exception); - } - } - - @Override - public String instrumentationInfo() { - final String info = getInstrumentInfo(); - return info != null ? info : toolOptListener.getClass().getSimpleName(); - } - } - } - - @NodeInfo(cost = NodeCost.NONE) - abstract class AbstractInstrumentNode extends EventHandlerNode { - - @Child protected AbstractInstrumentNode nextInstrumentNode; - - protected AbstractInstrumentNode(AbstractInstrumentNode nextNode) { - this.nextInstrumentNode = nextNode; - } - - @Override - public Probe getProbe() { - return probe; - } - - /** - * Gets the instrument that created this node. - */ - private Instrument getInstrument() { - return Instrument.this; - } - - /** - * Removes the node from this chain that was added by a particular instrument, assuming that - * the head of the chain is not the one to be replaced. This is awkward, but is required - * because {@link Node#replace(Node)} won't take a {@code null} argument. This doesn't work - * for the tail of the list, which would be replacing itself with null. So the replacement - * must be directed the parent of the node being removed. - */ - private boolean removeFromChain(Instrument instrument) { - assert getInstrument() != instrument; - if (nextInstrumentNode == null) { - return false; - } - if (nextInstrumentNode.getInstrument() == instrument) { - // Next is the one to remove - if (nextInstrumentNode.nextInstrumentNode == null) { - // Next is at the tail; just forget - nextInstrumentNode = null; - } else { - // Replace next with its successor - nextInstrumentNode.replace(nextInstrumentNode.nextInstrumentNode); - } - return true; - } - return nextInstrumentNode.removeFromChain(instrument); - } - - protected String getInstrumentInfo() { - return Instrument.this.instrumentInfo; - } - } -} diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java Fri Sep 25 14:58:35 2015 -0700 @@ -73,14 +73,14 @@ } /** - * {@linkplain Instrument Instrumentation}-based collectors of data during Guest Language + * {@linkplain ProbeInstrument Instrumentation}-based collectors of data during Guest Language * program execution. *

      * Tools share a common life cycle: *

        *
      • A newly created tool is inert until {@linkplain Instrumenter#install(Tool) installed}.
      • *
      • An installed tool becomes enabled and immediately begins installing - * {@linkplain Instrument instrumentation} on ASTs and collecting execution data from them.
      • + * {@linkplain ProbeInstrument instrumentation} on ASTs and collecting execution data from them. *
      • A tool may only be installed once.
      • *
      • 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.
      • @@ -247,7 +247,7 @@ } /** - * Prepares an AST node for {@linkplain Instrument instrumentation}, where the node is presumed + * Prepares an AST node for {@linkplain ProbeInstrument instrumentation}, where the node is presumed * to be part of a well-formed Truffle AST that has not yet been executed. *

        * Probing a node is idempotent: @@ -422,8 +422,8 @@ /** * Attaches a {@link SimpleInstrumentListener listener} to a {@link Probe}, creating a - * binding called an {@link Instrument}. Until the Instrument is - * {@linkplain Instrument#dispose() disposed}, it routes synchronous notification of + * binding called an {@link ProbeInstrument}. Until the Instrument is + * {@linkplain ProbeInstrument#dispose() disposed}, it routes synchronous notification of * {@linkplain EventHandlerNode execution events} taking place at the Probe's AST location to * the listener. * @@ -433,16 +433,16 @@ * @return a handle for access to the binding */ @SuppressWarnings("static-method") - public Instrument attach(Probe probe, SimpleInstrumentListener listener, String instrumentInfo) { - final Instrument instrument = new Instrument.SimpleInstrument(listener, instrumentInfo); + public ProbeInstrument attach(Probe probe, SimpleInstrumentListener listener, String instrumentInfo) { + final ProbeInstrument instrument = new ProbeInstrument.SimpleInstrument(listener, instrumentInfo); probe.attach(instrument); return instrument; } /** * Attaches a {@link StandardInstrumentListener listener} to a {@link Probe}, creating - * a binding called an {@link Instrument}. Until the Instrument is - * {@linkplain Instrument#dispose() disposed}, it routes synchronous notification of + * a binding called an {@link ProbeInstrument}. Until the Instrument is + * {@linkplain ProbeInstrument#dispose() disposed}, it routes synchronous notification of * {@linkplain EventHandlerNode execution events} taking place at the Probe's AST location to * the listener. * @@ -452,16 +452,16 @@ * @return a handle for access to the binding */ @SuppressWarnings("static-method") - public Instrument attach(Probe probe, StandardInstrumentListener listener, String instrumentInfo) { - final Instrument instrument = new Instrument.StandardInstrument(listener, instrumentInfo); + public ProbeInstrument attach(Probe probe, StandardInstrumentListener listener, String instrumentInfo) { + final ProbeInstrument instrument = new ProbeInstrument.StandardInstrument(listener, instrumentInfo); probe.attach(instrument); return instrument; } /** * Attaches a {@link AdvancedInstrumentResultListener listener} to a {@link Probe}, - * creating a binding called an {@link Instrument}. Until the Instrument is - * {@linkplain Instrument#dispose() disposed}, it routes synchronous notification of + * creating a binding called an {@link ProbeInstrument}. Until the Instrument is + * {@linkplain ProbeInstrument#dispose() disposed}, it routes synchronous notification of * {@linkplain EventHandlerNode execution events} taking place at the Probe's AST location to * the listener. *

        @@ -480,8 +480,8 @@ * @return a handle for access to the binding */ @SuppressWarnings("static-method") - public Instrument attach(Probe probe, AdvancedInstrumentResultListener listener, AdvancedInstrumentRootFactory rootFactory, Class requiredResultType, String instrumentInfo) { - final Instrument instrument = new Instrument.AdvancedInstrument(listener, rootFactory, requiredResultType, instrumentInfo); + public ProbeInstrument attach(Probe probe, AdvancedInstrumentResultListener listener, AdvancedInstrumentRootFactory rootFactory, Class requiredResultType, String instrumentInfo) { + final ProbeInstrument instrument = new ProbeInstrument.AdvancedInstrument(listener, rootFactory, requiredResultType, instrumentInfo); probe.attach(instrument); return instrument; } diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Fri Sep 25 14:58:35 2015 -0700 @@ -44,7 +44,7 @@ *

          *
        1. A guest language program location in an executing Truffle AST (corresponding to a * {@link SourceSection}), and
        2. - *
        3. A dynamically managed collection of attached {@linkplain Instrument Instruments} + *
        4. A dynamically managed collection of attached {@linkplain ProbeInstrument Instruments} * that receive event notifications from the Probe's AST location on behalf of external clients.
        5. *
        * Note:The relationship must be with an AST location, not a specific @@ -57,7 +57,7 @@ *

        * * @see Instrumenter - * @see Instrument + * @see ProbeInstrument * @see ASTProber * @see ProbeListener * @see SyntaxTag @@ -115,7 +115,7 @@ *

      *
    10. *
    11. The effect of the binding is to intercept {@linkplain EventHandlerNode execution events} - * arriving at the "probed" AST Node and notify each attached {@link Instrument} before + * arriving at the "probed" AST Node and notify each attached {@link ProbeInstrument} before * execution is allowed to proceed to the child and again after execution completes.
    12. * *
    13. The method {@link Instrumenter#probe(Node)} creates a Probe on an AST Node; redundant @@ -130,7 +130,7 @@ *
    14. The "probing" of an AST Node is implemented by insertion of a * {@link ProbeNode.WrapperNode} into the AST (as new parent of the Node being probed), together * with an associated {@link ProbeNode} that routes execution events at the probed Node to all - * the {@linkplain Instrument Instruments} attached to the Probe's instrument chain.
    15. + * the {@linkplain ProbeInstrument Instruments} attached to the Probe's instrument chain. * *
    16. When Truffle clones an AST, any attached WrapperNodes and ProbeNodes are cloned as well, * together with their attached instrument chains. Each Probe instance intercepts cloning events @@ -207,7 +207,7 @@ * @param instrument an instrument not yet attached to a probe * @throws IllegalStateException if the instrument has ever been attached before */ - void attach(Instrument instrument) throws IllegalStateException { + void attach(ProbeInstrument instrument) throws IllegalStateException { if (instrument.isDisposed()) { throw new IllegalStateException("Attempt to attach disposed instrument"); } @@ -243,9 +243,9 @@ * * @param instrument an instrument already attached * @throws IllegalStateException if instrument not attached at this Probe - * @see Instrument#dispose() + * @see ProbeInstrument#dispose() */ - void disposeInstrument(Instrument instrument) throws IllegalStateException { + void disposeInstrument(ProbeInstrument instrument) throws IllegalStateException { for (WeakReference ref : probeNodeClones) { final ProbeNode probeNode = ref.get(); if (probeNode != null) { diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java Fri Sep 25 14:58:35 2015 -0700 @@ -0,0 +1,619 @@ +/* + * Copyright (c) 2013, 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.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeInfo; +import com.oracle.truffle.api.source.SourceSection; + +/** + * A binding between: + *
        + *
      1. A {@link Probe}: a source of execution events taking place at a program location in + * an executing Truffle AST, and
      2. + *
      3. A listener: a consumer of execution events on behalf of an external client. + *
      + *

      + * Client-oriented documentation for the use of Instruments is available online at https:// + * wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events + * + * @see Probe + * @see EventHandlerNode + */ +public abstract class ProbeInstrument { + + /** + * Has this instrument been disposed? stays true once set. + */ + private boolean isDisposed = false; + + protected Probe probe = null; + + /** + * Optional documentation, mainly for debugging. + */ + private final String instrumentInfo; + + /** + *

      Implementation Notes

      + *

      + * The implementation of Instruments is complicated by the requirement that Truffle be able to + * clone ASTs at any time. In particular, any instrumentation-supporting Nodes that have been + * attached to an AST must be cloned along with the AST: AST clones are not permitted to share + * Nodes. + *

      + * AST cloning is intended to be as transparent as possible to clients. This is + * encouraged by providing the {@link SimpleInstrumentListener} for clients that need know + * nothing more than the properties associated with a Probe: its {@link SourceSection} and any + * associated instances of {@link SyntaxTag}. + *

      + * AST cloning is not transparent to clients that use the + * {@link StandardInstrumentListener}, since those event methods identify the concrete Node + * instance (and thus the AST instance) where the event takes place. + *

      + *

      Implementation Notes: the Life Cycle of an {@link ProbeInstrument} at a {@link Probe}

      + *

      + *

        + *
      • A new Instrument is created in permanent association with a client-provided + * listener.
      • + * + *
      • Multiple Instruments may share a single listener.
      • + * + *
      • An Instrument does nothing until it is {@linkplain Probe#attach(ProbeInstrument) attached} to + * a Probe, at which time the Instrument begins routing execution events from the Probe's AST + * location to the Instrument's listener.
      • + * + *
      • Neither Instruments nor Probes are {@link Node}s.
      • + * + *
      • A Probe has a single source-based location in an AST, but manages a separate + * instrumentation chain of Nodes at the equivalent location in each clone of the AST.
      • + *
      • When a probed AST is cloned, the instrumentation chain associated with each Probe is + * cloned along with the rest of the AST.
      • + * + *
      • When a new Instrument is attached to a Probe, the Instrument inserts a new instance of + * its private Node type into each of the instrument chains managed by the Probe, i.e. + * one node instance per existing clone of the AST.
      • + * + *
      • If an Instrument is attached to a Probe in an AST that subsequently gets cloned, then the + * Instrument's private Node type will be cloned along with the rest of the the AST.
      • + *
      • Each Instrument's private Node type is a dynamic inner class whose only state is in the + * shared (outer) Instrument instance; that state includes a reference to the Instrument's + * listener.
      • + * + *
      • When an Instrument that has been attached to a Probe is {@linkplain #dispose() disposed}, + * the Instrument searches every instrument chain associated with the Probe and removes the + * instance of its private Node type.
      • + * + *
      • Attaching or disposing an Instrument at a Probe deoptimizes any compilations of + * the AST.
      • + * + *
      + */ + private ProbeInstrument(String instrumentInfo) { + this.instrumentInfo = instrumentInfo; + } + + /** + * Gets the {@link Probe} to which this Instrument is currently attached: {@code null} if not + * yet attached to a Probe or if this Instrument has been {@linkplain #dispose() disposed}. + */ + public Probe getProbe() { + return probe; + } + + /** + * Removes this Instrument from the Probe to which it attached and renders this Instrument + * inert. + * + * @throws IllegalStateException if this instrument has already been disposed + */ + public void dispose() throws IllegalStateException { + if (isDisposed) { + throw new IllegalStateException("Attempt to dispose an already disposed Instrumennt"); + } + if (probe != null) { + // It's attached + probe.disposeInstrument(this); + probe = null; + } + this.isDisposed = true; + } + + /** + * For internal implementation only. + */ + void setAttachedTo(Probe probe) { + this.probe = probe; + } + + /** + * Has this instrument been disposed and rendered unusable? + */ + boolean isDisposed() { + return isDisposed; + } + + abstract AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode); + + /** + * Removes this instrument from an instrument chain. + */ + abstract AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode); + + /** + * An instrument that propagates events to an instance of {@link SimpleInstrumentListener}. + */ + static final class SimpleInstrument extends ProbeInstrument { + + /** + * Tool-supplied listener for events. + */ + private final SimpleInstrumentListener simpleListener; + + SimpleInstrument(SimpleInstrumentListener simpleListener, String instrumentInfo) { + super(instrumentInfo); + this.simpleListener = simpleListener; + } + + @Override + AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { + return new SimpleInstrumentNode(nextNode); + } + + @Override + AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { + boolean found = false; + if (instrumentNode != null) { + if (instrumentNode.getInstrument() == this) { + // Found the match at the head of the chain + return instrumentNode.nextInstrumentNode; + } + // Match not at the head of the chain; remove it. + found = instrumentNode.removeFromChain(SimpleInstrument.this); + } + if (!found) { + throw new IllegalStateException("Couldn't find instrument node to remove: " + this); + } + return instrumentNode; + } + + /** + * Node that implements a {@link SimpleInstrument} in a particular AST. + */ + @NodeInfo(cost = NodeCost.NONE) + private final class SimpleInstrumentNode extends AbstractInstrumentNode { + + private SimpleInstrumentNode(AbstractInstrumentNode nextNode) { + super(nextNode); + } + + @Override + public void enter(Node node, VirtualFrame vFrame) { + SimpleInstrument.this.simpleListener.onEnter(SimpleInstrument.this.probe); + if (nextInstrumentNode != null) { + nextInstrumentNode.enter(node, vFrame); + } + } + + @Override + public void returnVoid(Node node, VirtualFrame vFrame) { + SimpleInstrument.this.simpleListener.onReturnVoid(SimpleInstrument.this.probe); + if (nextInstrumentNode != null) { + nextInstrumentNode.returnVoid(node, vFrame); + } + } + + @Override + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + SimpleInstrument.this.simpleListener.onReturnValue(SimpleInstrument.this.probe, result); + if (nextInstrumentNode != null) { + nextInstrumentNode.returnValue(node, vFrame, result); + } + } + + @Override + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + SimpleInstrument.this.simpleListener.onReturnExceptional(SimpleInstrument.this.probe, exception); + if (nextInstrumentNode != null) { + nextInstrumentNode.returnExceptional(node, vFrame, exception); + } + } + + @Override + public String instrumentationInfo() { + final String info = getInstrumentInfo(); + return info != null ? info : simpleListener.getClass().getSimpleName(); + } + } + } + + /** + * An instrument that propagates events to an instance of {@link StandardInstrumentListener}. + */ + static final class StandardInstrument extends ProbeInstrument { + + /** + * Tool-supplied listener for AST events. + */ + private final StandardInstrumentListener standardListener; + + StandardInstrument(StandardInstrumentListener standardListener, String instrumentInfo) { + super(instrumentInfo); + this.standardListener = standardListener; + } + + @Override + AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { + return new StandardInstrumentNode(nextNode); + } + + @Override + AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { + boolean found = false; + if (instrumentNode != null) { + if (instrumentNode.getInstrument() == this) { + // Found the match at the head of the chain + return instrumentNode.nextInstrumentNode; + } + // Match not at the head of the chain; remove it. + found = instrumentNode.removeFromChain(StandardInstrument.this); + } + if (!found) { + throw new IllegalStateException("Couldn't find instrument node to remove: " + this); + } + return instrumentNode; + } + + /** + * Node that implements a {@link StandardInstrument} in a particular AST. + */ + @NodeInfo(cost = NodeCost.NONE) + private final class StandardInstrumentNode extends AbstractInstrumentNode { + + private StandardInstrumentNode(AbstractInstrumentNode nextNode) { + super(nextNode); + } + + @Override + public void enter(Node node, VirtualFrame vFrame) { + standardListener.onEnter(StandardInstrument.this.probe, node, vFrame); + if (nextInstrumentNode != null) { + nextInstrumentNode.enter(node, vFrame); + } + } + + @Override + public void returnVoid(Node node, VirtualFrame vFrame) { + standardListener.onReturnVoid(StandardInstrument.this.probe, node, vFrame); + if (nextInstrumentNode != null) { + nextInstrumentNode.returnVoid(node, vFrame); + } + } + + @Override + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + standardListener.onReturnValue(StandardInstrument.this.probe, node, vFrame, result); + if (nextInstrumentNode != null) { + nextInstrumentNode.returnValue(node, vFrame, result); + } + } + + @Override + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + standardListener.onReturnExceptional(StandardInstrument.this.probe, node, vFrame, exception); + if (nextInstrumentNode != null) { + nextInstrumentNode.returnExceptional(node, vFrame, exception); + } + } + + @Override + public String instrumentationInfo() { + final String info = getInstrumentInfo(); + return info != null ? info : standardListener.getClass().getSimpleName(); + } + } + } + + /** + * An instrument that allows clients to provide an AST fragment to be executed directly from + * within a Probe's instrumentation chain, and thus directly in the executing Truffle + * AST with potential for full optimization. + */ + static final class AdvancedInstrument extends ProbeInstrument { + + private final AdvancedInstrumentResultListener resultListener; + private final AdvancedInstrumentRootFactory rootFactory; + private final Class requiredResultType; + + AdvancedInstrument(AdvancedInstrumentResultListener resultListener, AdvancedInstrumentRootFactory rootFactory, Class requiredResultType, String instrumentInfo) { + super(instrumentInfo); + this.resultListener = resultListener; + this.rootFactory = rootFactory; + this.requiredResultType = requiredResultType; + } + + @Override + AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { + return new AdvancedInstrumentNode(nextNode); + } + + @Override + AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { + boolean found = false; + if (instrumentNode != null) { + if (instrumentNode.getInstrument() == this) { + // Found the match at the head of the chain + return instrumentNode.nextInstrumentNode; + } + // Match not at the head of the chain; remove it. + found = instrumentNode.removeFromChain(AdvancedInstrument.this); + } + if (!found) { + throw new IllegalStateException("Couldn't find instrument node to remove: " + this); + } + return instrumentNode; + } + + /** + * Node that implements a {@link AdvancedInstrument} in a particular AST. + */ + @NodeInfo(cost = NodeCost.NONE) + private final class AdvancedInstrumentNode extends AbstractInstrumentNode { + + @Child private AdvancedInstrumentRoot instrumentRoot; + + private AdvancedInstrumentNode(AbstractInstrumentNode nextNode) { + super(nextNode); + } + + @Override + public void enter(Node node, VirtualFrame vFrame) { + if (instrumentRoot == null) { + try { + final AdvancedInstrumentRoot newInstrumentRoot = AdvancedInstrument.this.rootFactory.createInstrumentRoot(AdvancedInstrument.this.probe, node); + if (newInstrumentRoot != null) { + instrumentRoot = newInstrumentRoot; + adoptChildren(); + AdvancedInstrument.this.probe.invalidateProbeUnchanged(); + } + } catch (RuntimeException ex) { + if (resultListener != null) { + resultListener.onFailure(node, vFrame, ex); + } + } + } + if (instrumentRoot != null) { + try { + final Object result = instrumentRoot.executeRoot(node, vFrame); + if (resultListener != null) { + checkResultType(result); + resultListener.onExecution(node, vFrame, result); + } + } catch (RuntimeException ex) { + if (resultListener != null) { + resultListener.onFailure(node, vFrame, ex); + } + } + } + if (nextInstrumentNode != null) { + nextInstrumentNode.enter(node, vFrame); + } + } + + private void checkResultType(Object result) { + if (requiredResultType == null) { + return; + } + if (result == null) { + throw instrumentResultNull(); + } + if (!(requiredResultType.isAssignableFrom(result.getClass()))) { + throw instrumentResultWrongType(result); + } + } + + @TruffleBoundary + private RuntimeException instrumentResultNull() { + return new RuntimeException("Instrument result null: " + requiredResultType.getSimpleName() + " is required"); + } + + @TruffleBoundary + private RuntimeException instrumentResultWrongType(Object result) { + return new RuntimeException("Instrument result " + result.toString() + " not assignable to " + requiredResultType.getSimpleName()); + } + + @Override + public void returnVoid(Node node, VirtualFrame vFrame) { + if (nextInstrumentNode != null) { + nextInstrumentNode.returnVoid(node, vFrame); + } + } + + @Override + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + if (nextInstrumentNode != null) { + nextInstrumentNode.returnValue(node, vFrame, result); + } + } + + @Override + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + if (nextInstrumentNode != null) { + nextInstrumentNode.returnExceptional(node, vFrame, exception); + } + } + + @Override + public String instrumentationInfo() { + final String info = getInstrumentInfo(); + return info != null ? info : rootFactory.getClass().getSimpleName(); + } + } + } + + // TODO (mlvdv) experimental + public interface TruffleOptListener { + void notifyIsCompiled(boolean isCompiled); + } + + @SuppressWarnings("unused") + private static final class TruffleOptInstrument extends ProbeInstrument { + + private final TruffleOptListener toolOptListener; + + private TruffleOptInstrument(TruffleOptListener listener, String instrumentInfo) { + super(instrumentInfo); + this.toolOptListener = listener; + } + + @Override + AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { + return new TruffleOptInstrumentNode(nextNode); + } + + @Override + AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { + boolean found = false; + if (instrumentNode != null) { + if (instrumentNode.getInstrument() == this) { + // Found the match at the head of the chain + return instrumentNode.nextInstrumentNode; + } + // Match not at the head of the chain; remove it. + found = instrumentNode.removeFromChain(TruffleOptInstrument.this); + } + if (!found) { + throw new IllegalStateException("Couldn't find instrument node to remove: " + this); + } + return instrumentNode; + } + + @NodeInfo(cost = NodeCost.NONE) + private final class TruffleOptInstrumentNode extends AbstractInstrumentNode { + + private boolean isCompiled; + + private TruffleOptInstrumentNode(AbstractInstrumentNode nextNode) { + super(nextNode); + this.isCompiled = CompilerDirectives.inCompiledCode(); + } + + @Override + public void enter(Node node, VirtualFrame vFrame) { + if (this.isCompiled != CompilerDirectives.inCompiledCode()) { + this.isCompiled = CompilerDirectives.inCompiledCode(); + TruffleOptInstrument.this.toolOptListener.notifyIsCompiled(this.isCompiled); + } + if (nextInstrumentNode != null) { + nextInstrumentNode.enter(node, vFrame); + } + } + + @Override + public void returnVoid(Node node, VirtualFrame vFrame) { + if (nextInstrumentNode != null) { + nextInstrumentNode.returnVoid(node, vFrame); + } + } + + @Override + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + if (nextInstrumentNode != null) { + nextInstrumentNode.returnValue(node, vFrame, result); + } + } + + @Override + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + if (nextInstrumentNode != null) { + nextInstrumentNode.returnExceptional(node, vFrame, exception); + } + } + + @Override + public String instrumentationInfo() { + final String info = getInstrumentInfo(); + return info != null ? info : toolOptListener.getClass().getSimpleName(); + } + } + } + + @NodeInfo(cost = NodeCost.NONE) + abstract class AbstractInstrumentNode extends EventHandlerNode { + + @Child protected AbstractInstrumentNode nextInstrumentNode; + + protected AbstractInstrumentNode(AbstractInstrumentNode nextNode) { + this.nextInstrumentNode = nextNode; + } + + @Override + public Probe getProbe() { + return probe; + } + + /** + * Gets the instrument that created this node. + */ + private ProbeInstrument getInstrument() { + return ProbeInstrument.this; + } + + /** + * Removes the node from this chain that was added by a particular instrument, assuming that + * the head of the chain is not the one to be replaced. This is awkward, but is required + * because {@link Node#replace(Node)} won't take a {@code null} argument. This doesn't work + * for the tail of the list, which would be replacing itself with null. So the replacement + * must be directed the parent of the node being removed. + */ + private boolean removeFromChain(ProbeInstrument instrument) { + assert getInstrument() != instrument; + if (nextInstrumentNode == null) { + return false; + } + if (nextInstrumentNode.getInstrument() == instrument) { + // Next is the one to remove + if (nextInstrumentNode.nextInstrumentNode == null) { + // Next is at the tail; just forget + nextInstrumentNode = null; + } else { + // Replace next with its successor + nextInstrumentNode.replace(nextInstrumentNode.nextInstrumentNode); + } + return true; + } + return nextInstrumentNode.removeFromChain(instrument); + } + + protected String getInstrumentInfo() { + return ProbeInstrument.this.instrumentInfo; + } + } +} diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Fri Sep 25 14:58:35 2015 -0700 @@ -27,7 +27,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.instrument.Instrument.AbstractInstrumentNode; +import com.oracle.truffle.api.instrument.ProbeInstrument.AbstractInstrumentNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; @@ -36,11 +36,11 @@ * Implementation class & interface for enabling the attachment of {@linkplain Probe Probes} to * Truffle ASTs. *

      - * A {@link ProbeNode} is the head of a chain of nodes acting on behalf of {@linkplain Instrument + * A {@link ProbeNode} is the head of a chain of nodes acting on behalf of {@linkplain ProbeInstrument * instruments}. It is attached to an AST as a child of a guest-language-specific * {@link WrapperNode} node. *

      - * When Truffle clones an AST, the chain, including all attached {@linkplain Instrument instruments} + * When Truffle clones an AST, the chain, including all attached {@linkplain ProbeInstrument instruments} * will be cloned along with the {@link WrapperNode} to which it is attached. An instance of * {@link Probe} represents abstractly the instrumentation at a particular location in a Guest * Language AST, tracks the clones of the chain, and keeps the instrumentation attached to the @@ -135,7 +135,7 @@ * Adds an {@link AbstractInstrumentNode} to this chain. */ @TruffleBoundary - void addInstrument(Instrument instrument) { + void addInstrument(ProbeInstrument instrument) { assert instrument.getProbe() == probe; // The existing chain of nodes may be empty // Attach the modified chain. @@ -148,7 +148,7 @@ * @throws RuntimeException if no matching instrument is found, */ @TruffleBoundary - void removeInstrument(Instrument instrument) { + void removeInstrument(ProbeInstrument instrument) { assert instrument.getProbe() == probe; final AbstractInstrumentNode modifiedChain = instrument.removeFromChain(firstInstrumentNode); if (modifiedChain == null) { diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java Fri Sep 25 14:58:35 2015 -0700 @@ -37,7 +37,7 @@ * execution state should use {@link StandardInstrumentListener}. *

      * Clients are free, of course, to record additional information in the listener implementation that - * carries additional information about the context and reason for the particular {@link Instrument} + * carries additional information about the context and reason for the particular {@link ProbeInstrument} * that is to be created from the listener. *

      * Notification is fully synchronous, so overrides have performance implications. Non-trivial diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java Fri Sep 25 14:58:35 2015 -0700 @@ -39,7 +39,7 @@ * {@link SimpleInstrumentListener}. *

      * Clients are free, of course, to record additional information in the listener implementation that - * carries additional information about the context and reason for the particular {@link Instrument} + * carries additional information about the context and reason for the particular {@link ProbeInstrument} * that is to be created from the listener. *

      * Notification is fully synchronous, so overrides have performance implications. Non-trivial diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/WrapperNode.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/WrapperNode.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/WrapperNode.java Fri Sep 25 14:58:35 2015 -0700 @@ -28,7 +28,7 @@ /** * A {@link Node} instance that must be inserted into a Truffle AST in order to enable - * {@linkplain Instrument instrumentation} at a particular Guest Language (GL) node. + * {@linkplain ProbeInstrument instrumentation} at a particular Guest Language (GL) node. *

      * The implementation must be GL-specific. A wrapper decorates a GL AST node (the wrapper's * child) by acting as a transparent proxy with respect to the GL's execution @@ -41,7 +41,7 @@ * at the wrapped AST node during program execution. *

      * When a GL AST is cloned, the {@link WrapperNode}, its {@link EventHandlerNode} and any - * {@linkplain Instrument instrumentation} are also cloned; they are in effect part of the GL AST. + * {@linkplain ProbeInstrument instrumentation} are also cloned; they are in effect part of the GL AST. * An instance of {@link Probe} represents abstractly the instrumentation at a particular location * in a GL AST; it tracks all the copies of the Wrapper and attached instrumentation, and acts as a * single point of access for tools. @@ -60,11 +60,11 @@ *

    17. Method {@code insertProbe(EventHandlerNode)} should be implemented as * {@code this.eventHandlerNode=insert(eventHandlerNode);}
    18. *
    19. Most importantly, Wrappers must be implemented so that Truffle optimization will reduce their - * runtime overhead to zero when there are no attached {@link Instrument}s.
    20. + * runtime overhead to zero when there are no attached {@link ProbeInstrument}s. *
    *

    * - * @see Instrument + * @see ProbeInstrument */ public interface WrapperNode extends InstrumentationNode { diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/package-info.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/package-info.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/package-info.java Fri Sep 25 14:58:35 2015 -0700 @@ -119,12 +119,12 @@ *

  10. Clients can be notified of AST execution events by creating one of several kinds of * event listener and attaching it to a * {@linkplain com.oracle.truffle.api.instrument.Probe Probe}. This creates an - * {@linkplain com.oracle.truffle.api.instrument.Instrument Instrument} that notifies the listener + * {@linkplain com.oracle.truffle.api.instrument.ProbeInstrument Instrument} that notifies the listener * of every subsequent execution event at the AST location corresponding to the * {@linkplain com.oracle.truffle.api.instrument.Probe Probe}.
  11. *
  12. An - * {@linkplain com.oracle.truffle.api.instrument.Instrument Instrument} can be - * {@linkplain com.oracle.truffle.api.instrument.Instrument#dispose() disposed}, at which time + * {@linkplain com.oracle.truffle.api.instrument.ProbeInstrument Instrument} can be + * {@linkplain com.oracle.truffle.api.instrument.ProbeInstrument#dispose() disposed}, at which time * it is removed from service at every clone of the AST, incurs no further overhead, and is * permanently unusable.
  13. *
  14. Many clients need only implement a @@ -140,7 +140,7 @@ * {@linkplain com.oracle.truffle.api.nodes.Node AST location} and current * {@linkplain com.oracle.truffle.api.frame.Frame stack frame}.
  15. *
  16. Clients can also create an - * {@linkplain com.oracle.truffle.api.instrument.Instrument Instrument} (whose design is currently + * {@linkplain com.oracle.truffle.api.instrument.ProbeInstrument Instrument} (whose design is currently * under revision) that supports (effectively) inserting a Truffle AST fragment into the AST * location, where it will be executed subject to full Truffle optimization.
  17. * diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java Fri Sep 25 14:58:35 2015 -0700 @@ -42,7 +42,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrument.EventHandlerNode; -import com.oracle.truffle.api.instrument.Instrument; +import com.oracle.truffle.api.instrument.ProbeInstrument; import com.oracle.truffle.api.instrument.KillException; import com.oracle.truffle.api.instrument.Probe; import com.oracle.truffle.api.instrument.WrapperNode; @@ -57,7 +57,7 @@ /** * A Truffle node that can be inserted into a Simple AST (assumed not to have executed yet) to * enable "instrumentation" of an {@link SLExpressionNode}. Tools wishing to interact with AST - * execution may attach {@link Instrument}s to the {@link Probe} uniquely associated with the + * execution may attach {@link ProbeInstrument}s to the {@link Probe} uniquely associated with the * wrapper, and to which this wrapper routes execution events. */ @NodeInfo(cost = NodeCost.NONE) diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java Fri Sep 25 14:58:35 2015 -0700 @@ -42,7 +42,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrument.EventHandlerNode; -import com.oracle.truffle.api.instrument.Instrument; +import com.oracle.truffle.api.instrument.ProbeInstrument; import com.oracle.truffle.api.instrument.KillException; import com.oracle.truffle.api.instrument.Probe; import com.oracle.truffle.api.instrument.WrapperNode; @@ -54,7 +54,7 @@ /** * A Truffle node that can be inserted into a Simple AST (assumed not to have executed yet) to * enable "instrumentation" of a {@link SLStatementNode}. Tools wishing to interact with AST - * execution may attach {@link Instrument}s to the {@link Probe} uniquely associated with the + * execution may attach {@link ProbeInstrument}s to the {@link Probe} uniquely associated with the * wrapper, and to which this wrapper routes execution events. */ @NodeInfo(cost = NodeCost.NONE) diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java --- a/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java Fri Sep 25 14:58:35 2015 -0700 @@ -33,7 +33,7 @@ import java.util.Map.Entry; import java.util.TreeSet; -import com.oracle.truffle.api.instrument.Instrument; +import com.oracle.truffle.api.instrument.ProbeInstrument; import com.oracle.truffle.api.instrument.Instrumenter; import com.oracle.truffle.api.instrument.Probe; import com.oracle.truffle.api.instrument.ProbeListener; @@ -79,7 +79,7 @@ * any time in a simple textual format, with no other effect on the state of the tool. *

    * - * @see Instrument + * @see ProbeInstrument * @see SyntaxTag */ public final class CoverageTracker extends Instrumenter.Tool { @@ -88,7 +88,7 @@ private final Map coverageMap = new HashMap<>(); /** Needed for disposal. */ - private final List instruments = new ArrayList<>(); + private final List instruments = new ArrayList<>(); /** * Coverage counting is restricted to nodes holding this tag. @@ -132,7 +132,7 @@ @Override protected void internalDispose() { getInstrumenter().removeProbeListener(probeListener); - for (Instrument instrument : instruments) { + for (ProbeInstrument instrument : instruments) { instrument.dispose(); } } @@ -247,7 +247,7 @@ private final class CoverageRecord extends DefaultSimpleInstrumentListener { private final SourceSection srcSection; // The text of the code being counted - private Instrument instrument; // The attached Instrument, in case need to remove. + private ProbeInstrument instrument; // The attached Instrument, in case need to remove. private long count = 0; CoverageRecord(SourceSection srcSection) { @@ -304,7 +304,7 @@ } final CoverageRecord coverageRecord = new CoverageRecord(srcSection); - final Instrument instrument = getInstrumenter().attach(probe, coverageRecord, CoverageTracker.class.getSimpleName()); + final ProbeInstrument instrument = getInstrumenter().attach(probe, coverageRecord, CoverageTracker.class.getSimpleName()); coverageRecord.instrument = instrument; instruments.add(instrument); coverageMap.put(lineLocation, coverageRecord); diff -r 7ec5eef84ecf -r e7643754d982 truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java --- a/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java Fri Sep 25 14:16:21 2015 -0700 +++ b/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java Fri Sep 25 14:58:35 2015 -0700 @@ -37,7 +37,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 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.ProbeInstrument; import com.oracle.truffle.api.instrument.Instrumenter; import com.oracle.truffle.api.instrument.Probe; import com.oracle.truffle.api.instrument.ProbeException; @@ -93,7 +93,7 @@ * any time in a simple textual format, without effect on the state of the tool. *

    * - * @see Instrument + * @see ProbeInstrument * @see SyntaxTag * @see ProbeFailure */ @@ -110,7 +110,7 @@ /** * Listener for events at instrumented nodes. Counts are maintained in a shared table, so the - * listener is stateless and can be shared by every {@link Instrument}. + * listener is stateless and can be shared by every {@link ProbeInstrument}. */ private final StandardInstrumentListener instrumentListener = new DefaultStandardInstrumentListener() { @Override @@ -151,7 +151,7 @@ private final List failures = new ArrayList<>(); /** For disposal. */ - private final List instruments = new ArrayList<>(); + private final List instruments = new ArrayList<>(); /** * If non-null, counting is restricted to nodes holding this tag. @@ -209,7 +209,7 @@ if (probeListener != null) { getInstrumenter().removeProbeListener(probeListener); } - for (Instrument instrument : instruments) { + for (ProbeInstrument instrument : instruments) { instrument.dispose(); } } @@ -301,7 +301,7 @@ try { final Probe probe = instrumenter.probe(node); - final Instrument instrument = instrumenter.attach(probe, instrumentListener, "NodeExecCounter"); + final ProbeInstrument instrument = instrumenter.attach(probe, instrumentListener, "NodeExecCounter"); instruments.add(instrument); } catch (ProbeException ex) { failures.add(ex.getFailure()); @@ -322,7 +322,7 @@ @Override public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) { if (countingTag == tag) { - final Instrument instrument = getInstrumenter().attach(probe, instrumentListener, NodeExecCounter.class.getSimpleName()); + final ProbeInstrument instrument = getInstrumenter().attach(probe, instrumentListener, NodeExecCounter.class.getSimpleName()); instruments.add(instrument); } }