Mercurial > hg > truffle
diff truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java @ 22219:1c0f490984d5
Merge with f47b601edbc626dcfe8b3636933b4834c89f7779
author | Michael Van De Vanter <michael.van.de.vanter@oracle.com> |
---|---|
date | Wed, 16 Sep 2015 15:36:22 -0700 |
parents | dc83cc1f94f2 3aad794eec0e |
children | 776dc0a09749 |
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Wed Sep 16 12:27:08 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Wed Sep 16 15:36:22 2015 -0700 @@ -24,18 +24,6 @@ */ package com.oracle.truffle.api.instrument; -import com.oracle.truffle.api.Assumption; -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.InstrumentationNode.TruffleEvents; -import com.oracle.truffle.api.nodes.InvalidAssumptionException; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.nodes.NodeVisitor; -import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.api.utilities.CyclicAssumption; import java.io.PrintStream; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -43,7 +31,14 @@ import java.util.Collections; import java.util.List; -//TODO (mlvdv) these statics should not be global. Move them to some kind of context. +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.InstrumentationNode.TruffleEvents; +import com.oracle.truffle.api.nodes.InvalidAssumptionException; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.api.utilities.CyclicAssumption; /** * A <em>binding</em> between: @@ -75,13 +70,14 @@ * arriving at the "probed" AST Node and notify each attached {@link Instrument} before execution is * allowed to proceed to the child and again after execution completes.</li> * - * <li>The method {@link Node#probe()} creates a Probe on an AST Node; redundant calls return the - * same Probe.</li> + * <li>The method {@link Instrumenter#probe(Node)} creates a Probe on an AST Node; redundant calls + * return the same Probe.</li> * * <li>The "probing" of a Truffle AST must be done after the AST is complete (i.e. parent pointers - * correctly assigned), but before any cloning or executions. This is done by creating an instance - * of {@link ASTProber} and registering it via {@link #registerASTProber(ASTProber)}. Once - * registered, it will be applied automatically to every newly created AST.</li> + * correctly assigned), but before any cloning or executions. This is done by applying instances of + * {@link ASTProber} provided by each language implementation, combined with any instances + * registered by tools via {@link Instrumenter#registerASTProber(ASTProber)}. Once registered, these + * will be applied automatically to every newly created AST.</li> * * <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 @@ -121,173 +117,7 @@ } } - private static final List<ASTProber> astProbers = new ArrayList<>(); - - private static final List<ProbeListener> probeListeners = new ArrayList<>(); - - /** - * All Probes that have been created. - */ - private static 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. - */ - @CompilationFinal private static SyntaxTagTrap beforeTagTrap = null; - - /** - * A global trap that triggers notification just after executing any Node that is Probed with a - * matching tag. - */ - @CompilationFinal private static SyntaxTagTrap afterTagTrap = null; - - private static final class FindSourceVisitor implements NodeVisitor { - - Source source = null; - - public boolean visit(Node node) { - final SourceSection sourceSection = node.getSourceSection(); - if (sourceSection != null) { - source = sourceSection.getSource(); - return false; - } - return true; - } - } - - /** - * Walks an AST, looking for the first node with an assigned {@link SourceSection} and returning - * the {@link Source}. - */ - private static Source findSource(Node node) { - final FindSourceVisitor visitor = new FindSourceVisitor(); - node.accept(visitor); - return visitor.source; - } - - /** - * Enables instrumentation at selected nodes in all subsequently constructed ASTs. - */ - public static void registerASTProber(ASTProber prober) { - astProbers.add(prober); - } - - public static void unregisterASTProber(ASTProber prober) { - astProbers.remove(prober); - } - - /** - * Enables instrumentation in a newly created AST by applying all registered instances of - * {@link ASTProber}. - */ - public static void applyASTProbers(Node node) { - - String name = "<?>"; - final Source source = findSource(node); - if (source != null) { - name = source.getShortName(); - } else { - final SourceSection sourceSection = node.getEncapsulatingSourceSection(); - if (sourceSection != null) { - name = sourceSection.getShortDescription(); - } - } - trace("START %s", name); - for (ProbeListener listener : probeListeners) { - listener.startASTProbing(source); - } - for (ASTProber prober : astProbers) { - prober.probeAST(node); - } - for (ProbeListener listener : probeListeners) { - listener.endASTProbing(source); - } - trace("FINISHED %s", name); - } - - /** - * Adds a {@link ProbeListener} to receive events. - */ - public static void addProbeListener(ProbeListener listener) { - assert listener != null; - probeListeners.add(listener); - } - - /** - * Removes a {@link ProbeListener}. Ignored if listener not found. - */ - public static void removeProbeListener(ProbeListener listener) { - probeListeners.remove(listener); - } - - /** - * Returns all {@link Probe}s holding a particular {@link SyntaxTag}, or the whole collection of - * probes if the specified tag is {@code null}. - * - * @return A collection of probes containing the given tag. - */ - public static Collection<Probe> findProbesTaggedAs(SyntaxTag tag) { - final List<Probe> taggedProbes = new ArrayList<>(); - for (WeakReference<Probe> ref : probes) { - Probe probe = ref.get(); - if (probe != null) { - if (tag == null || probe.isTaggedAs(tag)) { - taggedProbes.add(ref.get()); - } - } - } - 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 static 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 static void setAfterTagTrap(SyntaxTagTrap newAfterTagTrap) { - afterTagTrap = newAfterTagTrap; - for (WeakReference<Probe> ref : probes) { - final Probe probe = ref.get(); - if (probe != null) { - probe.notifyTrapsChanged(); - } - } - } - + private final Instrumenter instrumenter; private final SourceSection sourceSection; private final ArrayList<SyntaxTag> tags = new ArrayList<>(); private final List<WeakReference<ProbeNode>> probeNodeClones = new ArrayList<>(); @@ -313,17 +143,10 @@ /** * Intended for use only by {@link ProbeNode}. */ - Probe(Class<? extends TruffleLanguage> l, ProbeNode probeNode, SourceSection sourceSection) { + Probe(Instrumenter instrumenter, Class<? extends TruffleLanguage> l, ProbeNode probeNode, SourceSection sourceSection) { + this.instrumenter = instrumenter; this.sourceSection = sourceSection; - probes.add(new WeakReference<>(this)); registerProbeNodeClone(probeNode); - if (TRACE) { - final String location = this.sourceSection == null ? "<unknown>" : sourceSection.getShortDescription(); - trace("ADDED %s %s %s", "Probe@", location, getTagsDescription()); - } - for (ProbeListener listener : probeListeners) { - listener.newProbeInserted(this); - } this.language = l; } @@ -351,16 +174,16 @@ assert tag != null; if (!tags.contains(tag)) { tags.add(tag); - for (ProbeListener listener : probeListeners) { - listener.probeTaggedAs(this, tag, tagValue); - } + 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; } + final SyntaxTagTrap afterTagTrap = instrumenter.getAfterTagTrap(); if (afterTagTrap != null && tag == afterTagTrap.getTag()) { this.isAfterTrapActive = true; tagTrapsChanged = true; @@ -439,23 +262,27 @@ /** * Gets the currently active <strong><em>before</em></strong> {@linkplain SyntaxTagTrap Tag * Trap} at this Probe. Non{@code -null} if the global - * {@linkplain Probe#setBeforeTagTrap(SyntaxTagTrap) Before Tag Trap} is set and if this Probe - * holds the {@link SyntaxTag} specified in the trap. + * {@linkplain Instrumenter#setBeforeTagTrap(SyntaxTagTrap) Before Tag Trap} is set and if this + * Probe holds the {@link SyntaxTag} specified in the trap. */ SyntaxTagTrap getBeforeTrap() { checkProbeUnchanged(); - return isBeforeTrapActive ? beforeTagTrap : null; + return isBeforeTrapActive ? instrumenter.getBeforeTagTrap() : null; } /** * Gets the currently active <strong><em>after</em></strong> {@linkplain SyntaxTagTrap Tag Trap} * at this Probe. Non{@code -null} if the global - * {@linkplain Probe#setAfterTagTrap(SyntaxTagTrap) After Tag Trap} is set and if this Probe - * holds the {@link SyntaxTag} specified in the trap. + * {@linkplain Instrumenter#setAfterTagTrap(SyntaxTagTrap) After Tag Trap} is set and if this + * Probe holds the {@link SyntaxTag} specified in the trap. */ SyntaxTagTrap getAfterTrap() { checkProbeUnchanged(); - return isAfterTrapActive ? afterTagTrap : null; + return isAfterTrapActive ? instrumenter.getAfterTagTrap() : null; + } + + Class<? extends TruffleLanguage> getLanguage() { + return language; } /** @@ -476,13 +303,15 @@ probeStateUnchangedCyclic.invalidate(); } - private void notifyTrapsChanged() { + 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()); invalidateProbeUnchanged(); } - private String getTagsDescription() { + String getTagsDescription() { final StringBuilder sb = new StringBuilder(); sb.append("["); String prefix = ""; @@ -494,18 +323,4 @@ sb.append("]"); return sb.toString(); } - - static final class AccessorInstrument extends Accessor { - @Override - protected Class<? extends TruffleLanguage> findLanguage(RootNode n) { - return super.findLanguage(n); - } - - @Override - protected Class<? extends TruffleLanguage> findLanguage(Probe probe) { - return probe.language; - } - } - - static final AccessorInstrument ACCESSOR = new AccessorInstrument(); }