Mercurial > hg > truffle
changeset 22256:75e5db92973a
TruffleInstrumentation: fold the "TagTrap" mechanism into the general framework of Instruments, Listeners, and management via Instrumenter.attach() methods.
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java Fri Sep 25 14:58:35 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java Sun Sep 27 21:34:39 2015 -0700 @@ -34,6 +34,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.frame.FrameInstance; import com.oracle.truffle.api.frame.FrameInstanceVisitor; import com.oracle.truffle.api.frame.MaterializedFrame; @@ -44,9 +45,11 @@ import com.oracle.truffle.api.instrument.Instrumenter; import com.oracle.truffle.api.instrument.KillException; import com.oracle.truffle.api.instrument.Probe; +import com.oracle.truffle.api.instrument.StandardAfterInstrumentListener; +import com.oracle.truffle.api.instrument.StandardBeforeInstrumentListener; import com.oracle.truffle.api.instrument.StandardSyntaxTag; import com.oracle.truffle.api.instrument.SyntaxTag; -import com.oracle.truffle.api.instrument.SyntaxTagTrap; +import com.oracle.truffle.api.instrument.TagInstrument; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.LineLocation; import com.oracle.truffle.api.source.Source; @@ -406,6 +409,8 @@ * @see Debugger#prepareStepInto(int) */ private final class StepInto extends StepStrategy { + private TagInstrument beforeTagInstrument; + private TagInstrument afterTagInstrument; private int unfinishedStepCount; StepInto(int stepCount) { @@ -415,26 +420,40 @@ @Override protected void setStrategy(final int stackDepth) { - instrumenter.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) { + + beforeTagInstrument = instrumenter.attach(STEPPING_TAG, new StandardBeforeInstrumentListener() { @TruffleBoundary @Override - public void tagTrappedAt(Node node, MaterializedFrame mFrame) { + public void onEnter(Probe probe, Node node, VirtualFrame vFrame) { // HALT: just before statement --unfinishedStepCount; - strategyTrace("TRAP BEFORE", "unfinished steps=%d", unfinishedStepCount); + strategyTrace("HALT BEFORE", "unfinished steps=%d", unfinishedStepCount); // Should run in fast path if (unfinishedStepCount <= 0) { - halt(node, mFrame, true); + halt(node, vFrame.materialize(), true); } strategyTrace("RESUME BEFORE", ""); } - }); - instrumenter.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) { + }, "Debugger StepInto"); + + afterTagInstrument = instrumenter.attach(CALL_TAG, new StandardAfterInstrumentListener() { + + public void onReturnVoid(Probe probe, Node node, VirtualFrame vFrame) { + doHalt(node, vFrame.materialize()); + } + + public void onReturnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) { + doHalt(node, vFrame.materialize()); + } + + public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) { + doHalt(node, vFrame.materialize()); + } + @TruffleBoundary - @Override - public void tagTrappedAt(Node node, MaterializedFrame mFrame) { + private void doHalt(Node node, MaterializedFrame mFrame) { --unfinishedStepCount; - strategyTrace(null, "TRAP AFTER unfinished steps=%d", unfinishedStepCount); + strategyTrace(null, "HALT AFTER unfinished steps=%d", unfinishedStepCount); if (currentStackDepth() < stackDepth) { // HALT: just "stepped out" if (unfinishedStepCount <= 0) { @@ -443,13 +462,13 @@ } strategyTrace("RESUME AFTER", ""); } - }); + }, "Debugger StepInto"); } @Override protected void unsetStrategy() { - instrumenter.setBeforeTagTrap(null); - instrumenter.setAfterTagTrap(null); + beforeTagInstrument.dispose(); + afterTagInstrument.dispose(); } } @@ -470,27 +489,41 @@ */ private final class StepOut extends StepStrategy { + private TagInstrument afterTagInstrument; + @Override protected void setStrategy(final int stackDepth) { - instrumenter.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) { + + afterTagInstrument = instrumenter.attach(CALL_TAG, new StandardAfterInstrumentListener() { + + public void onReturnVoid(Probe probe, Node node, VirtualFrame vFrame) { + doHalt(node, vFrame.materialize()); + } + + public void onReturnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) { + doHalt(node, vFrame.materialize()); + } + + public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) { + doHalt(node, vFrame.materialize()); + } @TruffleBoundary - @Override - public void tagTrappedAt(Node node, MaterializedFrame mFrame) { + private void doHalt(Node node, MaterializedFrame mFrame) { // HALT: final int currentStackDepth = currentStackDepth(); - strategyTrace("TRAP AFTER", "stackDepth: start=%d current=%d", stackDepth, currentStackDepth); + strategyTrace("HALT AFTER", "stackDepth: start=%d current=%d", stackDepth, currentStackDepth); if (currentStackDepth < stackDepth) { halt(node, mFrame, false); } strategyTrace("RESUME AFTER", ""); } - }); + }, "Debugger StepOut"); } @Override protected void unsetStrategy() { - instrumenter.setAfterTagTrap(null); + afterTagInstrument.dispose(); } } @@ -508,6 +541,8 @@ * </ul> */ private final class StepOver extends StepStrategy { + private TagInstrument beforeTagInstrument; + private TagInstrument afterTagInstrument; private int unfinishedStepCount; StepOver(int stepCount) { @@ -516,20 +551,21 @@ @Override protected void setStrategy(final int stackDepth) { - instrumenter.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) { + beforeTagInstrument = instrumenter.attach(STEPPING_TAG, new StandardBeforeInstrumentListener() { + @TruffleBoundary @Override - public void tagTrappedAt(Node node, MaterializedFrame mFrame) { + public void onEnter(Probe probe, Node node, VirtualFrame vFrame) { final int currentStackDepth = currentStackDepth(); if (currentStackDepth <= stackDepth) { // HALT: stack depth unchanged or smaller; treat like StepInto --unfinishedStepCount; if (TRACE) { - strategyTrace("TRAP BEFORE", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth); + strategyTrace("HALT BEFORE", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth); } // Test should run in fast path if (unfinishedStepCount <= 0) { - halt(node, mFrame, true); + halt(node, vFrame.materialize(), true); } } else { // CONTINUE: Stack depth increased; don't count as a step @@ -539,17 +575,29 @@ } strategyTrace("RESUME BEFORE", ""); } - }); + }, "Debugger StepOver"); + + afterTagInstrument = instrumenter.attach(CALL_TAG, new StandardAfterInstrumentListener() { + + public void onReturnVoid(Probe probe, Node node, VirtualFrame vFrame) { + doHalt(node, vFrame.materialize()); + } - instrumenter.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) { + public void onReturnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) { + doHalt(node, vFrame.materialize()); + } + + public void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) { + doHalt(node, vFrame.materialize()); + } + @TruffleBoundary - @Override - public void tagTrappedAt(Node node, MaterializedFrame mFrame) { + private void doHalt(Node node, MaterializedFrame mFrame) { final int currentStackDepth = currentStackDepth(); if (currentStackDepth < stackDepth) { // HALT: just "stepped out" --unfinishedStepCount; - strategyTrace("TRAP AFTER", "unfinished steps=%d stackDepth: start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth); + strategyTrace("HALT AFTER", "unfinished steps=%d stackDepth: start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth); // Should run in fast path if (unfinishedStepCount <= 0) { halt(node, mFrame, false); @@ -557,13 +605,13 @@ strategyTrace("RESUME AFTER", ""); } } - }); + }, "Debugger StepOver"); } @Override protected void unsetStrategy() { - instrumenter.setBeforeTagTrap(null); - instrumenter.setAfterTagTrap(null); + beforeTagInstrument.dispose(); + afterTagInstrument.dispose(); } } @@ -581,6 +629,7 @@ * </ul> */ private final class StepOverNested extends StepStrategy { + private TagInstrument beforeTagInstrument; private int unfinishedStepCount; private final int startStackDepth; @@ -591,28 +640,28 @@ @Override protected void setStrategy(final int stackDepth) { - instrumenter.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) { + beforeTagInstrument = instrumenter.attach(STEPPING_TAG, new StandardBeforeInstrumentListener() { @TruffleBoundary @Override - public void tagTrappedAt(Node node, MaterializedFrame mFrame) { + public void onEnter(Probe probe, Node node, VirtualFrame vFrame) { final int currentStackDepth = currentStackDepth(); if (currentStackDepth <= startStackDepth) { // At original step depth (or smaller) after being nested --unfinishedStepCount; - strategyTrace("TRAP AFTER", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth); + strategyTrace("HALT AFTER", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth); if (unfinishedStepCount <= 0) { - halt(node, mFrame, false); + halt(node, vFrame.materialize(), false); } // TODO (mlvdv) fixme for multiple steps strategyTrace("RESUME BEFORE", ""); } } - }); + }, "Debuger StepOverNested"); } @Override protected void unsetStrategy() { - instrumenter.setBeforeTagTrap(null); + beforeTagInstrument.dispose(); } }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java Fri Sep 25 14:58:35 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java Sun Sep 27 21:34:39 2015 -0700 @@ -46,11 +46,10 @@ 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.ProbeInstrument; import com.oracle.truffle.api.instrument.Instrumenter; import com.oracle.truffle.api.instrument.Probe; +import com.oracle.truffle.api.instrument.ProbeInstrument; import com.oracle.truffle.api.instrument.SyntaxTag; -import com.oracle.truffle.api.instrument.SyntaxTagTrap; import com.oracle.truffle.api.instrument.impl.DefaultProbeListener; import com.oracle.truffle.api.instrument.impl.DefaultStandardInstrumentListener; import com.oracle.truffle.api.nodes.InvalidAssumptionException; @@ -63,18 +62,20 @@ * Support class for creating and managing "Tag Breakpoints". A Tag Breakpoint halts execution just * before reaching any node whose Probe carries a specified {@linkplain SyntaxTag Tag}. * <p> - * The {@linkplain Instrumenter#setBeforeTagTrap(SyntaxTagTrap) Tag Trap}, which is built directly - * into the Instrumentation Framework, does the same thing more efficiently, but there may only be - * one Tag Trap active at a time. Any number of tag breakpoints may coexist with the Tag Trap, but - * it would be confusing to have a Tag Breakpoint set for the same Tag as the current Tag Trap. + * The + * {@linkplain Instrumenter#attach(SyntaxTag, com.oracle.truffle.api.instrument.StandardBeforeInstrumentListener, String) + * before TagInstrument}, does the same thing more efficiently, but there may only be one + * <em>before</em> TagInstrument active at a time. Any number of {@link TagBreakpoint}s may coexist + * with the <em>before</em> TagInstrument, but it would be confusing to have a {@link TagBreakpoint} + * set for the same Tag as the current <em>before</em> TagInstrument. * <p> * Notes: * <ol> * <li>Only one Tag Breakpoint can be active for a specific {@linkplain SyntaxTag Tag}.</li> * <li>A newly created breakpoint looks for probes matching the tag, attaches to them if found by * installing an {@link ProbeInstrument}.</li> - * <li>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.</li> + * <li>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.</li> * <li>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 * location.</li>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Sun Sep 27 21:34:39 2015 -0700 @@ -0,0 +1,57 @@ +/* + * 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; + +/** + * A <em>binding</em> between: + * <ol> + * <li>Some source of <em>execution events</em> in an executing Truffle AST, and</li> + * <li>A <em>listener</em>: a consumer of execution events on behalf of an external client. + * </ol> + * <p> + * Client-oriented documentation for the use of Instruments is available online at <a + * HREF="https://wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events" >https:// + * wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events</a> + * + * @See Instrumenter + */ +abstract class Instrument { + + protected Instrument() { + } + + /** + * Removes this from its source of execution events and renders itself Instrument inert. + * + * @throws IllegalStateException if this has already been disposed + */ + public abstract void dispose() throws IllegalStateException; + + /** + * Has this been detached from its source of execution events. + */ + public abstract boolean isDisposed(); + +}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java Fri Sep 25 14:58:35 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java Sun Sep 27 21:34:39 2015 -0700 @@ -37,6 +37,8 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.impl.Accessor; +import com.oracle.truffle.api.instrument.TagInstrument.AfterTagInstrument; +import com.oracle.truffle.api.instrument.TagInstrument.BeforeTagInstrument; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; @@ -80,7 +82,8 @@ * <ul> * <li>A newly created tool is inert until {@linkplain Instrumenter#install(Tool) installed}.</li> * <li>An installed tool becomes <em>enabled</em> and immediately begins installing - * {@linkplain ProbeInstrument instrumentation} on ASTs and collecting execution data from them.</li> + * {@linkplain ProbeInstrument instrumentation} on ASTs and collecting execution data from them. + * </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> @@ -231,24 +234,24 @@ private final List<WeakReference<Probe>> probes = new ArrayList<>(); /** - * A global trap that triggers notification just before executing any Node that is Probed with a - * matching tag. + * A global instrument that triggers notification just before executing any Node that is Probed + * with a matching tag. */ - @CompilationFinal private SyntaxTagTrap beforeTagTrap = null; + @CompilationFinal private BeforeTagInstrument beforeTagInstrument = null; /** - * A global trap that triggers notification just after executing any Node that is Probed with a - * matching tag. + * A global instrument that triggers notification just after executing any Node that is Probed + * with a matching tag. */ - @CompilationFinal private SyntaxTagTrap afterTagTrap = null; + @CompilationFinal private AfterTagInstrument afterTagInstrument = null; Instrumenter(Object vm) { this.vm = vm; } /** - * 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. + * 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. * <p> * <em>Probing</em> a node is idempotent: * <ul> @@ -357,54 +360,6 @@ return taggedProbes; } - // TODO (mlvdv) generalize to permit multiple "before traps" without a performance hit? - /** - * Sets the current "<em>before</em> tag trap"; there can be no more than one in effect. - * <ul> - * <li>The before-trap triggers a callback just <strong><em>before</em></strong> execution - * reaches <strong><em>any</em></strong> {@link Probe} (either existing or subsequently created) - * with the specified {@link SyntaxTag}.</li> - * <li>Setting the before-trap to {@code null} clears an existing before-trap.</li> - * <li>Setting a non{@code -null} before-trap when one is already set clears the previously set - * before-trap.</li> - * </ul> - * - * @param newBeforeTagTrap The new "before" {@link SyntaxTagTrap} to set. - */ - public void setBeforeTagTrap(SyntaxTagTrap newBeforeTagTrap) { - beforeTagTrap = newBeforeTagTrap; - for (WeakReference<Probe> ref : probes) { - final Probe probe = ref.get(); - if (probe != null) { - probe.notifyTrapsChanged(); - } - } - } - - // TODO (mlvdv) generalize to permit multiple "after traps" without a performance hit? - /** - * Sets the current "<em>after</em> tag trap"; there can be no more than one in effect. - * <ul> - * <li>The after-trap triggers a callback just <strong><em>after</em></strong> execution leaves - * <strong><em>any</em></strong> {@link Probe} (either existing or subsequently created) with - * the specified {@link SyntaxTag}.</li> - * <li>Setting the after-trap to {@code null} clears an existing after-trap.</li> - * <li>Setting a non{@code -null} after-trap when one is already set clears the previously set - * after-trap.</li> - * </ul> - * - * @param newAfterTagTrap The new "after" {@link SyntaxTagTrap} to set. - */ - public void setAfterTagTrap(SyntaxTagTrap newAfterTagTrap) { - afterTagTrap = newAfterTagTrap; - for (WeakReference<Probe> ref : probes) { - final Probe probe = ref.get(); - if (probe != null) { - probe.notifyTrapsChanged(); - } - } - } - /** * Enables instrumentation at selected nodes in all subsequently constructed ASTs. Ignored if * the argument is already registered, runtime error if argument is {@code null}. @@ -486,6 +441,66 @@ return instrument; } + // TODO (mlvdv) allow multiple <em>before</em> instruments without performance hit? + /** + * Sets the current "<em>before</em>" TagInstrument; there can be no more than one in effect. + * <ul> + * <li>The Instrument triggers a callback just <strong><em>before</em></strong> execution + * reaches <strong><em>any</em></strong> {@link Probe} (either existing or subsequently created) + * with the specified {@link SyntaxTag}.</li> + * <li>Calling {@link TagInstrument#dispose()} removes the instrument.</li> + * </ul> + * + * @param tag identifies the nodes to be instrumented + * @param listener receiver of <em>before</em> execution events + * @param instrumentInfo optional, mainly for debugging. + * @return a newly created, active Instrument + * @throws IllegalStateException if called when a <em>before</em> Instrument is active. + */ + public TagInstrument attach(SyntaxTag tag, StandardBeforeInstrumentListener listener, String instrumentInfo) { + if (beforeTagInstrument != null) { + throw new IllegalStateException("Only one 'before' TagInstrument at a time"); + } + this.beforeTagInstrument = new TagInstrument.BeforeTagInstrument(tag, listener, instrumentInfo); + for (WeakReference<Probe> ref : probes) { + final Probe probe = ref.get(); + if (probe != null) { + probe.notifyTagInstrumentsChanged(); + } + } + return beforeTagInstrument; + } + + // TODO (mlvdv) allow multiple <em>after</em> instruments without performance hit? + /** + * Sets the current "<em>after</em>" TagInstrument; there can be no more than one in effect. + * <ul> + * <li>The Instrument triggers a callback just <strong><em>after</em></strong> execution reaches + * <strong><em>any</em></strong> {@link Probe} (either existing or subsequently created) with + * the specified {@link SyntaxTag}.</li> + * <li>Calling {@link TagInstrument#dispose()} removes the instrument.</li> + * </ul> + * + * @param tag identifies the nodes to be instrumented + * @param listener receiver of <em>after</em> execution events + * @param instrumentInfo optional, mainly for debugging. + * @return a newly created, active Instrument + * @throws IllegalStateException if called when a <em>after</em> Instrument is active. + */ + public TagInstrument attach(SyntaxTag tag, StandardAfterInstrumentListener listener, String instrumentInfo) { + if (afterTagInstrument != null) { + throw new IllegalStateException("Only one 'afater' TagInstrument at a time"); + } + this.afterTagInstrument = new TagInstrument.AfterTagInstrument(tag, listener, instrumentInfo); + for (WeakReference<Probe> ref : probes) { + final Probe probe = ref.get(); + if (probe != null) { + probe.notifyTagInstrumentsChanged(); + } + } + return afterTagInstrument; + } + /** * Connects the tool to some part of the Truffle runtime, and enable data collection to start. * @@ -514,12 +529,12 @@ } } - SyntaxTagTrap getBeforeTagTrap() { - return beforeTagTrap; + BeforeTagInstrument getBeforeTagInstrument() { + return beforeTagInstrument; } - SyntaxTagTrap getAfterTagTrap() { - return afterTagTrap; + AfterTagInstrument getAfterTagInstrument() { + return afterTagInstrument; } // TODO (mlvdv) build this in as a VM event?
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Fri Sep 25 14:58:35 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Sun Sep 27 21:34:39 2015 -0700 @@ -34,6 +34,8 @@ import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.instrument.TagInstrument.AfterTagInstrument; +import com.oracle.truffle.api.instrument.TagInstrument.BeforeTagInstrument; import com.oracle.truffle.api.nodes.InvalidAssumptionException; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.SourceSection; @@ -44,12 +46,13 @@ * <ol> * <li>A <em>guest language program location</em> in an executing Truffle AST (corresponding to a * {@link SourceSection}), and</li> - * <li>A dynamically managed collection of <em>attached</em> {@linkplain ProbeInstrument Instruments} - * that receive event notifications from the Probe's AST location on behalf of external clients.</li> + * <li>A dynamically managed collection of <em>attached</em> {@linkplain Instrument Instruments} + * that receive event notifications on behalf of external clients.</li> * </ol> - * <strong>Note</strong>:The relationship must be with an AST <em>location</em>, not a specific - * {@link Node}, because ASTs are routinely <em>cloned</em> at runtime. An AST <em>location</em> is - * best represented as the {@link SourceSection} from which the original AST Node was created. + * <strong>Note</strong>:The relationship for {@link ProlbeInstrument} must be with an AST + * <em>location</em>, not a specific {@link Node}, because ASTs are routinely <em>cloned</em> at + * runtime. An AST <em>location</em> is best represented as the {@link SourceSection} from which the + * original AST Node was created. * <p> * Client-oriented documentation for the use of Probes is available online at <a * HREF="https://wiki.openjdk.java.net/display/Graal/Finding+Probes" >https://wiki.openjdk.java. @@ -94,10 +97,10 @@ @CompilationFinal private Assumption probeStateUnchangedAssumption = probeStateUnchangedCyclic.getAssumption(); // Must invalidate whenever changed - @CompilationFinal private boolean isBeforeTrapActive = false; + @CompilationFinal private boolean isBeforeTagInstrumentActive = false; // Must invalidate whenever changed - @CompilationFinal private boolean isAfterTrapActive = false; + @CompilationFinal private boolean isAfterTagInstrumentActive = false; /** * Constructor for use only by {@link ProbeNode}. @@ -130,7 +133,8 @@ * <li>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 ProbeInstrument Instruments} attached to the Probe's <em>instrument chain</em>.</li> + * the {@linkplain ProbeInstrument Instruments} attached to the Probe's + * <em>instrument chain</em>.</li> * * <li>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 @@ -163,19 +167,19 @@ tags.add(tag); instrumenter.tagAdded(this, tag, tagValue); - // Update the status of this Probe with respect to global tag traps - boolean tagTrapsChanged = false; - final SyntaxTagTrap beforeTagTrap = instrumenter.getBeforeTagTrap(); - if (beforeTagTrap != null && tag == beforeTagTrap.getTag()) { - this.isBeforeTrapActive = true; - tagTrapsChanged = true; + // Update the status of this Probe with respect to global TagInstruments + boolean tagInstrumentsChanged = false; + final BeforeTagInstrument beforeTagInstrument = instrumenter.getBeforeTagInstrument(); + if (beforeTagInstrument != null && tag == beforeTagInstrument.getTag()) { + this.isBeforeTagInstrumentActive = true; + tagInstrumentsChanged = true; } - final SyntaxTagTrap afterTagTrap = instrumenter.getAfterTagTrap(); - if (afterTagTrap != null && tag == afterTagTrap.getTag()) { - this.isAfterTrapActive = true; - tagTrapsChanged = true; + final AfterTagInstrument afterTagInstrument = instrumenter.getAfterTagInstrument(); + if (afterTagInstrument != null && tag == afterTagInstrument.getTag()) { + this.isAfterTagInstrumentActive = true; + tagInstrumentsChanged = true; } - if (tagTrapsChanged) { + if (tagInstrumentsChanged) { invalidateProbeUnchanged(); } if (TRACE) { @@ -264,25 +268,23 @@ } /** - * Gets the currently active <strong><em>before</em></strong> {@linkplain SyntaxTagTrap Tag - * Trap} at this Probe. Non{@code -null} if the global - * {@linkplain Instrumenter#setBeforeTagTrap(SyntaxTagTrap) Before Tag Trap} is set and if this - * Probe holds the {@link SyntaxTag} specified in the trap. + * Gets the currently active {@linkplain BeforeTagInstrument} at this Probe. Non{@code -null} if + * the global {@linkplain BeforeTagInstrument} is set and if this Probe holds the + * {@link SyntaxTag} specified in the instrument. */ - SyntaxTagTrap getBeforeTrap() { + BeforeTagInstrument getBeforeTagInstrument() { checkProbeUnchanged(); - return isBeforeTrapActive ? instrumenter.getBeforeTagTrap() : null; + return isBeforeTagInstrumentActive ? instrumenter.getBeforeTagInstrument() : null; } /** - * Gets the currently active <strong><em>after</em></strong> {@linkplain SyntaxTagTrap Tag Trap} - * at this Probe. Non{@code -null} if the global - * {@linkplain Instrumenter#setAfterTagTrap(SyntaxTagTrap) After Tag Trap} is set and if this - * Probe holds the {@link SyntaxTag} specified in the trap. + * Gets the currently active {@linkplain AfterTagInstrument} at this Probe. Non{@code -null} if + * the global {@linkplain BeforeTagInstrument} is set and if this Probe holds the + * {@link SyntaxTag} specified in the instrument. */ - SyntaxTagTrap getAfterTrap() { + AfterTagInstrument getAfterTagInstrument() { checkProbeUnchanged(); - return isAfterTrapActive ? instrumenter.getAfterTagTrap() : null; + return isAfterTagInstrumentActive ? instrumenter.getAfterTagInstrument() : null; } Class<? extends TruffleLanguage> getLanguage() { @@ -307,11 +309,11 @@ probeStateUnchangedCyclic.invalidate(); } - void notifyTrapsChanged() { - final SyntaxTagTrap beforeTagTrap = instrumenter.getBeforeTagTrap(); - this.isBeforeTrapActive = beforeTagTrap != null && this.isTaggedAs(beforeTagTrap.getTag()); - final SyntaxTagTrap afterTagTrap = instrumenter.getAfterTagTrap(); - this.isAfterTrapActive = afterTagTrap != null && this.isTaggedAs(afterTagTrap.getTag()); + void notifyTagInstrumentsChanged() { + final BeforeTagInstrument beforeTagInstrument = instrumenter.getBeforeTagInstrument(); + this.isBeforeTagInstrumentActive = beforeTagInstrument != null && this.isTaggedAs(beforeTagInstrument.getTag()); + final AfterTagInstrument afterTagInstrument = instrumenter.getAfterTagInstrument(); + this.isAfterTagInstrumentActive = afterTagInstrument != null && this.isTaggedAs(afterTagInstrument.getTag()); invalidateProbeUnchanged(); }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java Fri Sep 25 14:58:35 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java Sun Sep 27 21:34:39 2015 -0700 @@ -45,9 +45,14 @@ * wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events</a> * * @see Probe - * @see EventHandlerNode + * @see Instrumenter */ -public abstract class ProbeInstrument { +public abstract class ProbeInstrument extends Instrument { + + /** + * Optional documentation, mainly for debugging. + */ + private final String instrumentInfo; /** * Has this instrument been disposed? stays true once set. @@ -57,11 +62,6 @@ protected Probe probe = null; /** - * Optional documentation, mainly for debugging. - */ - private final String instrumentInfo; - - /** * <h4>Implementation Notes</h4> * <p> * The implementation of Instruments is complicated by the requirement that Truffle be able to @@ -86,9 +86,9 @@ * * <li>Multiple Instruments may share a single listener.</li> * - * <li>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.</li> + * <li>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.</li> * * <li>Neither Instruments nor Probes are {@link Node}s.</li> * @@ -121,19 +121,12 @@ } /** - * 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 */ + @Override public void dispose() throws IllegalStateException { if (isDisposed) { throw new IllegalStateException("Attempt to dispose an already disposed Instrumennt"); @@ -146,6 +139,19 @@ this.isDisposed = true; } + @Override + public boolean isDisposed() { + return isDisposed; + } + + /** + * 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; + } + /** * For internal implementation only. */ @@ -153,13 +159,6 @@ this.probe = probe; } - /** - * Has this instrument been disposed and rendered unusable? - */ - boolean isDisposed() { - return isDisposed; - } - abstract AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode); /**
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Fri Sep 25 14:58:35 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Sun Sep 27 21:34:39 2015 -0700 @@ -28,6 +28,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrument.ProbeInstrument.AbstractInstrumentNode; +import com.oracle.truffle.api.instrument.TagInstrument.AfterTagInstrument; +import com.oracle.truffle.api.instrument.TagInstrument.BeforeTagInstrument; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; @@ -36,14 +38,14 @@ * Implementation class & interface for enabling the attachment of {@linkplain Probe Probes} to * Truffle ASTs. * <p> - * 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. + * 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. * <p> - * 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 + * 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 * clones consistent. */ @NodeInfo(cost = NodeCost.NONE) @@ -74,9 +76,9 @@ @Override public void enter(Node node, VirtualFrame vFrame) { this.probe.checkProbeUnchanged(); - final SyntaxTagTrap beforeTagTrap = probe.getBeforeTrap(); - if (beforeTagTrap != null) { - beforeTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); + final BeforeTagInstrument beforeTagInstrument = probe.getBeforeTagInstrument(); + if (beforeTagInstrument != null) { + beforeTagInstrument.getListener().onEnter(probe, ((WrapperNode) this.getParent()).getChild(), vFrame); } if (firstInstrumentNode != null) { firstInstrumentNode.enter(node, vFrame); @@ -89,9 +91,9 @@ if (firstInstrumentNode != null) { firstInstrumentNode.returnVoid(node, vFrame); } - final SyntaxTagTrap afterTagTrap = probe.getAfterTrap(); - if (afterTagTrap != null) { - afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); + final AfterTagInstrument afterTagInstrument = probe.getAfterTagInstrument(); + if (afterTagInstrument != null) { + afterTagInstrument.getListener().onReturnVoid(probe, ((WrapperNode) this.getParent()).getChild(), vFrame); } } @@ -101,9 +103,9 @@ if (firstInstrumentNode != null) { firstInstrumentNode.returnValue(node, vFrame, result); } - final SyntaxTagTrap afterTagTrap = probe.getAfterTrap(); - if (afterTagTrap != null) { - afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); + final AfterTagInstrument afterTagInstrument = probe.getAfterTagInstrument(); + if (afterTagInstrument != null) { + afterTagInstrument.getListener().onReturnValue(probe, ((WrapperNode) this.getParent()).getChild(), vFrame, result); } } @@ -113,9 +115,9 @@ if (firstInstrumentNode != null) { firstInstrumentNode.returnExceptional(node, vFrame, exception); } - final SyntaxTagTrap afterTagTrap = probe.getAfterTrap(); - if (afterTagTrap != null) { - afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); + final AfterTagInstrument afterTagInstrument = probe.getAfterTagInstrument(); + if (afterTagInstrument != null) { + afterTagInstrument.getListener().onReturnExceptional(probe, ((WrapperNode) this.getParent()).getChild(), vFrame, exception); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardAfterInstrumentListener.java Sun Sep 27 21:34:39 2015 -0700 @@ -0,0 +1,72 @@ +/* + * 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.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.source.SourceSection; + +/** + * A receiver of Truffle AST <em>after</em> execution events that can act on behalf of an external + * client. + * <p> + * The {@link Probe} argument provides access to the {@link SourceSection} associated with the + * event, as well as any {@link SyntaxTag}s that have been applied at that program's location. + * <p> + * This listener is designed for clients that also require access to the AST execution state at the + * time of the event. Clients that do not require access to the AST execution state should use the + * {@link SimpleInstrumentListener}. + * <p> + * 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 ProbeInstrument} + * that is to be created from the listener. + * <p> + * Notification is fully synchronous, so overrides have performance implications. Non-trivial + * methods should be coded with Truffle guidelines and cautions in mind. + */ +public interface StandardAfterInstrumentListener { + + /** + * Receive notification that an AST Node's {@code void}-valued execute method has just returned. + * <p> + * <strong>Synchronous</strong>: Truffle execution waits until the call returns. + */ + void onReturnVoid(Probe probe, Node node, VirtualFrame vFrame); + + /** + * Receive notification that an AST Node's execute method has just returned a value (boxed if + * primitive). + * <p> + * <strong>Synchronous</strong>: Truffle execution waits until the call returns. + */ + void onReturnValue(Probe probe, Node node, VirtualFrame vFrame, Object result); + + /** + * Receive notification that an AST Node's execute method has just thrown an exception. + * <p> + * <strong>Synchronous</strong>: Truffle execution waits until the call returns. + */ + void onReturnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardBeforeInstrumentListener.java Sun Sep 27 21:34:39 2015 -0700 @@ -0,0 +1,57 @@ +/* + * 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.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.source.SourceSection; + +/** + * A receiver of Truffle AST <em>before</em> execution events that can act on behalf of an external client. + * <p> + * The {@link Probe} argument provides access to the {@link SourceSection} associated with the + * event, as well as any {@link SyntaxTag}s that have been applied at that program's location. + * <p> + * This listener is designed for clients that also require access to the AST execution state at the + * time of the event. Clients that do not require access to the AST execution state should use the + * {@link SimpleInstrumentListener}. + * <p> + * 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 ProbeInstrument} + * that is to be created from the listener. + * <p> + * Notification is fully synchronous, so overrides have performance implications. Non-trivial + * methods should be coded with Truffle guidelines and cautions in mind. + */ +public interface StandardBeforeInstrumentListener { + + /** + * Receive notification that an AST node's execute method is about to be called. + * <p> + * <strong>Synchronous</strong>: Truffle execution waits until the call returns. + */ + void onEnter(Probe probe, Node node, VirtualFrame vFrame); + +}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagTrap.java Fri Sep 25 14:58:35 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2014, 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.frame.MaterializedFrame; -import com.oracle.truffle.api.nodes.Node; - -/** - * A trap that can be set to interrupt execution at probed nodes carrying a specific tag. - * - * @see Probe - */ -public abstract class SyntaxTagTrap { - - private final SyntaxTag tag; - - protected SyntaxTagTrap(SyntaxTag tag) { - this.tag = tag; - } - - public final SyntaxTag getTag() { - return tag; - } - - /** - * Notifies that execution is halted at a node with the specified tag. - */ - public abstract void tagTrappedAt(Node node, MaterializedFrame frame); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TagInstrument.java Sun Sep 27 21:34:39 2015 -0700 @@ -0,0 +1,106 @@ +/* + * 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; + +/** + * A <em>binding</em> between: + * <ol> + * <li>A {@link SyntaxTag} that specifies nodes to act as source of <em>execution events</em> taking + * place at a program location in an executing Truffle AST, and</li> + * <li>A <em>listener</em>: a consumer of execution events on behalf of an external client. + * </ol> + * <p> + * Client-oriented documentation for the use of Instruments is available online at <a + * HREF="https://wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events" >https:// + * wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events</a> + * + * @see SyntaxTag + * @see Instrumenter + */ +public abstract class TagInstrument extends Instrument { + + /** + * Optional documentation, mainly for debugging. + */ + @SuppressWarnings("unused") private final String instrumentInfo; + + /** + * Has this instrument been disposed? stays true once set. + */ + private boolean isDisposed = false; + + private SyntaxTag tag = null; + + protected TagInstrument(SyntaxTag tag, String instrumentInfo) { + this.tag = tag; + this.instrumentInfo = instrumentInfo; + } + + @Override + public void dispose() throws IllegalStateException { + if (isDisposed) { + throw new IllegalStateException("Attempt to dispose an already disposed Instrumennt"); + } + + // TODO (mlvdv) + this.isDisposed = true; + } + + @Override + public boolean isDisposed() { + return isDisposed; + } + + public SyntaxTag getTag() { + return tag; + } + + static final class BeforeTagInstrument extends TagInstrument { + + private final StandardBeforeInstrumentListener listener; + + BeforeTagInstrument(SyntaxTag tag, StandardBeforeInstrumentListener listener, String instrumentInfo) { + super(tag, instrumentInfo); + this.listener = listener; + } + + StandardBeforeInstrumentListener getListener() { + return listener; + } + } + + static final class AfterTagInstrument extends TagInstrument { + + private final StandardAfterInstrumentListener listener; + + AfterTagInstrument(SyntaxTag tag, StandardAfterInstrumentListener listener, String instrumentInfo) { + super(tag, instrumentInfo); + this.listener = listener; + } + + StandardAfterInstrumentListener getListener() { + return listener; + } + } +}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/package-info.java Fri Sep 25 14:58:35 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/package-info.java Sun Sep 27 21:34:39 2015 -0700 @@ -145,25 +145,25 @@ * location, where it will be executed subject to full Truffle optimization.</li> * </ul></li> * - * <li><strong>Wide-area Instrumentation: traps</strong> + * <li><strong>Wide-area Instrumentation: TagInstruments</strong> * <ul> * <li>A specialized form of Instrumentation is provided that efficiently attaches a single * listener called a - * {@linkplain com.oracle.truffle.api.instrument.SyntaxTagTrap tag trap} to every + * {@linkplain com.oracle.truffle.api.instrument.StandardBeforeInstrumentListener StandardBeforeInstrumentListener} to every * {@linkplain com.oracle.truffle.api.instrument.Probe Probe} containing a specified * {@linkplain com.oracle.truffle.api.instrument.SyntaxTag tag}.</li> * <li>One (but no more than one) - * {@linkplain com.oracle.truffle.api.instrument.SyntaxTagTrap tag trap} may optionally be set - * to be notified <em>before</em> every <em>AST execution event</em> where the specified + * {@linkplain com.oracle.truffle.api.instrument.StandardBeforeInstrumentListener StandardBeforeInstrumentListener} + * may optionally be attached for notification <em>before</em> every <em>AST execution event</em> where the specified * {@linkplain com.oracle.truffle.api.instrument.SyntaxTag tag} is present.</li> * <li>One (but no more than one) - * {@linkplain com.oracle.truffle.api.instrument.SyntaxTagTrap tag trap} may optionally be set - * to be notified <em>after</em> every <em>AST execution event</em> where the specified + * {@linkplain com.oracle.truffle.api.instrument.StandardBeforeInstrumentListener StandardBeforeInstrumentListener} + * may optionally be attached for notification <em>after</em> every <em>AST execution event</em> where the specified * {@linkplain com.oracle.truffle.api.instrument.SyntaxTag tag} is present.</li> * <li>The - * {@linkplain com.oracle.truffle.api.instrument.SyntaxTagTrap tag trap} mechanism is independent + * {@linkplain com.oracle.truffle.api.instrument.TagInstrument TagInstrument} mechanism is independent * of listeners that may be attached to - * {@linkplain com.oracle.truffle.api.instrument.Probe Probe}. It is especially valuable for + * {@linkplain com.oracle.truffle.api.instrument.Probe Probes}. It is especially valuable for * applications such as the debugger, where during "stepping" the program should be halted at * any node tagged with * {@linkplain com.oracle.truffle.api.instrument.StandardSyntaxTag#STATEMENT STATEMENT}.</li>