changeset 15279:0c6d8a08e31b

Truffle: Major cleanup and extension of the Truffle Instrumentation framework in com.oracle.truffle.api
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Sun, 20 Apr 2014 20:37:27 -0700
parents 0e713dba33bb
children 417e2ae45b89
files graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ASTPrinter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugContext.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugManager.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DefaultDebugManager.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractExecutionContext.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentEventListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentation.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationFactory.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTag.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTagged.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Wrapper.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultInstrument.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationImpl.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNodeImpl.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/NullInstrumentEventListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/DefaultNodeInstrumenter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeEvents.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProxyNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodeInstrumenter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodePhylum.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/PhylumMarked.java
diffstat 38 files changed, 2108 insertions(+), 1367 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Thu Mar 27 16:38:39 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Sun Apr 20 20:37:27 2014 -0700
@@ -24,11 +24,12 @@
  */
 package com.oracle.truffle.api;
 
-import com.oracle.truffle.api.debug.*;
+import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.source.*;
 
 /**
- * Information about the runtime context of a Truffle program.
+ * Access to information and basic services in the runtime context for a Truffle-implemented guest
+ * language.
  * <p>
  * <strong>Disclaimer:</strong> this interface is under development and will change.
  */
@@ -46,8 +47,20 @@
     SourceManager getSourceManager();
 
     /**
-     * Gets access to debugging services. Returns an inert instance if no services installed.
+     * Gets access to AST instrumentation services.
+     */
+    Instrumentation instrumentation();
+
+    /**
+     * Access to information visualization services for the specific language.
      */
-    DebugContext getDebugContext();
+    Visualizer visualizer();
 
+    /**
+     * Add instrumentation to subsequently constructed Truffle ASTs for the guest language; every
+     * one added will have the opportunity to add instrumentation.
+     *
+     * @throws IllegalArgumentException if prober not usable for the guest language.
+     */
+    void addNodeProber(ASTNodeProber nodeProber);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ASTPrinter.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, 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.debug;
-
-import java.io.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Language-agnostic access to AST-based debugging support.
- * <p>
- * <strong>WARNING:</strong> this interface is under development and will change substantially.
- */
-public interface ASTPrinter {
-
-    /**
-     * Prints a textual AST display, one line per node, with nesting.
-     * 
-     * @param p
-     * @param node the root node of the display.
-     * @param maxDepth the maximum number of levels to print below the root
-     * @param markNode a node to mark with a textual arrow prefix, if present.
-     */
-    void printTree(PrintWriter p, Node node, int maxDepth, Node markNode);
-
-    /**
-     * Creates a textual AST display, one line per node, with nesting.
-     * 
-     * @param node the root node of the display.
-     * @param maxDepth the maximum number of levels to print below the root
-     * @param markNode a node to mark with a textual arrow prefix, if present.
-     */
-    String printTreeToString(Node node, int maxDepth, Node markNode);
-
-    /**
-     * Creates a textual AST display, one line per node, with nesting.
-     * 
-     * @param node the root node of the display.
-     * @param maxDepth the maximum number of levels to print below the root
-     */
-    String printTreeToString(Node node, int maxDepth);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugContext.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2014, 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.debug;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.instrument.*;
-
-/**
- * Access to the suite of facilities available when debugging is enabled.
- */
-public interface DebugContext {
-
-    /**
-     * Access to the Truffle execution context being debugged.
-     */
-    ExecutionContext getContext();
-
-    /**
-     * Access to the appropriate implementation of AST node instrumentation.
-     */
-    NodeInstrumenter getNodeInstrumenter();
-
-    /**
-     * Access to the management of breakpoints, notifications, etc.
-     */
-    DebugManager getDebugManager();
-
-    /**
-     * Gets a printer for Truffle ASTs helpful for debugging guest language implementations.
-     */
-    ASTPrinter getASTPrinter();
-
-    /**
-     * Converts a value in the guest language to a display string.
-     */
-    String displayValue(Object value);
-
-    /**
-     * Converts a slot identifier in the guest language to a display string.
-     */
-    String displayIdentifier(FrameSlot slot);
-
-    /**
-     * Invokes appropriate debugging action when Truffle execution halts.
-     */
-    void executionHalted(Node node, VirtualFrame frame);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugManager.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, 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.debug;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.instrument.*;
-import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
-
-/**
- * Language-agnostic access to AST-based debugging support.
- * <p>
- * <strong>Disclaimer:</strong> this interface is under development and will change.
- */
-public interface DebugManager {
-
-    /**
-     * Informs the {@link DebugManager} that the Guest Language runtime is starting to load a
-     * source. Care should be taken to ensure that under any circumstance there is always a
-     * following call to {@link #notifyFinishedLoading(Source)} with the same argument.
-     */
-    void notifyStartLoading(Source source);
-
-    /**
-     * Informs the {@link DebugManager} that the Guest Language runtime has finished loading a
-     * source. Care should be taken to ensure that under any circumstance there is always a prior
-     * call to {@link #notifyStartLoading(Source)} with the same argument.
-     */
-    void notifyFinishedLoading(Source source);
-
-    /**
-     * Return a reference to the (canonical) instrumentation site associated with a particular
-     * source code location; this site will have effect on any Truffle/AST implementation
-     * corresponding to the source location, even if the AST is copied multiple times.
-     */
-    ProbeChain getProbeChain(SourceSection sourceSection);
-
-    /**
-     * Informs the {@link DebugManager} that Truffle execution has halted; execution will resume
-     * when this method returns.
-     * 
-     * @param astNode a guest language AST node that represents the current execution site, assumed
-     *            not to be any kind of {@link InstrumentationNode},
-     * @param frame execution frame at the site where execution suspended
-     */
-    void haltedAt(Node astNode, VirtualFrame frame);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DefaultDebugManager.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2014, 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.debug;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
-import com.oracle.truffle.api.source.*;
-
-/**
- * A minimal, language-agnostic implementation that tracks loaded sources, and keeps maps describing
- * what locations in the source have instrumentation available. This implementation will do nothing
- * unless there are calls to it during AST construction, notably {@link #notifyStartLoading(Source)}
- * and {@link #notifyFinishedLoading(Source)} <em>and</em> there are at least some AST nodes being
- * instrumented.
- */
-public class DefaultDebugManager implements DebugManager {
-
-    private final Set<Source> loadedSources = new HashSet<>();
-
-    private Source beingLoaded = null;
-
-    /**
-     * Map: SourceSection ==> probe chain associated with that source section in an AST.
-     */
-    private final Map<SourceSection, ProbeChain> srcToProbeChain = new HashMap<>();
-
-    /**
-     * Map: Source lines ==> probe chains associated with source sections starting on the line.
-     */
-    private final Map<SourceLineLocation, Set<ProbeChain>> lineToProbeChains = new HashMap<>();
-
-    private final ExecutionContext context;
-
-    public DefaultDebugManager(ExecutionContext context) {
-        this.context = context;
-    }
-
-    /**
-     * Gets the {@linkplain ProbeChain probe} associated with a particular {@link SourceSection
-     * source location}, creating a new one if needed. There should only be one probe associated
-     * with each {@linkplain SourceSection source location}.
-     */
-    public ProbeChain getProbeChain(SourceSection sourceSection) {
-        assert sourceSection != null;
-        assert sourceSection.getSource().equals(beingLoaded);
-
-        ProbeChain probeChain = srcToProbeChain.get(sourceSection);
-
-        if (probeChain != null) {
-            return probeChain;
-        }
-        probeChain = new ProbeChain(context, sourceSection, null);
-
-        // Register new ProbeChain by unique SourceSection
-        srcToProbeChain.put(sourceSection, probeChain);
-
-        // Register new ProbeChain by source line, there may be more than one
-        // Create line location for map key
-        final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine());
-
-        Set<ProbeChain> probeChains = lineToProbeChains.get(lineLocation);
-        if (probeChains == null) {
-            probeChains = new HashSet<>();
-            lineToProbeChains.put(lineLocation, probeChains);
-        }
-        probeChains.add(probeChain);
-
-        return probeChain;
-    }
-
-    public void notifyStartLoading(Source source) {
-        assert beingLoaded == null;
-        beingLoaded = source;
-    }
-
-    public void notifyFinishedLoading(Source source) {
-        assert source == beingLoaded;
-        loadedSources.add(source);
-        beingLoaded = null;
-    }
-
-    public void haltedAt(Node astNode, VirtualFrame frame) {
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2014, 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.debug;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Controls breaking out of an execution context, such as a shell or eval.
- */
-public final class KillException extends ControlFlowException {
-
-    private static final long serialVersionUID = 3163641880088766957L;
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2014, 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.debug;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Controls breaking out of all executions and ending Truffle execution.
- */
-public final class QuitException extends ControlFlowException {
-
-    private static final long serialVersionUID = -4301115629772778413L;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractExecutionContext.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2014, 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.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.source.*;
+
+public abstract class AbstractExecutionContext implements ExecutionContext {
+
+    private final SourceManager sourceManager = new SourceManager();
+    private final Instrumentation instrumentation;
+    private Visualizer visualizer = new DefaultVisualizer();
+    protected ASTProber astProber = null;
+
+    protected AbstractExecutionContext() {
+        this.instrumentation = InstrumentationFactory.create(this);
+    }
+
+    public final SourceManager getSourceManager() {
+        return sourceManager;
+    }
+
+    public final Instrumentation instrumentation() {
+        return instrumentation;
+    }
+
+    public Visualizer visualizer() {
+        return visualizer;
+    }
+
+    public void addNodeProber(ASTNodeProber nodeProber) {
+        if (astProber == null) {
+            throw new IllegalStateException("No ASTProber installed in context");
+        }
+        astProber.addNodeProber(nodeProber);
+    }
+
+    /**
+     * Assign guest language-specific visualization support for tools. This must be assigned outside
+     * the implementation context to avoid build circularities.
+     */
+    public void setVisualizer(Visualizer visualizer) {
+        this.visualizer = visualizer;
+    }
+
+    /**
+     * Assigns a guest language-specific manager for using {@link ASTNodeProber}s added by tools to
+     * instrument ASTs with {@link Probe}s at specified nodes. This must be assigned outside the
+     * implementation context to avoid build circularities. It must also be set before any
+     * instrumentation probe implementations are assigned.
+     */
+    public void setASTProber(ASTProber astProber) {
+        this.astProber = astProber;
+    }
+
+    /**
+     * Gets a guest language-specific {@link ASTNodeProber} that will apply all that have been
+     * added; {@code null} if no instrumentation in AST.
+     */
+    public ASTNodeProber getCombinedNodeProber() {
+        return astProber == null ? null : astProber.getCombinedNodeProber();
+    }
+
+    public abstract void setInstrumentEventListener(InstrumentEventListener listener);
+
+    public abstract InstrumentEventListener getInstrumentEventListener();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 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.nodes.*;
+
+/**
+ * Implementation of a policy for <em>instrumenting</em> inserting a {@link Probe} at a Truffle AST
+ * node.
+ * <p>
+ * Note that this interface is guest language agnostic, but current extensions are
+ * language-specific. This will be revisited.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development. Really!
+ */
+public interface ASTNodeProber {
+
+    /**
+     * Optionally applies <em>instrumentation</em> at a Truffle AST node, depending on guest
+     * language characteristics and use-case policy.
+     * <ul>
+     * <li>if no instrumentation is to be applied, returns the AST node unmodified;</li>
+     * <li>if an AST node is to be instrumented, then returns a newly created {@link Wrapper} that
+     * <em>decorates</em> the AST node and notifies an associated {@link Probe} of all
+     * {@link ExecutionEvents} at the wrapped AST node.</li>
+     * <li>if the argument is itself a {@link Wrapper}, i.e. if the AST node at this site has
+     * already been wrapped, then the wrapper is returned (with the possible addition of a
+     * {@linkplain PhylumTag tag}).</li>
+     * </ul>
+     *
+     * @param astNode an AST node to which instrumentation might be applied
+     * @param tag an optional category directing how the node, if instrumented, should be perceived
+     *            by tool users
+     * @param args additional arguments for instrumentation specific to a particular guest language
+     * @return if no instrumentation should be applied or if the node is a {@link Wrapper} then the
+     *         unmodified node; otherwise a newly created {@link Wrapper} (whose child
+     *         {@code astNode}) with an associated {@link Probe} .
+     */
+
+    Node probeAs(Node astNode, PhylumTag tag, Object... args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, 2014, 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 java.io.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Language-agnostic access to AST-based debugging support.
+ * <p>
+ * <strong>WARNING:</strong> this interface is under development and will change substantially.
+ */
+public interface ASTPrinter {
+
+    /**
+     * Prints a textual AST display, one line per node, with nesting.
+     * 
+     * @param p
+     * @param node the root node of the display.
+     * @param maxDepth the maximum number of levels to print below the root
+     * @param markNode a node to mark with a textual arrow prefix, if present.
+     */
+    void printTree(PrintWriter p, Node node, int maxDepth, Node markNode);
+
+    /**
+     * Creates a textual AST display, one line per node, with nesting.
+     * 
+     * @param node the root node of the display.
+     * @param maxDepth the maximum number of levels to print below the root
+     * @param markNode a node to mark with a textual arrow prefix, if present.
+     */
+    String printTreeToString(Node node, int maxDepth, Node markNode);
+
+    /**
+     * Creates a textual AST display, one line per node, with nesting.
+     * 
+     * @param node the root node of the display.
+     * @param maxDepth the maximum number of levels to print below the root
+     */
+    String printTreeToString(Node node, int maxDepth);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2014, 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;
+
+/**
+ * Implementation of a policy for <em>instrumenting</em> Truffle ASTs with {@link Probe}s at
+ * particular nodes by inserting node {@link Wrapper}s.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface ASTProber {
+
+    // TODO (mlvdv) This is a provisional interface, more of a marker really
+    // TODO (mlvdv) AST probing should eventually be done with visitors.
+
+    void addNodeProber(ASTNodeProber nodeProber);
+
+    /**
+     * Gets a prober that applies all added {@link ASTNodeProber}s.
+     */
+    ASTNodeProber getCombinedNodeProber();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2013, 2014, 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.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Normal events during program execution at Truffle AST nodes that are reported via a {@link Probe}
+ * associated with the node, and made available to the probe's attached {@link Instrument}s.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface ExecutionEvents {
+
+    /**
+     * Notifies that an AST node's execute method has just been entered. Callers should assure that
+     * a matching call to {@link #leave(Node, VirtualFrame, Object)} always follows.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame being passed to the execute method
+     */
+    void enter(Node astNode, VirtualFrame frame);
+
+    /**
+     * Notifies that an AST Node's void-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     */
+    void leave(Node astNode, VirtualFrame frame);
+
+    /**
+     * Notifies that an AST Node's boolean-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, boolean result);
+
+    /**
+     * Notifies that an AST Node's byte-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, byte result);
+
+    /**
+     * Notifies that an AST Node's short-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, short result);
+
+    /**
+     * Notifies that an AST Node's integer-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, int result);
+
+    /**
+     * Notifies that an AST Node's long-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, long result);
+
+    /**
+     * Notifies that an AST Node's float-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, float result);
+
+    /**
+     * Notifies that an AST Node's double-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, double result);
+
+    /**
+     * Notifies that an AST Node's char-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, char result);
+
+    /**
+     * Notifies that an AST Node's object-valued execute method is about to exit.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param result The result of the call to the execute method.
+     */
+    void leave(Node astNode, VirtualFrame frame, Object result);
+
+    /**
+     * Notifies that an AST Node's execute method is about to leave under exceptional conditions,
+     * returning no value.
+     * <p>
+     * Callers should assure (via {@code try/finally}) that a matching call to this method always
+     * follows a call to {@link #enter(Node, VirtualFrame)}.
+     *
+     * @param astNode The AST node on which the execute method is being called
+     * @param frame The frame that was passed to the execute method
+     * @param e the exception associated with the unusual return
+     */
+    void leaveExceptional(Node astNode, VirtualFrame frame, Exception e);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 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 receiver of Truffle AST {@link ExecutionEvents}, propagated from a {@link Probe} to which the
+ * instrument is attached.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface Instrument extends ExecutionEvents {
+
+    /**
+     * @return the {@link Probe} to which this instrument is attached.
+     */
+    Probe getProbe();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentEventListener.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 2014, 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.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A client of the instrumentation framework that requests event notifications from the language
+ * engine.
+ */
+public interface InstrumentEventListener {
+
+    /**
+     * The guest language runtime is starting to load a source. Care should be taken to ensure that
+     * under any circumstance there is always a following call to {@link #loadEnding(Source)} with
+     * the same argument.
+     */
+    void loadStarting(Source source);
+
+    /**
+     * The guest language runtime has finished loading a source. Care should be taken to ensure that
+     * under any circumstance there is always a prior call to {@link #loadStarting(Source)} with the
+     * same argument.
+     */
+    void loadEnding(Source source);
+
+    /**
+     * A guest language call is about to be executed.
+     */
+    void callEntering(Node astNode, String name);
+
+    /**
+     * A guest language call has just completed.
+     */
+    void callReturned(Node astNode, String name);
+
+    /**
+     * An opportunity for instrumentation to interact with Truffle AST execution halted at some
+     * node.
+     */
+    void haltedAt(Node astNode, MaterializedFrame frame);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentation.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, 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 java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.source.*;
+
+public interface Instrumentation {
+
+    /**
+     * Adds a new specification for how to instrument ASTs.
+     */
+    void addNodeProber(ASTNodeProber nodeProber);
+
+    /**
+     * Registers a tool interested in being notified about the insertion of a newly created
+     * {@link Probe} into a Truffle AST.
+     */
+    void addProbeListener(ProbeListener listener);
+
+    /**
+     * Return the (possibly newly created) {@link Probe} uniquely associated with a particular
+     * source code location. A newly created probe carries no tags.
+     *
+     * @param eventListener an optional listener for certain instrumentation-related events
+     * @return a probe uniquely associated with an extent of guest language source code.
+     */
+    Probe getProbe(SourceSection sourceSection, InstrumentEventListener eventListener);
+
+    /**
+     * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty
+     * collection if no probes found.
+     */
+    Collection<Probe> findProbesTaggedAs(PhylumTag tag);
+
+    /**
+     * Returns all existing probes with first character on a specified line; empty collection if no
+     * probes found.
+     */
+    Collection<Probe> findProbesByLine(SourceLineLocation lineLocation);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationFactory.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, 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.*;
+import com.oracle.truffle.api.instrument.impl.*;
+
+public class InstrumentationFactory {
+
+    public static Instrumentation create(ExecutionContext context) {
+        return new InstrumentationImpl(context);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 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.nodes.*;
+
+/**
+ * Controls breaking out of an execution context, such as a shell or eval.
+ */
+public final class KillException extends ControlFlowException {
+
+    private static final long serialVersionUID = 3163641880088766957L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTag.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 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;
+
+/**
+ * Program element "tags" that define user-visible behavior for debugging and other simple tools.
+ * These categories (<em>phyla</em>) should correspond to program structures that are meaningful to
+ * a guest language programmer.
+ * <p>
+ * An untagged Truffle node should be understood as an artifact of the guest language implementation
+ * and should not be visible to the user of a guest language programming tool. Nodes may also have
+ * more than one tag, for example a variable assignment that is also a statement. Finally, the
+ * assignment of tags to nodes could depending on the use-case of whatever tool is using them.
+ * <p>
+ * This is a somewhat language-agnostic set of phyla, suitable for conventional imperative
+ * languages, and is being developed incrementally.
+ * <p>
+ * The need for alternative sets of tags is likely to arise, perhaps for other families of languages
+ * (for example for mostly expression-oriented languages) or even for specific languages.
+ * <p>
+ * These are listed alphabetically so that listing from some collection classes will come out in
+ * that order.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public enum PhylumTag {
+
+    /**
+     * Marker for a variable assignment.
+     */
+    ASSIGNMENT,
+
+    /**
+     * Marker for a call site.
+     */
+    CALL,
+
+    /**
+     * Marker for a location where a guest language exception is about to be thrown.
+     */
+    THROW,
+
+    /**
+     * Marker for a location where ordinary "stepping" should halt.
+     */
+    STATEMENT;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTagged.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 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 java.util.*;
+
+/**
+ * Information about a guest language program element that can be marked as belonging to 0 or more
+ * {@linkplain PhylumTag tags}.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface PhylumTagged {
+
+    /**
+     * Is this node tagged as belonging to a particular category of language constructs?
+     */
+    boolean isTaggedAs(PhylumTag tag);
+
+    /**
+     * In which categories has this node been tagged (<em>empty set</em> if none).
+     */
+    Set<PhylumTag> getPhylumTags();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2014, 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.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A collector of {@link ExecutionEvents} at a specific site (node) in a Truffle AST (generated by a
+ * {@link Wrapper} inserted into the AST) for the purpose of <em>instrumentation</em>. For probes
+ * associated with programmer-facing tools, there should be no more than one probe associated with a
+ * particular piece of source code syntax (i.e. a {@link SourceSection}).
+ * <p>
+ * Any {@linkplain PhylumTag tags} associated with a particular piece of source code syntax are
+ * managed by the probe.
+ * <p>
+ * When ASTs are copied, it is presumed that the probe for a site is shared by all AST nodes
+ * representing that site.
+ * <p>
+ * A probe holds zero or more {@link Instrument}s, which can be added and removed dynamically.
+ * Events reported to a probe are propagated to every attached instrument; the order is undefined.
+ * <p>
+ * Probe methods must be amenable to Truffle/Graal inlining on the assumption that the collection of
+ * attached instruments seldom changes. The assumption is invalidated when instruments are added or
+ * removed, but some instruments may change their internal state in such a way that the assumption
+ * should also be invalidated.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface Probe extends PhylumTagged {
+
+    /**
+     * The source location with which this probe is (presumably uniquely) associated.
+     */
+    SourceSection getSourceLocation();
+
+    /**
+     * Mark this probe as being associated with an AST node in some category useful for debugging
+     * and other tools.
+     */
+    void tagAs(PhylumTag tag);
+
+    /**
+     * Adds an instrument to this probe.
+     */
+    void addInstrument(Instrument newInstrument);
+
+    /**
+     * Removes an instrument from this probe.
+     */
+    void removeInstrument(Instrument oldInstrument);
+
+    /**
+     * Change <em>stepping mode</em>, which is used in association with nodes tagged as
+     * {@linkplain PhylumTag#STATEMENT statements}.
+     */
+    void setStepping(boolean stepping);
+
+    /**
+     * Value of <em>stepping mode</em>, which is used in association with nodes tagged as
+     * {@linkplain PhylumTag#STATEMENT statements}.
+     */
+    boolean isStepping();
+
+    /**
+     * @see ExecutionEvents#enter(Node, VirtualFrame)
+     */
+    void notifyEnter(Node astNode, VirtualFrame frame);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, boolean)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, boolean result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, byte)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, byte result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, short)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, short result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, int)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, int result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, long)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, long result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, char)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, char result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, float)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, float result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, double)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, double result);
+
+    /**
+     * @see ExecutionEvents#leave(Node, VirtualFrame, Object)
+     */
+    void notifyLeave(Node astNode, VirtualFrame frame, Object result);
+
+    /**
+     * @see ExecutionEvents#leaveExceptional(Node, VirtualFrame, Exception)
+     */
+    void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 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.*;
+
+/**
+ * Client for receiving events relate to {@link Probe} management. Does not report AST copying.
+ */
+public interface ProbeListener {
+
+    /**
+     * Notifies that a newly created (untagged) {@link Probe} has been inserted into a Truffle AST.
+     * There will be no notification when an existing {@link Probe} is shared by an AST copy.
+     */
+    void newProbeInserted(SourceSection location, Probe probe);
+
+    /**
+     * Notifies that a (fully constructed) {@link Probe} has been tagged. A subsequent marking with
+     * the same tag is idempotent and generates no notification.
+     */
+    void probeTaggedAs(Probe probe, PhylumTag tag);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 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.nodes.*;
+
+/**
+ * Controls breaking out of all executions and ending Truffle execution.
+ */
+public final class QuitException extends ControlFlowException {
+
+    private static final long serialVersionUID = -4301115629772778413L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 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.*;
+
+/**
+ * Visualization services for guest language and Truffle information.
+ */
+public interface Visualizer {
+
+    /**
+     * Gets a printer for Truffle ASTs, possibly specialized to be helpful for a specific guest
+     * language implementation.
+     */
+    ASTPrinter getASTPrinter();
+
+    /**
+     * Converts a value in the guest language to a display string.
+     */
+    String displayValue(Object value);
+
+    /**
+     * Converts a slot identifier in the guest language to a display string.
+     */
+    String displayIdentifier(FrameSlot slot);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Wrapper.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2014, 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.nodes.*;
+
+/**
+ * A node that can be inserted into a Truffle AST in order to attach <em>instrumentation</em> at a
+ * particular node.
+ * <p>
+ * A wrapper <em>decorates</em> an AST node (its <em>child</em>) by acting as a transparent
+ * <em>proxy</em> for the child with respect to Truffle execution semantics.
+ * <p>
+ * A wrapper is also expected to notify its associated {@link Probe} when certain
+ * {@link ExecutionEvents} occur at the wrapper during program execution.
+ * <p>
+ * The wrapper's {@link Probe} is shared by every copy of the wrapper made when the AST is copied.
+ * <p>
+ * Wrappers methods must be amenable to Truffle/Graal inlining.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface Wrapper extends PhylumTagged {
+
+    /**
+     * Gets the AST node being instrumented, which should never be an instance of {@link Wrapper}.
+     */
+    Node getChild();
+
+    /**
+     * Gets the {@link Probe} to which events occurring at this wrapper's child are propagated.
+     */
+    Probe getProbe();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2014, 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.impl;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeClass;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind;
+
+/**
+ * A language-agnostic for printing out various pieces of a Truffle AST.
+ */
+public class DefaultASTPrinter implements ASTPrinter {
+
+    public DefaultASTPrinter() {
+    }
+
+    public void printTree(PrintWriter p, Node node, int maxDepth, Node markNode) {
+        printTree(p, node, maxDepth, markNode, 1);
+        p.println();
+        p.flush();
+    }
+
+    public String printTreeToString(Node node, int maxDepth, Node markNode) {
+        StringWriter out = new StringWriter();
+        printTree(new PrintWriter(out), node, maxDepth, markNode);
+        return out.toString();
+    }
+
+    public String printTreeToString(Node node, int maxDepth) {
+        return printTreeToString(node, maxDepth, null);
+    }
+
+    private static void printTree(PrintWriter p, Node node, int maxDepth, Node markNode, int level) {
+        if (node == null) {
+            p.print("null");
+            return;
+        }
+
+        p.print(nodeName(node));
+
+        String sep = "";
+        p.print("(");
+
+        final SourceSection src = node.getSourceSection();
+        if (src != null) {
+            if (!(src instanceof NullSourceSection)) {
+                p.print(src.getSource().getName() + ":" + src.getStartLine());
+            }
+        }
+        if (node instanceof PhylumTagged) {
+            final PhylumTagged taggedNode = (PhylumTagged) node;
+            String prefix = "";
+            for (PhylumTag tag : taggedNode.getPhylumTags()) {
+                p.print(prefix);
+                prefix = ",";
+                p.print(tag.toString());
+            }
+
+        }
+
+        ArrayList<NodeField> childFields = new ArrayList<>();
+
+        for (NodeField field : NodeClass.get(node.getClass()).getFields()) {
+            if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
+                childFields.add(field);
+            } else if (field.getKind() == NodeFieldKind.DATA) {
+                // p.print(sep);
+                // sep = ", ";
+                //
+                // final String fieldName = field.getName();
+                // switch (fieldName) {
+                //
+                // }
+                // p.print(fieldName);
+                // p.print(" = ");
+                // p.print(field.loadValue(node));
+            }
+        }
+        p.print(")");
+
+        if (level <= maxDepth) {
+
+            if (childFields.size() != 0) {
+                p.print(" {");
+                for (NodeField field : childFields) {
+
+                    Object value = field.loadValue(node);
+                    if (value == null) {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                        p.print(" = null ");
+                    } else if (field.getKind() == NodeFieldKind.CHILD) {
+                        final Node valueNode = (Node) value;
+                        printNewLine(p, level, valueNode == markNode);
+                        p.print(field.getName());
+                        p.print(" = ");
+                        printTree(p, valueNode, maxDepth, markNode, level + 1);
+                    } else if (field.getKind() == NodeFieldKind.CHILDREN) {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                        Node[] children = (Node[]) value;
+                        p.print(" = [");
+                        sep = "";
+                        for (Node child : children) {
+                            p.print(sep);
+                            sep = ", ";
+                            printTree(p, child, maxDepth, markNode, level + 1);
+                        }
+                        p.print("]");
+                    } else {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                    }
+                }
+                printNewLine(p, level - 1);
+                p.print("}");
+            }
+        }
+    }
+
+    private static void printNewLine(PrintWriter p, int level, boolean mark) {
+        p.println();
+        for (int i = 0; i < level; i++) {
+            if (mark && i == 0) {
+                p.print(" -->");
+            } else {
+                p.print("    ");
+            }
+        }
+    }
+
+    private static void printNewLine(PrintWriter p, int level) {
+        printNewLine(p, level, false);
+    }
+
+    private static String nodeName(Node node) {
+        return node.getClass().getSimpleName();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultInstrument.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, 2014, 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.impl;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An {@link Instrument} that implements all {@link ExecutionEvents} notifications with empty
+ * methods.
+ */
+public class DefaultInstrument extends InstrumentationNodeImpl implements Instrument {
+
+    protected DefaultInstrument() {
+    }
+
+    public void enter(Node astNode, VirtualFrame frame) {
+    }
+
+    public void leave(Node astNode, VirtualFrame frame) {
+    }
+
+    public void leave(Node astNode, VirtualFrame frame, boolean result) {
+        leave(astNode, frame, (Object) result);
+    }
+
+    public void leave(Node astNode, VirtualFrame frame, byte result) {
+        leave(astNode, frame, (Object) result);
+    }
+
+    public void leave(Node astNode, VirtualFrame frame, short result) {
+        leave(astNode, frame, (Object) result);
+    }
+
+    public void leave(Node astNode, VirtualFrame frame, int result) {
+        leave(astNode, frame, (Object) result);
+    }
+
+    public void leave(Node astNode, VirtualFrame frame, long result) {
+        leave(astNode, frame, (Object) result);
+    }
+
+    public void leave(Node astNode, VirtualFrame frame, char result) {
+        leave(astNode, frame, (Object) result);
+    }
+
+    public void leave(Node astNode, VirtualFrame frame, float result) {
+        leave(astNode, frame, (Object) result);
+    }
+
+    public void leave(Node astNode, VirtualFrame frame, double result) {
+        leave(astNode, frame, (Object) result);
+    }
+
+    public void leave(Node astNode, VirtualFrame frame, Object result) {
+    }
+
+    public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 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.impl;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+
+public class DefaultVisualizer implements Visualizer {
+
+    private final ASTPrinter astPrinter;
+
+    public DefaultVisualizer() {
+        this.astPrinter = new DefaultASTPrinter();
+    }
+
+    public ASTPrinter getASTPrinter() {
+        return astPrinter;
+    }
+
+    public String displayValue(Object value) {
+        return value.toString();
+    }
+
+    public String displayIdentifier(FrameSlot slot) {
+        return slot.getIdentifier().toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationImpl.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2013, 2014, 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.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * @author mlvdv
+ *
+ */
+public final class InstrumentationImpl implements Instrumentation {
+
+    private final ExecutionContext context;
+
+    // TODO (mlvdv) maps should really use weak references.
+
+    /**
+     * Map: SourceSection ==> probe associated with that source section in an AST.
+     */
+    private final Map<SourceSection, Probe> srcToProbe = new HashMap<>();
+
+    /**
+     * Map: Source line ==> probes associated with source sections starting on the line.
+     */
+    private final Map<SourceLineLocation, Collection<Probe>> lineToProbes = new HashMap<>();
+
+    private final List<ProbeListener> probeListeners = new ArrayList<>();
+
+    public InstrumentationImpl(ExecutionContext context) {
+        this.context = context;
+    }
+
+    public void addNodeProber(ASTNodeProber nodeProber) {
+        context.addNodeProber(nodeProber);
+    }
+
+    public void addProbeListener(ProbeListener listener) {
+        assert listener != null;
+        probeListeners.add(listener);
+    }
+
+    /**
+     * Return the (possibly newly created) {@link Probe} uniquely associated with a particular
+     * source code location. A newly created probe carries no tags.
+     *
+     * @param eventListener an optional listener for certain instrumentation-related events
+     * @return a probe uniquely associated with an extent of guest language source code.
+     */
+    public Probe getProbe(SourceSection sourceSection, InstrumentEventListener eventListener) {
+        assert sourceSection != null;
+
+        Probe probe = srcToProbe.get(sourceSection);
+
+        if (probe != null) {
+            return probe;
+        }
+        probe = InstrumentationNodeImpl.createProbe(this, sourceSection, eventListener);
+
+        // Register new probe by unique SourceSection
+        srcToProbe.put(sourceSection, probe);
+
+        // Register new probe by source line, there may be more than one
+        // Create line location for map key
+        final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine());
+
+        Collection<Probe> probes = lineToProbes.get(lineLocation);
+        if (probes == null) {
+            probes = new ArrayList<>(2);
+            lineToProbes.put(lineLocation, probes);
+        }
+        probes.add(probe);
+
+        for (ProbeListener listener : probeListeners) {
+            listener.newProbeInserted(sourceSection, probe);
+        }
+
+        return probe;
+    }
+
+    /**
+     * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty
+     * collection if no probes found.
+     */
+    public Collection<Probe> findProbesTaggedAs(PhylumTag tag) {
+        if (tag == null) {
+            return new ArrayList<>(srcToProbe.values());
+        }
+        final List<Probe> probes = new ArrayList<>();
+        for (Probe probe : srcToProbe.values()) {
+            if (probe.isTaggedAs(tag)) {
+                probes.add(probe);
+            }
+        }
+        return probes;
+    }
+
+    /**
+     * Returns all existing probes with first character on a specified line; empty collection if no
+     * probes found.
+     */
+    public Collection<Probe> findProbesByLine(SourceLineLocation lineLocation) {
+        final Collection<Probe> probes = lineToProbes.get(lineLocation);
+        if (probes == null) {
+            return Collections.emptyList();
+        }
+        return new ArrayList<>(probes);
+    }
+
+    /**
+     * Receives (from the {@link Probe} implementation) and distributes notification that a
+     * {@link Probe} has acquired a new {@linkplain PhylumTag tag}.
+     */
+    void newTagAdded(Probe probe, PhylumTag tag) {
+        for (ProbeListener listener : probeListeners) {
+            listener.probeTaggedAs(probe, tag);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNodeImpl.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2013, 2014, 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.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Abstract implementation of Truffle {@link Node} to be used for AST probes and instruments.
+ * <p>
+ * Coordinates propagation of Truffle AST {@link ExecutionEvents}.
+ */
+public abstract class InstrumentationNodeImpl extends Node implements ExecutionEvents {
+
+    // TODO (mlvdv) This is a pretty awkward design.
+
+    /**
+     * Creates a new {@link Probe}, presumed to be unique to a particular {@linkplain SourceSection}
+     * extent of guest language source code.
+     *
+     * @param eventListener an optional listener for certain instrumentation-related events.
+     * @return a new probe
+     */
+    static Probe createProbe(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) {
+        return new ProbeImpl(instrumentation, sourceSection, eventListener);
+    }
+
+    /**
+     * Next in chain.
+     */
+    @Child protected InstrumentationNodeImpl next;
+
+    protected InstrumentationNodeImpl() {
+    }
+
+    /**
+     * @return the instance of {@link Probe} to which this instrument is attached.
+     */
+    public Probe getProbe() {
+        final InstrumentationNodeImpl parent = (InstrumentationNodeImpl) getParent();
+        return parent == null ? null : parent.getProbe();
+    }
+
+    /**
+     * Add a probe to the end of this probe chain.
+     */
+    void internalAddInstrument(InstrumentationNodeImpl newInstrument) {
+        if (next == null) {
+            this.next = insert(newInstrument);
+        } else {
+            next.internalAddInstrument(newInstrument);
+        }
+    }
+
+    void internalRemoveInstrument(InstrumentationNodeImpl oldInstrument) {
+        if (next == null) {
+            throw new RuntimeException("Couldn't find probe to remove: " + oldInstrument);
+        } else if (next == oldInstrument) {
+            if (oldInstrument.next == null) {
+                this.next = null;
+            } else {
+                this.next = insert(oldInstrument.next);
+                oldInstrument.next = null;
+            }
+        } else {
+            next.internalRemoveInstrument(oldInstrument);
+        }
+    }
+
+    /**
+     * Reports to the instance of {@link Probe} holding this instrument that some essential state
+     * has changed that requires deoptimization.
+     */
+    @CompilerDirectives.SlowPath
+    protected void notifyProbeChanged(InstrumentationNodeImpl instrument) {
+        final ProbeImpl probe = (ProbeImpl) getProbe();
+        probe.notifyProbeChanged(instrument);
+    }
+
+    private void internalEnter(Node astNode, VirtualFrame frame) {
+        enter(astNode, frame);
+        if (next != null) {
+            next.internalEnter(astNode, frame);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame) {
+        leave(astNode, frame);
+        if (next != null) {
+            next.internalLeave(astNode, frame);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, boolean result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, byte result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, short result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, int result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, long result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, char result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, float result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, double result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeave(Node astNode, VirtualFrame frame, Object result) {
+        leave(astNode, frame, result);
+        if (next != null) {
+            next.internalLeave(astNode, frame, result);
+        }
+    }
+
+    private void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
+        leaveExceptional(astNode, frame, null);
+        if (next != null) {
+            next.internalLeaveExceptional(astNode, frame, e);
+        }
+    }
+
+    /**
+     * Holder of a chain of {@linkplain InstrumentationNodeImpl instruments}: manages the
+     * {@link Assumption} that none of the instruments have changed since last checked.
+     * <p>
+     * An instance is intended to be shared by every clone of the AST node with which it is
+     * originally attached, so it holds no parent pointer.
+     * <p>
+     * May be categorized by one or more {@linkplain PhylumTag tags}, signifying information useful
+     * for instrumentation about its AST location(s).
+     */
+    private static final class ProbeImpl extends InstrumentationNodeImpl implements Probe {
+
+        final InstrumentationImpl instrumentation;
+
+        final InstrumentEventListener eventListener;
+
+        @CompilerDirectives.CompilationFinal private Assumption probeUnchanged;
+
+        /**
+         * When in stepping mode, ordinary line breakpoints are ignored, but every entry at a line
+         * will cause a halt.
+         */
+        @CompilerDirectives.CompilationFinal private boolean stepping;
+
+        /**
+         * Source information about the AST node to which this instrumentation is attached.
+         */
+        private final SourceSection probedSourceSection;
+
+        private final Set<PhylumTag> tags = EnumSet.noneOf(PhylumTag.class);
+
+        private ProbeImpl(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) {
+            this.instrumentation = instrumentation;
+            this.probedSourceSection = sourceSection;
+            this.eventListener = eventListener == null ? NullInstrumentEventListener.INSTANCE : eventListener;
+            this.probeUnchanged = Truffle.getRuntime().createAssumption();
+            this.next = null;
+        }
+
+        @Override
+        public Probe getProbe() {
+            return this;
+        }
+
+        @Override
+        protected void notifyProbeChanged(InstrumentationNodeImpl instrument) {
+            probeUnchanged.invalidate();
+            probeUnchanged = Truffle.getRuntime().createAssumption();
+        }
+
+        public SourceSection getSourceLocation() {
+            return probedSourceSection;
+        }
+
+        public void tagAs(PhylumTag tag) {
+            assert tag != null;
+            if (!tags.contains(tag)) {
+                tags.add(tag);
+                instrumentation.newTagAdded(this, tag);
+            }
+        }
+
+        public boolean isTaggedAs(PhylumTag tag) {
+            assert tag != null;
+            return tags.contains(tag);
+        }
+
+        public Set<PhylumTag> getPhylumTags() {
+            return tags;
+        }
+
+        public void setStepping(boolean stepping) {
+            if (this.stepping != stepping) {
+                this.stepping = stepping;
+                probeUnchanged.invalidate();
+                probeUnchanged = Truffle.getRuntime().createAssumption();
+            }
+        }
+
+        public boolean isStepping() {
+            return stepping;
+        }
+
+        @CompilerDirectives.SlowPath
+        public void addInstrument(Instrument instrument) {
+            probeUnchanged.invalidate();
+            final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument;
+            super.internalAddInstrument(instrumentImpl);
+            probeUnchanged = Truffle.getRuntime().createAssumption();
+        }
+
+        @CompilerDirectives.SlowPath
+        public void removeInstrument(Instrument instrument) {
+            probeUnchanged.invalidate();
+            final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument;
+            super.internalRemoveInstrument(instrumentImpl);
+            probeUnchanged = Truffle.getRuntime().createAssumption();
+        }
+
+        public void notifyEnter(Node astNode, VirtualFrame frame) {
+            if (stepping || next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                if (stepping) {
+                    eventListener.haltedAt(astNode, frame.materialize());
+                }
+                if (next != null) {
+                    next.internalEnter(astNode, frame);
+                }
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, byte result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, short result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, int result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, long result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, char result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, float result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, double result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeave(Node astNode, VirtualFrame frame, Object result) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeave(astNode, frame, result);
+            }
+        }
+
+        public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
+            if (next != null) {
+                if (!probeUnchanged.isValid()) {
+                    CompilerDirectives.transferToInterpreter();
+                }
+                next.internalLeaveExceptional(astNode, frame, e);
+            }
+        }
+
+        public void enter(Node astNode, VirtualFrame frame) {
+        }
+
+        public void leave(Node astNode, VirtualFrame frame) {
+        }
+
+        public void leave(Node astNode, VirtualFrame frame, boolean result) {
+            leave(astNode, frame, (Object) result);
+        }
+
+        public void leave(Node astNode, VirtualFrame frame, byte result) {
+            leave(astNode, frame, (Object) result);
+        }
+
+        public void leave(Node astNode, VirtualFrame frame, short result) {
+            leave(astNode, frame, (Object) result);
+        }
+
+        public void leave(Node astNode, VirtualFrame frame, int result) {
+            leave(astNode, frame, (Object) result);
+        }
+
+        public void leave(Node astNode, VirtualFrame frame, long result) {
+            leave(astNode, frame, (Object) result);
+        }
+
+        public void leave(Node astNode, VirtualFrame frame, char result) {
+            leave(astNode, frame, (Object) result);
+        }
+
+        public void leave(Node astNode, VirtualFrame frame, float result) {
+            leave(astNode, frame, (Object) result);
+        }
+
+        public void leave(Node astNode, VirtualFrame frame, double result) {
+            leave(astNode, frame, (Object) result);
+        }
+
+        public void leave(Node astNode, VirtualFrame frame, Object result) {
+        }
+
+        public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/NullInstrumentEventListener.java	Sun Apr 20 20:37:27 2014 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2014, 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.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Minimal, mostly no-op implementation of instrumentation services.
+ */
+public final class NullInstrumentEventListener implements InstrumentEventListener {
+
+    public static final InstrumentEventListener INSTANCE = new NullInstrumentEventListener();
+
+    private NullInstrumentEventListener() {
+    }
+
+    public void callEntering(Node astNode, String name) {
+    }
+
+    public void callReturned(Node astNode, String name) {
+    }
+
+    public void haltedAt(Node astNode, MaterializedFrame frame) {
+    }
+
+    public void loadStarting(Source source) {
+    }
+
+    public void loadEnding(Source source) {
+    }
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/DefaultNodeInstrumenter.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nodes.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A no-op node instrumenter; always returns the node unproxied and unmodified.
- */
-public class DefaultNodeInstrumenter implements NodeInstrumenter {
-
-    public Node instrumentAs(Node node, NodePhylum phylum, Object... args) {
-        return node;
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationNode.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2013, 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.nodes.instrument;
-
-/**
- * Marker interface for all Truffle <strong>instrumentation nodes</strong>: nodes that are do not
- * appear in Truffle ASTs as part of a language's execution semantics.
- * <p>
- * In documentation related to instrumentation nodes, these are distinguished by referring to all
- * other nodes (i.e. ones that <em>do</em> implement language semantics) as <em>AST nodes</em>.
- */
-public interface InstrumentationNode {
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeEvents.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2013, 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.nodes.instrument;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Marker interface for all Truffle <strong>instrumentation nodes</strong>: nodes that are do not
- * appear in Truffle ASTs as part of a language's execution semantics.
- * <p>
- * In documentation related to instrumentation nodes, these are distinguished by referring to all
- * other nodes (i.e. ones that <em>do</em> implement language semantics) as <em>AST nodes</em>.
- */
-public interface InstrumentationProbeEvents {
-
-    /**
-     * Notifies a probe that receiver that an AST node's execute method has just been entered.
-     * Callers should assure that a matching call to {@link #leave(Node, VirtualFrame, Object)}
-     * always follows.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame being passed to the execute method
-     */
-    void enter(Node astNode, VirtualFrame frame);
-
-    /**
-     * Notifies a probe that an AST Node's void-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     */
-    void leave(Node astNode, VirtualFrame frame);
-
-    /**
-     * Notifies a probe that an AST Node's boolean-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, boolean result);
-
-    /**
-     * Notifies a probe that an AST Node's byte-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, byte result);
-
-    /**
-     * Notifies a probe that an AST Node's short-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, short result);
-
-    /**
-     * Notifies a probe that an AST Node's integer-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, int result);
-
-    /**
-     * Notifies a probe that an AST Node's long-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, long result);
-
-    /**
-     * Notifies a probe that an AST Node's float-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, float result);
-
-    /**
-     * Notifies a probe that an AST Node's double-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, double result);
-
-    /**
-     * Notifies a probe that an AST Node's char-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, char result);
-
-    /**
-     * Notifies a probe that an AST Node's object-valued execute method is about to exit.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param result The result of the call to the execute method.
-     */
-    void leave(Node astNode, VirtualFrame frame, Object result);
-
-    /**
-     * Notifies a probe that an AST Node's execute method is about to leave under exceptional
-     * conditions, returning no value.
-     * <p>
-     * Callers should assure (via {@code try/finally}) that a matching call to this method always
-     * follows a call to {@link #enter(Node, VirtualFrame)}.
-     * 
-     * @param astNode The AST node on which the execute method is being called
-     * @param frame The frame that was passed to the execute method
-     * @param e the exception associated with the unusual return
-     */
-    void leaveExceptional(Node astNode, VirtualFrame frame, Exception e);
-
-    /**
-     * Notifies a probe that an AST node is about to be replaced with another.
-     * 
-     * @param oldAstNode the AST node currently in the tree
-     * @param newAstNode the AST replacement node
-     * @param reason explanation for the replacement
-     */
-    void replace(Node oldAstNode, Node newAstNode, String reason);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,500 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, 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.nodes.instrument;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A <strong>probe</strong>: a Truffle instrumentation node that holds code to perform some action
- * when notified (via a {@linkplain InstrumentationProxyNode proxy node} in the AST) of a
- * {@linkplain InstrumentationProbeEvents probe event} taking place at the AST node.
- * <p>
- * Probes are only active when attached to a {@linkplain ProbeChain "probe chain"} that is referred
- * to by one or more {@linkplain InstrumentationProxyNode proxy nodes} in an AST.
- */
-public abstract class InstrumentationProbeNode extends Node implements InstrumentationNode, InstrumentationProbeEvents {
-
-    /**
-     * Next in chain.
-     */
-    @Child protected InstrumentationProbeNode next;
-
-    protected InstrumentationProbeNode() {
-    }
-
-    protected int countProbes() {
-        return next == null ? 0 : next.countProbes() + 1;
-    }
-
-    protected boolean isStepping() {
-        final InstrumentationProbeNode parent = (InstrumentationProbeNode) getParent();
-        return parent.isStepping();
-    }
-
-    /**
-     * Add a probe to the end of this probe chain.
-     */
-    protected void internalAppendProbe(InstrumentationProbeNode newProbeNode) {
-        if (next == null) {
-            this.next = insert(newProbeNode);
-        } else {
-            next.internalAppendProbe(newProbeNode);
-        }
-    }
-
-    protected void internalRemoveProbe(InstrumentationProbeNode oldProbeNode) {
-        if (next == null) {
-            throw new RuntimeException("Couldn't find probe to remove: " + oldProbeNode);
-        } else if (next == oldProbeNode) {
-            if (oldProbeNode.next == null) {
-                this.next = null;
-            } else {
-                this.next = insert(oldProbeNode.next);
-                oldProbeNode.next = null;
-            }
-        } else {
-            next.internalRemoveProbe(oldProbeNode);
-        }
-    }
-
-    /**
-     * Passes up the chain notification that a probe has changed its execution state in a way that
-     * invalidates fast path code. Assumes that there is an instance of {@link ProbeChain} at the
-     * head of the chain.
-     */
-    @CompilerDirectives.SlowPath
-    protected void notifyProbeChanged(InstrumentationProbeNode probeNode) {
-        final InstrumentationProbeNode parent = (InstrumentationProbeNode) getParent();
-        parent.notifyProbeChanged(probeNode);
-    }
-
-    // TODO (mlvdv) making the internal*() methods public is a workaround for a bug/limitation in
-    // the Truffle compiler; they are intended to be private.
-
-    public void internalEnter(Node astNode, VirtualFrame frame) {
-        enter(astNode, frame);
-        if (next != null) {
-            next.internalEnter(astNode, frame);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame) {
-        leave(astNode, frame);
-        if (next != null) {
-            next.internalLeave(astNode, frame);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, boolean result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, byte result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, short result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, int result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, long result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, char result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, float result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, double result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeave(Node astNode, VirtualFrame frame, Object result) {
-        leave(astNode, frame, result);
-        if (next != null) {
-            next.internalLeave(astNode, frame, result);
-        }
-    }
-
-    public void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        leaveExceptional(astNode, frame, null);
-        if (next != null) {
-            next.internalLeaveExceptional(astNode, frame, e);
-        }
-    }
-
-    public void internalReplace(Node oldAstNode, Node newAstNode, String reason) {
-        replace(oldAstNode, newAstNode, reason);
-        if (next != null) {
-            next.internalReplace(oldAstNode, newAstNode, reason);
-        }
-    }
-
-    /**
-     * A probe implementation that implements all of {@link InstrumentationProbeEvents} with empty
-     * methods; concrete subclasses can override only the methods for which something is to be done.
-     */
-    public static class DefaultProbeNode extends InstrumentationProbeNode {
-
-        private final ExecutionContext executionContext;
-
-        protected DefaultProbeNode(ExecutionContext context) {
-            this.executionContext = context;
-        }
-
-        public ExecutionContext getContext() {
-            return executionContext;
-        }
-
-        public void enter(Node astNode, VirtualFrame frame) {
-        }
-
-        public void leave(Node astNode, VirtualFrame frame) {
-        }
-
-        public void leave(Node astNode, VirtualFrame frame, boolean result) {
-            leave(astNode, frame, (Object) result);
-        }
-
-        public void leave(Node astNode, VirtualFrame frame, byte result) {
-            leave(astNode, frame, (Object) result);
-        }
-
-        public void leave(Node astNode, VirtualFrame frame, short result) {
-            leave(astNode, frame, (Object) result);
-        }
-
-        public void leave(Node astNode, VirtualFrame frame, int result) {
-            leave(astNode, frame, (Object) result);
-        }
-
-        public void leave(Node astNode, VirtualFrame frame, long result) {
-            leave(astNode, frame, (Object) result);
-        }
-
-        public void leave(Node astNode, VirtualFrame frame, char result) {
-            leave(astNode, frame, (Object) result);
-        }
-
-        public void leave(Node astNode, VirtualFrame frame, float result) {
-            leave(astNode, frame, (Object) result);
-        }
-
-        public void leave(Node astNode, VirtualFrame frame, double result) {
-            leave(astNode, frame, (Object) result);
-        }
-
-        public void leave(Node astNode, VirtualFrame frame, Object result) {
-        }
-
-        public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        }
-
-        public void replace(Node oldAstNode, Node newAstNode, String reason) {
-        }
-
-    }
-
-    /**
-     * Holder of a chain of {@linkplain InstrumentationProbeNode probes}: manages the
-     * {@link Assumption} that the chain has not changed since checked checked.
-     * <p>
-     * May be categorized by one or more {@linkplain NodePhylum node phyla}, signifying information
-     * useful for instrumentation about its AST location(s).
-     */
-    public static final class ProbeChain extends DefaultProbeNode implements PhylumMarked {
-
-        @CompilerDirectives.CompilationFinal private Assumption probeUnchanged;
-
-        /**
-         * When in stepping mode, ordinary line breakpoints are ignored, but every entry at a line
-         * will cause a halt.
-         */
-        @CompilerDirectives.CompilationFinal private boolean stepping;
-
-        /**
-         * Source information about the node to which this probe chain is attached; it isn't
-         * otherwise available. A probe chain is shared by every copy made during runtime, so there
-         * is no parent pointer.
-         */
-        private final SourceSection probedSourceSection;
-
-        private final Set<NodePhylum> phyla = EnumSet.noneOf(NodePhylum.class);
-
-        private final String description; // for debugging
-
-        /**
-         * Creates a new, empty chain of {@linkplain InstrumentationProbeNode probes}, to which
-         * probes can be added/removed, and all of which will be notified of
-         * {@linkplain InstrumentationProbeEvents events} when the chain is notified.
-         */
-        public ProbeChain(ExecutionContext context, SourceSection sourceSection, String description) {
-            super(context);
-            this.probeUnchanged = Truffle.getRuntime().createAssumption();
-            this.probedSourceSection = sourceSection;
-            this.description = description;
-            this.next = null;
-        }
-
-        public int probeCount() {
-            return countProbes();
-        }
-
-        public String getDescription() {
-            return description;
-        }
-
-        public SourceSection getProbedSourceSection() {
-            return probedSourceSection;
-        }
-
-        /**
-         * Mark this probe chain as being associated with an AST node in some category useful for
-         * debugging and other tools.
-         */
-        public void markAs(NodePhylum phylum) {
-            assert phylum != null;
-            phyla.add(phylum);
-        }
-
-        /**
-         * Is this probe chain as being associated with an AST node in some category useful for
-         * debugging and other tools.
-         */
-        public boolean isMarkedAs(NodePhylum phylum) {
-            assert phylum != null;
-            return phyla.contains(phylum);
-        }
-
-        /**
-         * In which categories is the AST (with which this probe is associated) marked?
-         */
-        public Set<NodePhylum> getPhylumMarks() {
-            return phyla;
-        }
-
-        /**
-         * Change <em>stepping mode</em> for statements.
-         */
-        public void setStepping(boolean stepping) {
-            if (this.stepping != stepping) {
-                this.stepping = stepping;
-                probeUnchanged.invalidate();
-                probeUnchanged = Truffle.getRuntime().createAssumption();
-            }
-        }
-
-        @Override
-        protected boolean isStepping() {
-            return stepping;
-        }
-
-        @Override
-        protected int countProbes() {
-            // The head of the chain does not itself hold a probe
-            return next == null ? 0 : next.countProbes();
-        }
-
-        @Override
-        protected void notifyProbeChanged(InstrumentationProbeNode probeNode) {
-            probeUnchanged.invalidate();
-            probeUnchanged = Truffle.getRuntime().createAssumption();
-        }
-
-        @CompilerDirectives.SlowPath
-        public void appendProbe(InstrumentationProbeNode newProbeNode) {
-            probeUnchanged.invalidate();
-            super.internalAppendProbe(newProbeNode);
-            probeUnchanged = Truffle.getRuntime().createAssumption();
-        }
-
-        @CompilerDirectives.SlowPath
-        public void removeProbe(InstrumentationProbeNode oldProbeNode) {
-            probeUnchanged.invalidate();
-            super.internalRemoveProbe(oldProbeNode);
-            probeUnchanged = Truffle.getRuntime().createAssumption();
-        }
-
-        public void notifyEnter(Node astNode, VirtualFrame frame) {
-            if (stepping || next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                if (stepping) {
-                    getContext().getDebugContext().getDebugManager().haltedAt(astNode, frame);
-                }
-                if (next != null) {
-                    next.internalEnter(astNode, frame);
-                }
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, byte result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, short result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, int result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, long result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, char result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, float result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, double result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeave(Node astNode, VirtualFrame frame, Object result) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeave(astNode, frame, result);
-            }
-        }
-
-        public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalLeaveExceptional(astNode, frame, e);
-            }
-        }
-
-        public void notifyReplace(Node oldAstNode, Node newAstNode, String reason) {
-            if (next != null) {
-                if (!probeUnchanged.isValid()) {
-                    CompilerDirectives.transferToInterpreter();
-                }
-                next.internalReplace(oldAstNode, newAstNode, reason);
-            }
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProxyNode.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, 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.nodes.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
-
-/**
- * Interface implemented by language-specific Truffle <strong>proxy nodes</strong>: nodes that do
- * not participate in the language's execution semantics, but which are inserted into an AST so that
- * tools (e.g. tracers, analyzers, debuggers) can be notified of AST interpretation events and
- * possibly intervene.
- * <p>
- * Language-specific proxy nodes call notification methods on an attached {@linkplain ProbeChain
- * probe chain} which passes along {@linkplain InstrumentationProbeEvents events} to any
- * {@linkplain InstrumentationProbeNode probes} that might have been attached.
- */
-public interface InstrumentationProxyNode extends InstrumentationNode, PhylumMarked {
-
-    /**
-     * Gets the non-instrumentation node being proxied.
-     */
-    Node getChild();
-
-    /**
-     * Gets the chain of probes to which events at this node are delegated. Note that a chain of
-     * probes may be used by more than one proxy.
-     */
-    ProbeChain getProbeChain();
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodeInstrumenter.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nodes.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Implements the instrumentation of a Truffle AST node and returning either:
- * <ul>
- * <li>the node itself, or</li>
- * <li>a newly created {@linkplain InstrumentationProxyNode proxy node} that holds the instrumented
- * node as its {@linkplain com.oracle.truffle.api.nodes.Node.Child child}.</li>
- * </ul>
- */
-public interface NodeInstrumenter {
-
-    /**
-     * Wraps a {@linkplain InstrumentationProxyNode proxy node} around a node (if not already
-     * wrapped), marks the location with a {@linkplain NodePhylum phylum (category)} for user
-     * interaction, and passes along any characteristics of the particular node that are important
-     * for instrumentation (e.g. the function/method name at a call).
-     */
-    Node instrumentAs(Node node, NodePhylum phylum, Object... args);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodePhylum.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nodes.instrument;
-
-/**
- * Categories of {@link InstrumentationProxyNode}s to be used for defining user-visible debugging
- * and other simple tool behavior. These categories (<em>phyla</em>) should correspond to program
- * structures that are meaningful to a programmer using the guest language. A Truffle node without a
- * proxy carrying some phylum should be treated as an artifact of the guest language implementation
- * and should never be visible to the user of a guest language programming tool.
- * <p>
- * Note that phyla are not intended to represent a partition of user-visible node categories, as the
- * relative categorization of nodes can change with the particular programming tasks at hand.
- * <p>
- * This is a somewhat language-agnostic set of phyla, suitable for conventional imperative
- * languages, and is being developed incrementally.
- * <p>
- * The need for alternative sets of phyla is likely to arise, perhaps for other families of
- * languages (for example for mostly expression-oriented languages) or even for specific languages.
- * <p>
- * These are listed alphabetically so that listing from some collection classes will come out in
- * that order.
- * <p>
- * <strong>Disclaimer:</strong> this interface is under development and will change.
- */
-public enum NodePhylum {
-
-    /**
-     * Marker for a proxy at a variable assignment.
-     */
-    ASSIGNMENT,
-
-    /**
-     * Marker for a proxy at a call site.
-     */
-    CALL,
-
-    /**
-     * Marker for a proxy at which ordinary "stepping" should halt.
-     */
-    STATEMENT;
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/PhylumMarked.java	Thu Mar 27 16:38:39 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nodes.instrument;
-
-import java.util.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A kind of {@link Node} that can be marked as belong to 0 or more {@linkplain NodePhylum phyla}.
- */
-public interface PhylumMarked {
-
-    /**
-     * Is this proxy tagged as belonging to a particular category of language constructs?
-     */
-    boolean isMarkedAs(NodePhylum phylum);
-
-    /**
-     * In which categories is this node tagged (<em>empty set</em> if none).
-     */
-    Set<NodePhylum> getPhylumMarks();
-
-}