changeset 22293:260e3cdf11ec

Truffle/Instrumentation: replace (non-functional) AdvancedInstrument kind with new EvalInstrument - new API much simpler: only new method Instrumenter.attach() plus new kind of listener - removed the "expected result type check", which is now left to clients - the code to be evaluated now represented as a Source
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Thu, 08 Oct 2015 16:48:42 -0400
parents 371045b1312d
children 9f478b9db4f7
files truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestingLanguage.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TestingLanguage.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/AdvancedInstrumentTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestNodes.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestingLanguage.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Breakpoint.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/EvalInstrumentListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TagInstrument.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/ToolTestUtil.java
diffstat 28 files changed, 451 insertions(+), 683 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestingLanguage.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestingLanguage.java	Thu Oct 08 16:48:42 2015 -0400
@@ -27,8 +27,6 @@
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.Visualizer;
 import com.oracle.truffle.api.instrument.WrapperNode;
 import com.oracle.truffle.api.nodes.Node;
@@ -82,11 +80,6 @@
     }
 
     @Override
-    protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-        return null;
-    }
-
-    @Override
     protected Object createContext(Env env) {
         return null;
     }
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java	Thu Oct 08 16:48:42 2015 -0400
@@ -28,8 +28,6 @@
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.dsl.test.ExpectError;
 import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.Visualizer;
 import com.oracle.truffle.api.instrument.WrapperNode;
 import com.oracle.truffle.api.nodes.Node;
@@ -100,11 +98,6 @@
         }
 
         @Override
-        protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-            return null;
-        }
-
-        @Override
         protected Object createContext(Env env) {
             throw new UnsupportedOperationException();
         }
@@ -159,11 +152,6 @@
         }
 
         @Override
-        protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-            return null;
-        }
-
-        @Override
         protected Object createContext(Env env) {
             throw new UnsupportedOperationException();
         }
@@ -214,11 +202,6 @@
         }
 
         @Override
-        protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-            return null;
-        }
-
-        @Override
         protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
             throw new IOException();
         }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TestingLanguage.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TestingLanguage.java	Thu Oct 08 16:48:42 2015 -0400
@@ -27,8 +27,6 @@
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.Visualizer;
 import com.oracle.truffle.api.instrument.WrapperNode;
 import com.oracle.truffle.api.nodes.Node;
@@ -81,11 +79,6 @@
     }
 
     @Override
-    protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-        return null;
-    }
-
-    @Override
     protected Object createContext(Env env) {
         return null;
     }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/AdvancedInstrumentTest.java	Thu Oct 01 20:32:49 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.test.instrument;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-
-import org.junit.Test;
-
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRoot;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
-import com.oracle.truffle.api.instrument.Instrumenter;
-import com.oracle.truffle.api.instrument.Probe;
-import com.oracle.truffle.api.instrument.SyntaxTag;
-import com.oracle.truffle.api.instrument.impl.DefaultProbeListener;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestAdvancedInstrumentCounterRoot;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestingLanguage.InstrumentTestTag;
-import com.oracle.truffle.api.vm.PolyglotEngine;
-
-/**
- * Tests the kind of instrumentation where a client can provide an AST fragment to be
- * <em>spliced</em> directly into the AST.
- */
-public class AdvancedInstrumentTest {
-
-    @Test
-    public void testAdvancedInstrumentListener() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
-
-        final PolyglotEngine vm = PolyglotEngine.buildNew().build();
-        final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
-        field.setAccessible(true);
-        final Instrumenter instrumenter = (Instrumenter) field.get(vm);
-
-        instrumenter.registerASTProber(new InstrumentationTestingLanguage.TestASTProber());
-        final Source source = Source.fromText("testAdvancedInstrumentListener text", "testAdvancedInstrumentListener").withMimeType("text/x-instTest");
-
-        final Probe[] addNodeProbe = new Probe[1];
-        instrumenter.addProbeListener(new DefaultProbeListener() {
-
-            @Override
-            public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
-                if (tag == InstrumentTestTag.ADD_TAG) {
-                    assertNull("only one add node", addNodeProbe[0]);
-                    addNodeProbe[0] = probe;
-                }
-            }
-        });
-        assertEquals(vm.eval(source).get(), 13);
-        assertNotNull("Add node should be probed", addNodeProbe[0]);
-
-        // Attach a factory that never actually attaches a node.
-        final AdvancedInstrumentRootFactory rootFactory1 = new AdvancedInstrumentRootFactory() {
-
-            public AdvancedInstrumentRoot createInstrumentRoot(Probe p, Node n) {
-                return null;
-            }
-        };
-        instrumenter.attach(addNodeProbe[0], null, rootFactory1, null, "test AdvancedInstrument");
-
-        assertEquals(vm.eval(source).get(), 13);
-
-        // Attach a factory that splices an execution counter into the AST.
-        final TestAdvancedInstrumentCounterRoot counter = new TestAdvancedInstrumentCounterRoot();
-        final AdvancedInstrumentRootFactory rootFactory2 = new AdvancedInstrumentRootFactory() {
-
-            public AdvancedInstrumentRoot createInstrumentRoot(Probe p, Node n) {
-                return counter;
-            }
-        };
-        instrumenter.attach(addNodeProbe[0], null, rootFactory2, null, "test AdvancedInstrument");
-
-        assertEquals(0, counter.getCount());
-        assertEquals(vm.eval(source).get(), 13);
-        assertEquals(1, counter.getCount());
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java	Thu Oct 08 16:48:42 2015 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.test.instrument;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.instrument.EvalInstrumentListener;
+import com.oracle.truffle.api.instrument.Instrument;
+import com.oracle.truffle.api.instrument.Instrumenter;
+import com.oracle.truffle.api.instrument.Probe;
+import com.oracle.truffle.api.instrument.SyntaxTag;
+import com.oracle.truffle.api.instrument.impl.DefaultProbeListener;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestingLanguage.InstrumentTestTag;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+
+/**
+ * Tests the kind of instrumentation where a client can provide guest language code to be
+ * <em>spliced</em> directly into the AST.
+ */
+public class EvalInstrumentTest {
+
+    PolyglotEngine vm;
+    Instrumenter instrumenter;
+
+    @Before
+    public void before() {
+        // TODO (mlvdv) eventually abstract this
+        try {
+            vm = PolyglotEngine.buildNew().build();
+            final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
+            field.setAccessible(true);
+            instrumenter = (Instrumenter) field.get(vm);
+            final java.lang.reflect.Field testVMField = Instrumenter.class.getDeclaredField("testVM");
+            testVMField.setAccessible(true);
+            testVMField.set(instrumenter, vm);
+        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
+            fail("Reflective access to Instrumenter for testing");
+        }
+    }
+
+    @After
+    public void after() {
+        vm.dispose();
+        vm = null;
+        instrumenter = null;
+    }
+
+    @Test
+    public void testEvalInstrumentListener() throws IOException {
+
+        instrumenter.registerASTProber(new InstrumentationTestingLanguage.TestASTProber());
+        final Source source13 = InstrumentationTestingLanguage.createAdditionSource13("testEvalInstrumentListener");
+
+        final Probe[] addNodeProbe = new Probe[1];
+        instrumenter.addProbeListener(new DefaultProbeListener() {
+
+            @Override
+            public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
+                if (tag == InstrumentTestTag.ADD_TAG) {
+                    addNodeProbe[0] = probe;
+                }
+            }
+        });
+        assertEquals(vm.eval(source13).get(), 13);
+        assertNotNull("Add node should be probed", addNodeProbe[0]);
+
+        final Source source42 = InstrumentationTestingLanguage.createConstantSource42("testEvalInstrumentListener");
+        final int[] evalResult = {0};
+        final int[] evalCount = {0};
+        final Instrument instrument = instrumenter.attach(addNodeProbe[0], InstrumentationTestingLanguage.class, source42, new EvalInstrumentListener() {
+
+            public void onExecution(Node node, VirtualFrame vFrame, Object result) {
+                evalCount[0] = evalCount[0] + 1;
+                if (result instanceof Integer) {
+                    evalResult[0] = (Integer) result;
+                }
+            }
+
+            public void onFailure(Node node, VirtualFrame vFrame, Exception ex) {
+                fail("Eval test evaluates without exception");
+
+            }
+        }, "test EvalInstrument");
+
+        assertEquals(vm.eval(source13).get(), 13);
+        assertEquals(evalCount[0], 1);
+        assertEquals(evalResult[0], 42);
+
+        // Second execution; same result
+        assertEquals(vm.eval(source13).get(), 13);
+        assertEquals(evalCount[0], 2);
+        assertEquals(evalResult[0], 42);
+
+        // Add new eval instrument with no listener, no effect on third execution
+        instrumenter.attach(addNodeProbe[0], InstrumentationTestingLanguage.class, source42, null, "");
+        assertEquals(vm.eval(source13).get(), 13);
+        assertEquals(evalCount[0], 3);
+        assertEquals(evalResult[0], 42);
+
+        // Remove original instrument; no further effect from fourth execution
+        instrument.dispose();
+        evalResult[0] = 0;
+        assertEquals(vm.eval(source13).get(), 13);
+        assertEquals(evalCount[0], 3);
+        assertEquals(evalResult[0], 0);
+    }
+}
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java	Thu Oct 08 16:48:42 2015 -0400
@@ -69,7 +69,7 @@
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
         instrumenter.registerASTProber(new TestASTProber(instrumenter));
-        final Source source = Source.fromText("testProbing text", "testProbing").withMimeType("text/x-instTest");
+        final Source source = InstrumentationTestingLanguage.createAdditionSource13("testProbing");
 
         final Probe[] probes = new Probe[3];
         instrumenter.addProbeListener(new DefaultProbeListener() {
@@ -110,7 +110,7 @@
         final Field field = PolyglotEngine.class.getDeclaredField("instrumenter");
         field.setAccessible(true);
         final Instrumenter instrumenter = (Instrumenter) field.get(vm);
-        final Source source = Source.fromText("testTagging text", "testTagging").withMimeType("text/x-instTest");
+        final Source source = InstrumentationTestingLanguage.createAdditionSource13("testTagging");
 
         // Applies appropriate tags
         final TestASTProber astProber = new TestASTProber(instrumenter);
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestNodes.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestNodes.java	Thu Oct 08 16:48:42 2015 -0400
@@ -24,7 +24,6 @@
 
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRoot;
 import com.oracle.truffle.api.instrument.EventHandlerNode;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.KillException;
@@ -187,23 +186,4 @@
         }
     }
 
-    static class TestAdvancedInstrumentCounterRoot extends AdvancedInstrumentRoot {
-
-        private long count;
-
-        @Override
-        public Object executeRoot(Node node, VirtualFrame vFrame) {
-            count++;
-            return null;
-        }
-
-        public long getCount() {
-            return count;
-        }
-
-        public String instrumentationInfo() {
-            return null;
-        }
-    }
-
 }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestingLanguage.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestingLanguage.java	Thu Oct 08 16:48:42 2015 -0400
@@ -30,8 +30,6 @@
 import com.oracle.truffle.api.TruffleRuntime;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.instrument.ASTProber;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.SyntaxTag;
 import com.oracle.truffle.api.instrument.Visualizer;
@@ -51,6 +49,19 @@
 
     public static final InstrumentationTestingLanguage INSTANCE = new InstrumentationTestingLanguage();
 
+    private static final String ADD_SOURCE_TEXT = "Fake source text for testing:  parses to 6 + 7";
+    private static final String CONSTANT_SOURCE_TEXT = "Fake source text for testing: parses to 42";
+
+    /** Use a unique test name to avoid unexpected CallTarget sharing. */
+    static Source createAdditionSource13(String testName) {
+        return Source.fromText(ADD_SOURCE_TEXT, testName).withMimeType("text/x-instTest");
+    }
+
+    /** Use a unique test name to avoid unexpected CallTarget sharing. */
+    static Source createConstantSource42(String testName) {
+        return Source.fromText(CONSTANT_SOURCE_TEXT, testName).withMimeType("text/x-instTest");
+    }
+
     static enum InstrumentTestTag implements SyntaxTag {
 
         ADD_TAG("addition", "test language addition node"),
@@ -78,14 +89,24 @@
     }
 
     @Override
-    protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
-        final TestValueNode leftValueNode = new TestValueNode(6);
-        final TestValueNode rightValueNode = new TestValueNode(7);
-        final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
-        final InstrumentationTestRootNode rootNode = new InstrumentationTestRootNode(addNode);
-        final TruffleRuntime runtime = Truffle.getRuntime();
-        final CallTarget callTarget = runtime.createCallTarget(rootNode);
-        return callTarget;
+    protected CallTarget parse(Source source, Node context, String... argumentNames) throws IOException {
+        if (source.getCode().equals(ADD_SOURCE_TEXT)) {
+            final TestValueNode leftValueNode = new TestValueNode(6);
+            final TestValueNode rightValueNode = new TestValueNode(7);
+            final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
+            final InstrumentationTestRootNode rootNode = new InstrumentationTestRootNode(addNode);
+            final TruffleRuntime runtime = Truffle.getRuntime();
+            final CallTarget callTarget = runtime.createCallTarget(rootNode);
+            return callTarget;
+        }
+        if (source.getCode().equals(CONSTANT_SOURCE_TEXT)) {
+            final TestValueNode constantNode = new TestValueNode(42);
+            final InstrumentationTestRootNode rootNode = new InstrumentationTestRootNode(constantNode);
+            final TruffleRuntime runtime = Truffle.getRuntime();
+            final CallTarget callTarget = runtime.createCallTarget(rootNode);
+            return callTarget;
+        }
+        return null;
     }
 
     @Override
@@ -127,11 +148,6 @@
     }
 
     @Override
-    protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-        return null;
-    }
-
-    @Override
     protected Object createContext(Env env) {
         return null;
     }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Thu Oct 08 16:48:42 2015 -0400
@@ -45,8 +45,6 @@
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.Visualizer;
 import com.oracle.truffle.api.instrument.WrapperNode;
 import com.oracle.truffle.api.nodes.Node;
@@ -210,11 +208,6 @@
             return null;
         }
 
-        @Override
-        protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-            return null;
-        }
-
         private Object importExport(Source code) {
             assertNotEquals("Should run asynchronously", Thread.currentThread(), mainThread);
             final Node node = createFindContextNode();
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/InitializationTest.java	Thu Oct 08 16:48:42 2015 -0400
@@ -22,10 +22,10 @@
  */
 package com.oracle.truffle.api.test.vm;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.lang.reflect.Field;
@@ -42,8 +42,6 @@
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.instrument.ASTProber;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.EventHandlerNode;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.Probe;
@@ -101,22 +99,17 @@
 
         Source source = Source.fromText("accessProbeForAbstractLanguage text", "accessProbeForAbstractLanguage").withMimeType("application/x-abstrlang");
 
-        vm.eval(source);
+        assertEquals(vm.eval(source).get(), 1);
 
         assertNotNull("Debugger found", arr[0]);
 
-        try {
-            Debugger d = arr[0];
-            Breakpoint b = d.setLineBreakpoint(0, source.createLineLocation(1), true);
-            assertTrue(b.isEnabled());
-            b.setCondition("true");
+        Debugger d = arr[0];
+        Breakpoint b = d.setLineBreakpoint(0, source.createLineLocation(1), true);
+        assertTrue(b.isEnabled());
+        b.setCondition("true");
 
-            vm.eval(source);
-        } catch (InstrumentOKException ex) {
-            // OK
-            return;
-        }
-        fail("We should properly call up to TestLanguage.createAdvancedInstrumentRootFactory");
+        assertEquals(vm.eval(source).get(), 1);
+        vm.dispose();
     }
 
     private static final class MMRootNode extends RootNode {
@@ -220,11 +213,6 @@
         }
 
         @Override
-        public AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) {
-            throw new InstrumentOKException();
-        }
-
-        @Override
         public Visualizer getVisualizer() {
             throw new UnsupportedOperationException();
         }
@@ -239,8 +227,4 @@
             return node instanceof ANode ? new ANodeWrapper((ANode) node) : null;
         }
     }
-
-    private static final class InstrumentOKException extends RuntimeException {
-        static final long serialVersionUID = 1L;
-    }
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Thu Oct 08 16:48:42 2015 -0400
@@ -46,9 +46,6 @@
 import com.oracle.truffle.api.impl.Accessor;
 import com.oracle.truffle.api.impl.FindContextNode;
 import com.oracle.truffle.api.instrument.ASTProber;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRoot;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.SyntaxTag;
 import com.oracle.truffle.api.instrument.Visualizer;
@@ -269,21 +266,6 @@
     protected abstract Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws IOException;
 
     /**
-     * Creates a language-specific factory to produce instances of {@link AdvancedInstrumentRoot}
-     * that, when executed, computes the result of a textual expression in the language; used to
-     * create an
-     * {@linkplain Instrumenter#attach(com.oracle.truffle.api.instrument.Probe, AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)}
-     * .
-     *
-     * @param expr a guest language expression
-     * @param resultListener optional listener for the result of each evaluation.
-     * @return a new factory
-     * @throws IOException if the factory cannot be created, for example if the expression is badly
-     *             formed.
-     */
-    protected abstract AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException;
-
-    /**
      * Allows a language implementor to create a node that can effectively lookup up the context
      * associated with current execution. The context is created by
      * {@link #createContext(com.oracle.truffle.api.TruffleLanguage.Env)} method.
@@ -449,6 +431,11 @@
         private static final Map<Source, CallTarget> COMPILED = Collections.synchronizedMap(new WeakHashMap<Source, CallTarget>());
 
         @Override
+        protected CallTarget parse(TruffleLanguage<?> truffleLanguage, Source code, Node context, String... argumentNames) throws IOException {
+            return truffleLanguage.parse(code, context, argumentNames);
+        }
+
+        @Override
         protected Object eval(TruffleLanguage<?> language, Source source) throws IOException {
             CallTarget target = COMPILED.get(source);
             if (target == null) {
@@ -477,15 +464,6 @@
             return target.call();
         }
 
-        @SuppressWarnings("deprecation")
-        @Override
-        protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(Object vm, Class<? extends TruffleLanguage> languageClass, String expr,
-                        AdvancedInstrumentResultListener resultListener) throws IOException {
-
-            final TruffleLanguage language = findLanguageImpl(vm, languageClass);
-            return language.createAdvancedInstrumentRootFactory(expr, resultListener);
-        }
-
         @Override
         protected Object findExportedSymbol(TruffleLanguage.Env env, String globalName, boolean onlyExplicit) {
             return env.langCtx.findExportedSymbol(globalName, onlyExplicit);
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Breakpoint.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Breakpoint.java	Thu Oct 08 16:48:42 2015 -0400
@@ -142,10 +142,10 @@
     public abstract void setCondition(String expr) throws IOException;
 
     /**
-     * Gets the string, expressed in the Guest Language, that defines the current condition on this
-     * breakpoint; {@code null} if this breakpoint is currently unconditional.
+     * Gets the text that defines the current condition on this breakpoint; {@code null} if this
+     * breakpoint is currently unconditional.
      */
-    public String getCondition() {
+    public Source getCondition() {
         return null;
     }
 
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java	Thu Oct 08 16:48:42 2015 -0400
@@ -34,14 +34,11 @@
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.frame.FrameInstance;
 import com.oracle.truffle.api.frame.FrameInstanceVisitor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.impl.Accessor;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRoot;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.KillException;
 import com.oracle.truffle.api.instrument.Probe;
@@ -273,26 +270,6 @@
         debugContext.setStrategy(new StepOver(stepCount));
     }
 
-    // TODO (mlvdv) used by the breakpoint factories; to be deprecated/replaced.
-    /**
-     * Creates a language-specific factory to produce instances of {@link AdvancedInstrumentRoot}
-     * that, when executed, computes the result of a textual expression in the language; used to
-     * create an
-     * {@linkplain Instrumenter#attach(Probe, AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
-     * Advanced Instrument}.
-     *
-     * @param expr a guest language expression
-     * @param resultListener optional listener for the result of each evaluation.
-     * @return a new factory
-     * @throws IOException if the factory cannot be created, for example if the expression is badly
-     *             formed.
-     */
-    @SuppressWarnings("rawtypes")
-    AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(Probe probe, String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-        Class<? extends TruffleLanguage> languageClass = ACCESSOR.findLanguage(probe);
-        return ACCESSOR.createAdvancedInstrumentRootFactory(vm, languageClass, expr, resultListener);
-    }
-
     Instrumenter getInstrumenter() {
         return instrumenter;
     }
@@ -860,7 +837,7 @@
     }
 
     @SuppressWarnings("rawtypes")
-    private static final class AccessorDebug extends Accessor {
+    static final class AccessorDebug extends Accessor {
 
         @Override
         protected Closeable executionStart(Object vm, final Debugger debugger, Source s) {
@@ -883,13 +860,6 @@
             return super.findLanguage(probe);
         }
 
-        @SuppressWarnings("deprecation")
-        @Override
-        protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(Object vm, Class<? extends TruffleLanguage> languageClass, String expr,
-                        AdvancedInstrumentResultListener resultListener) throws IOException {
-            return super.createAdvancedInstrumentRootFactory(vm, languageClass, expr, resultListener);
-        }
-
         @Override
         protected void dispatchEvent(Object vm, Object event) {
             super.dispatchEvent(vm, event);
@@ -902,5 +872,5 @@
     }
 
     // registers into Accessor.DEBUG
-    private static final AccessorDebug ACCESSOR = new AccessorDebug();
+    static final AccessorDebug ACCESSOR = new AccessorDebug();
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java	Thu Oct 08 16:48:42 2015 -0400
@@ -44,13 +44,14 @@
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.debug.Debugger.BreakpointCallback;
 import com.oracle.truffle.api.debug.Debugger.WarningLog;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.ProbeInstrument;
+import com.oracle.truffle.api.instrument.EvalInstrumentListener;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.Probe;
+import com.oracle.truffle.api.instrument.ProbeInstrument;
 import com.oracle.truffle.api.instrument.StandardSyntaxTag;
 import com.oracle.truffle.api.instrument.SyntaxTag;
 import com.oracle.truffle.api.instrument.impl.DefaultProbeListener;
@@ -58,6 +59,7 @@
 import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.LineLocation;
+import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.api.utilities.CyclicAssumption;
 
@@ -153,14 +155,7 @@
                             // A Probe with line location tagged STATEMENT we haven't seen before.
                             final LineBreakpointImpl breakpoint = lineToBreakpoint.get(lineLocation);
                             if (breakpoint != null) {
-                                try {
-                                    breakpoint.attach(probe);
-                                } catch (IOException e) {
-                                    warningLog.addWarning(BREAKPOINT_NAME + " failure attaching to newly tagged Probe: " + e.getMessage());
-                                    if (TRACE) {
-                                        OUT.println(BREAKPOINT_NAME + " failure: " + e.getMessage());
-                                    }
-                                }
+                                breakpoint.attach(probe);
                             }
                         }
                     }
@@ -273,7 +268,7 @@
      * Concrete representation of a line breakpoint, implemented by attaching an instrument to a
      * probe at the designated source location.
      */
-    private final class LineBreakpointImpl extends LineBreakpoint implements AdvancedInstrumentResultListener {
+    private final class LineBreakpointImpl extends LineBreakpoint implements EvalInstrumentListener {
 
         private static final String SHOULD_NOT_HAPPEN = "LineBreakpointImpl:  should not happen";
 
@@ -286,7 +281,7 @@
         @CompilationFinal private boolean isEnabled;
         private Assumption enabledUnchangedAssumption;
 
-        private String conditionExpr;
+        private Source conditionSource;
 
         /**
          * The instrument(s) that this breakpoint currently has attached to a {@link Probe}:
@@ -344,7 +339,7 @@
 
         @Override
         public void setCondition(String expr) throws IOException {
-            if (this.conditionExpr != null || expr != null) {
+            if (this.conditionSource != null || expr != null) {
                 // De-instrument the Probes instrumented by this breakpoint
                 final ArrayList<Probe> probes = new ArrayList<>();
                 for (ProbeInstrument instrument : instruments) {
@@ -352,7 +347,7 @@
                     instrument.dispose();
                 }
                 instruments.clear();
-                this.conditionExpr = expr;
+                this.conditionSource = Source.fromText(expr, "breakpoint condition from text: " + expr);
                 // Re-instrument the probes previously instrumented
                 for (Probe probe : probes) {
                     attach(probe);
@@ -361,8 +356,8 @@
         }
 
         @Override
-        public String getCondition() {
-            return conditionExpr;
+        public Source getCondition() {
+            return conditionSource;
         }
 
         @TruffleBoundary
@@ -377,16 +372,18 @@
             }
         }
 
-        private void attach(Probe newProbe) throws IOException {
+        @SuppressWarnings("rawtypes")
+        private void attach(Probe newProbe) {
             if (getState() == DISPOSED) {
                 throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME);
             }
             ProbeInstrument newInstrument = null;
             final Instrumenter instrumenter = debugger.getInstrumenter();
-            if (conditionExpr == null) {
+            if (conditionSource == null) {
                 newInstrument = instrumenter.attach(newProbe, new UnconditionalLineBreakInstrumentListener(), BREAKPOINT_NAME);
             } else {
-                newInstrument = instrumenter.attach(newProbe, this, debugger.createAdvancedInstrumentRootFactory(newProbe, conditionExpr, this), Boolean.class, BREAKPOINT_NAME);
+                final Class<? extends TruffleLanguage> languageClass = Debugger.ACCESSOR.findLanguage(newProbe);
+                newInstrument = instrumenter.attach(newProbe, languageClass, conditionSource, this, BREAKPOINT_NAME);
             }
             instruments.add(newInstrument);
             changeState(isEnabled ? ENABLED : DISABLED);
@@ -447,16 +444,20 @@
         }
 
         public void onExecution(Node node, VirtualFrame vFrame, Object result) {
-            final boolean condition = (Boolean) result;
-            if (TRACE) {
-                trace("breakpoint condition = %b  %s", condition, getShortDescription());
-            }
-            if (condition) {
-                nodeEnter(node, vFrame);
+            if (result instanceof Boolean) {
+                final boolean condition = (Boolean) result;
+                if (TRACE) {
+                    trace("breakpoint condition = %b  %s", condition, getShortDescription());
+                }
+                if (condition) {
+                    nodeEnter(node, vFrame);
+                }
+            } else {
+                onFailure(node, vFrame, new RuntimeException("breakpint failure = non-boolean condition " + result.toString()));
             }
         }
 
-        public void onFailure(Node node, VirtualFrame vFrame, RuntimeException ex) {
+        public void onFailure(Node node, VirtualFrame vFrame, Exception ex) {
             addExceptionWarning(ex);
             if (TRACE) {
                 trace("breakpoint failure = %s  %s", ex, getShortDescription());
@@ -466,7 +467,7 @@
         }
 
         @TruffleBoundary
-        private void addExceptionWarning(RuntimeException ex) {
+        private void addExceptionWarning(Exception ex) {
             warningLog.addWarning(String.format("Exception in %s:  %s", getShortDescription(), ex.getMessage()));
         }
 
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java	Thu Oct 08 16:48:42 2015 -0400
@@ -42,10 +42,11 @@
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.debug.Debugger.BreakpointCallback;
 import com.oracle.truffle.api.debug.Debugger.WarningLog;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
+import com.oracle.truffle.api.instrument.EvalInstrumentListener;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.Probe;
 import com.oracle.truffle.api.instrument.ProbeInstrument;
@@ -54,6 +55,7 @@
 import com.oracle.truffle.api.instrument.impl.DefaultStandardInstrumentListener;
 import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.utilities.CyclicAssumption;
 
 // TODO (mlvdv) some common functionality could be factored out of this and LineBreakpointSupport
@@ -132,14 +134,7 @@
             public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
                 final TagBreakpointImpl breakpoint = tagToBreakpoint.get(tag);
                 if (breakpoint != null) {
-                    try {
-                        breakpoint.attach(probe);
-                    } catch (IOException e) {
-                        warningLog.addWarning(BREAKPOINT_NAME + " failure attaching to newly tagged Probe: " + e.getMessage());
-                        if (TRACE) {
-                            OUT.println(BREAKPOINT_NAME + " failure: " + e.getMessage());
-                        }
-                    }
+                    breakpoint.attach(probe);
                 }
             }
         });
@@ -242,7 +237,7 @@
      * Concrete representation of a line breakpoint, implemented by attaching an instrument to a
      * probe at the designated source location.
      */
-    private final class TagBreakpointImpl extends TagBreakpoint implements AdvancedInstrumentResultListener {
+    private final class TagBreakpointImpl extends TagBreakpoint implements EvalInstrumentListener {
 
         private static final String SHOULD_NOT_HAPPEN = "TagBreakpointImpl:  should not happen";
 
@@ -255,7 +250,7 @@
         @CompilationFinal private boolean isEnabled;
         private Assumption enabledUnchangedAssumption;
 
-        private String conditionExpr;
+        private Source conditionSource;
 
         /**
          * The instrument(s) that this breakpoint currently has attached to a {@link Probe}:
@@ -305,7 +300,7 @@
 
         @Override
         public void setCondition(String expr) throws IOException {
-            if (this.conditionExpr != null || expr != null) {
+            if (this.conditionSource != null || expr != null) {
                 // De-instrument the Probes instrumented by this breakpoint
                 final ArrayList<Probe> probes = new ArrayList<>();
                 for (ProbeInstrument instrument : instruments) {
@@ -313,7 +308,7 @@
                     instrument.dispose();
                 }
                 instruments.clear();
-                this.conditionExpr = expr;
+                this.conditionSource = Source.fromText(expr, "breakpoint condition for text: " + expr);
                 // Re-instrument the probes previously instrumented
                 for (Probe probe : probes) {
                     attach(probe);
@@ -322,8 +317,8 @@
         }
 
         @Override
-        public String getCondition() {
-            return conditionExpr;
+        public Source getCondition() {
+            return conditionSource;
         }
 
         @TruffleBoundary
@@ -338,16 +333,18 @@
             }
         }
 
-        private void attach(Probe newProbe) throws IOException {
+        @SuppressWarnings("rawtypes")
+        private void attach(Probe newProbe) {
             if (getState() == DISPOSED) {
                 throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME);
             }
             ProbeInstrument newInstrument = null;
             final Instrumenter instrumenter = debugger.getInstrumenter();
-            if (conditionExpr == null) {
+            if (conditionSource == null) {
                 newInstrument = instrumenter.attach(newProbe, new UnconditionalTagBreakInstrumentListener(), BREAKPOINT_NAME);
             } else {
-                instrumenter.attach(newProbe, this, debugger.createAdvancedInstrumentRootFactory(newProbe, conditionExpr, this), Boolean.class, BREAKPOINT_NAME);
+                final Class<? extends TruffleLanguage> languageClass = Debugger.ACCESSOR.findLanguage(newProbe);
+                instrumenter.attach(newProbe, languageClass, conditionSource, this, BREAKPOINT_NAME);
             }
             instruments.add(newInstrument);
             changeState(isEnabled ? ENABLED : DISABLED);
@@ -409,16 +406,20 @@
         }
 
         public void onExecution(Node node, VirtualFrame vFrame, Object result) {
-            final boolean condition = (Boolean) result;
-            if (TRACE) {
-                trace("breakpoint condition = %b  %s", condition, getShortDescription());
-            }
-            if (condition) {
-                nodeEnter(node, vFrame);
+            if (result instanceof Boolean) {
+                final boolean condition = (Boolean) result;
+                if (TRACE) {
+                    trace("breakpoint condition = %b  %s", condition, getShortDescription());
+                }
+                if (condition) {
+                    nodeEnter(node, vFrame);
+                }
+            } else {
+                onFailure(node, vFrame, new RuntimeException("breakpint failure = non-boolean condition " + result.toString()));
             }
         }
 
-        public void onFailure(Node node, VirtualFrame vFrame, RuntimeException ex) {
+        public void onFailure(Node node, VirtualFrame vFrame, Exception ex) {
             addExceptionWarning(ex);
             if (TRACE) {
                 trace("breakpoint failure = %s  %s", ex, getShortDescription());
@@ -428,7 +429,7 @@
         }
 
         @TruffleBoundary
-        private void addExceptionWarning(RuntimeException ex) {
+        private void addExceptionWarning(Exception ex) {
             warningLog.addWarning(String.format("Exception in %s:  %s", getShortDescription(), ex.getMessage()));
         }
 
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Thu Oct 08 16:48:42 2015 -0400
@@ -41,8 +41,6 @@
 import com.oracle.truffle.api.frame.FrameInstance;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.instrument.ASTProber;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.Probe;
 import com.oracle.truffle.api.instrument.Visualizer;
@@ -108,11 +106,6 @@
             protected Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws IOException {
                 return null;
             }
-
-            @Override
-            protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-                return null;
-            }
         };
         lng.hashCode();
         new Node(null) {
@@ -209,13 +202,6 @@
         return API.createWrapperNode(node, language);
     }
 
-    @Deprecated
-    @SuppressWarnings("rawtypes")
-    protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(Object vm, Class<? extends TruffleLanguage> languageClass, String expr, AdvancedInstrumentResultListener resultListener)
-                    throws IOException {
-        return API.createAdvancedInstrumentRootFactory(vm, languageClass, expr, resultListener);
-    }
-
     @SuppressWarnings("rawtypes")
     protected Class<? extends TruffleLanguage> findLanguage(RootNode n) {
         return NODES.findLanguage(n);
@@ -341,4 +327,15 @@
     protected void dispose(TruffleLanguage<?> impl, Env env) {
         API.dispose(impl, env);
     }
+
+    @SuppressWarnings("rawtypes")
+    protected CallTarget parse(Class<? extends TruffleLanguage> languageClass, Source code, Node context, String... argumentNames) throws IOException {
+        final TruffleLanguage<?> truffleLanguage = findLanguageImpl(null, languageClass);
+        return parse(truffleLanguage, code, context, argumentNames);
+    }
+
+    protected CallTarget parse(TruffleLanguage<?> truffleLanguage, Source code, Node context, String... argumentNames) throws IOException {
+        return API.parse(truffleLanguage, code, context, argumentNames);
+    }
+
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java	Thu Oct 01 20:32:49 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.Node;
-
-/**
- * Listener for receiving the result a client-provided {@linkplain AdvancedInstrumentRoot AST
- * fragment}, when executed by a
- * {@linkplain Instrumenter#attach(Probe, AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
- * Advanced Instrument}.
- * <p>
- * Notification is fully synchronous, so overrides have performance implications. Non-trivial
- * methods should be coded with Truffle guidelines and cautions in mind.
- *
- * @see ProbeInstrument
- * @see AdvancedInstrumentRoot
- * @see AdvancedInstrumentRootFactory
- */
-public interface AdvancedInstrumentResultListener {
-
-    /**
-     * Notifies listener that a client-provided {@linkplain AdvancedInstrumentRoot AST fragment} has
-     * been executed by an
-     * {@linkplain Instrumenter#attach(Probe, AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
-     * Advanced Instrument} with the specified result, possibly {@code null}.
-     * <p>
-     * <strong>Note: </strong> Truffle will attempt to optimize implementations through partial
-     * evaluation; annotate with {@link TruffleBoundary} if this should not be permitted.
-     *
-     * @param node the guest-language AST node to which the host Instrument's {@link Probe} is
-     *            attached
-     * @param vFrame execution frame at the guest-language AST node
-     * @param result the result of this AST fragment's execution
-     */
-    void onExecution(Node node, VirtualFrame vFrame, Object result);
-
-    /**
-     * Notifies listener that execution of client-provided {@linkplain AdvancedInstrumentRoot AST
-     * fragment} filed during execution by a @linkplain
-     * Instrument#create(AdvancedInstrumentRootFactory, String) Advanced Instrument}.
-     * <p>
-     * <strong>Note: </strong> Truffle will attempt to optimize implementations through partial
-     * evaluation; annotate with {@link TruffleBoundary} if this should not be permitted.
-     *
-     * @param node the guest-language AST node to which the host Instrument's {@link Probe} is
-     *            attached
-     * @param vFrame execution frame at the guest-language AST node
-     * @param ex the exception
-     */
-    void onFailure(Node node, VirtualFrame vFrame, RuntimeException ex);
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java	Thu Oct 01 20:32:49 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.Node;
-
-/**
- * Root of a client-provided AST fragment that can be executed efficiently, subject to full Truffle
- * optimization, by an
- * {@linkplain Instrumenter#attach(Probe, AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
- * Advanced Instrument}.
- *
- * @see ProbeInstrument
- * @see AdvancedInstrumentRootFactory
- * @see AdvancedInstrumentResultListener
- */
-public abstract class AdvancedInstrumentRoot extends Node implements InstrumentationNode {
-
-    /**
-     * Executes this AST fragment on behalf of a client {@link ProbeInstrument}, just before the
-     * guest-language AST node to which the {@link Probe} holding the Instrument is executed.
-     *
-     * @param node the guest-language AST node to which the host Instrument's Probe is attached
-     * @param vFrame execution frame at the guest-language AST node
-     * @return the result of this AST fragment's execution
-     */
-    public abstract Object executeRoot(Node node, VirtualFrame vFrame);
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java	Thu Oct 01 20:32:49 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.nodes.Node;
-
-/**
- * Creator of {@linkplain AdvancedInstrumentRoot AST fragments} suitable for efficient execution,
- * subject to full Truffle optimization, by an
- * {@linkplain Instrumenter#attach(Probe, AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
- * Advanced Instrument}.
- *
- * @see ProbeInstrument
- * @see AdvancedInstrumentRoot
- */
-public interface AdvancedInstrumentRootFactory {
-
-    /**
-     * Provider of {@linkplain AdvancedInstrumentRoot AST fragment} instances to be executed by the
-     * {@linkplain Instrumenter Instrumentation Framework} at a {@linkplain Probe Probed} site in a
-     * guest-language AST.
-     * <p>
-     * <strong>Notes:</strong>
-     * <ul>
-     * <li>Once the factory has produced an AST fragment at a particular {@linkplain Node AST Node},
-     * it will not be called again at that Node.</li>
-     * <li>In some use cases, for example to implement a breakpoint at a specific program location,
-     * the Probe argument will be the same for every call. Each Node argument will represent the
-     * same program location associated with the Probe, but in different clones of the AST.</li>
-     * <li>In other use cases, for example to implement a breakpoint at any Node with a particular
-     * {@linkplain SyntaxTag tag}, both the Probe and Node argument may differ. Implementations that
-     * are sensitive to the lexical context in which the AST fragment will be evaluated must take
-     * care to build a new, possibly different AST fragment for each request.</li>
-     * </ul>
-     *
-     * @param probe the Probe to which the Instrument requesting the AST fragment is attached
-     * @param node the guest-language AST location that is the context in which the requesting
-     *            Instrument must execute the AST fragment.
-     * @return a newly created AST fragment suitable for execution, via instrumentation, in the
-     *         execution context of the specified guest-language AST site.
-     */
-    AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/EvalInstrumentListener.java	Thu Oct 08 16:48:42 2015 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
+
+/**
+ * Listener for receiving the result a client-provided Guest Language expression
+ * {@linkplain Instrumenter#attach(Probe, Class, Source, EvalListener, String) attached} to a
+ * {@link Probe}.
+ * <p>
+ * Notification is fully synchronous, so method bodies have performance implications. Non-trivial
+ * methods should be coded with Truffle guidelines and cautions in mind.
+ *
+ * @see Instrumenter
+ */
+public interface EvalInstrumentListener {
+
+    /**
+     * Notifies listener that a client-provided Guest Language expression
+     * {@linkplain Instrumenter#attach(Probe, Class, Source, EvalListener, String) attached} to a
+     * {@link Probe} has just been executed with the specified result, possibly {@code null}.
+     * <p>
+     * <strong>Note: </strong> Truffle will attempt to optimize implementations through partial
+     * evaluation; annotate with {@link TruffleBoundary} if this should not be permitted.
+     *
+     * @param node the guest language AST node at which the expression was evaluated
+     * @param vFrame execution frame at the guest-language AST node
+     * @param result expression evaluation
+     */
+    void onExecution(Node node, VirtualFrame vFrame, Object result);
+
+    /**
+     * Notifies listener that a client-provided Guest Language expression
+     * {@linkplain Instrumenter#attach(Probe, Class, Source, EvalListener, String) attached} to a
+     * {@link Probe} has just been executed and generated an exception. The exception does not
+     * affect Guest language evaluation; the only report is to listeners implementing this methods.
+     * <p>
+     * <strong>Note: </strong> Truffle will attempt to optimize implementations through partial
+     * evaluation; annotate with {@link TruffleBoundary} if this should not be permitted.
+     *
+     * @param node the guest-language AST node to which the host Instrument's {@link Probe} is
+     *            attached
+     * @param vFrame execution frame at the guest-language AST node
+     * @param ex the exception
+     */
+    void onFailure(Node node, VirtualFrame vFrame, Exception ex);
+
+}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java	Thu Oct 08 16:48:42 2015 -0400
@@ -39,19 +39,39 @@
  */
 public abstract class Instrument {
 
-    protected Instrument() {
+    /** Optional string for debugging. */
+    private final String instrumentInfo;
+
+    private boolean isDisposed = false;
+
+    protected Instrument(String instrumentInfo) {
+        this.instrumentInfo = instrumentInfo;
     }
 
     /**
-     * Detaches this from its source of execution events and renders itself unusable.
+     * Detaches this from its source of execution events and makes itself unusable.
      *
      * @throws IllegalStateException if this has already been disposed
      */
-    public abstract void dispose() throws IllegalStateException;
+    public void dispose() throws IllegalStateException {
+        if (isDisposed) {
+            throw new IllegalStateException("Istruments only dispose once");
+        }
+        innerDispose();
+        this.isDisposed = true;
+    }
 
     /**
-     * Has this been detached from its source of execution events.
+     * Has this been detached from its source of execution events?
      */
-    public abstract boolean isDisposed();
+    public boolean isDisposed() {
+        return isDisposed;
+    }
+
+    protected final String getInstrumentInfo() {
+        return instrumentInfo;
+    }
+
+    protected abstract void innerDispose();
 
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java	Thu Oct 08 16:48:42 2015 -0400
@@ -24,6 +24,7 @@
  */
 package com.oracle.truffle.api.instrument;
 
+import java.io.IOException;
 import java.io.PrintStream;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -34,9 +35,11 @@
 import java.util.List;
 import java.util.Set;
 
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.impl.Accessor;
+import com.oracle.truffle.api.instrument.ProbeInstrument.EvalInstrument;
 import com.oracle.truffle.api.instrument.TagInstrument.AfterTagInstrument;
 import com.oracle.truffle.api.instrument.TagInstrument.BeforeTagInstrument;
 import com.oracle.truffle.api.nodes.Node;
@@ -422,13 +425,13 @@
      * {@linkplain EventHandlerNode execution events} taking place at the Probe's AST location to
      * the listener.
      *
-     * @param probe source of AST execution events
+     * @param probe source of AST execution events, non-null
      * @param listener receiver of execution events
      * @param instrumentInfo optional documentation about the Instrument
      * @return a handle for access to the binding
      */
-    @SuppressWarnings("static-method")
     public ProbeInstrument attach(Probe probe, SimpleInstrumentListener listener, String instrumentInfo) {
+        assert probe.getInstrumenter() == this;
         final ProbeInstrument instrument = new ProbeInstrument.SimpleInstrument(listener, instrumentInfo);
         probe.attach(instrument);
         return instrument;
@@ -441,42 +444,45 @@
      * {@linkplain EventHandlerNode execution events} taking place at the Probe's AST location to
      * the listener.
      *
-     * @param probe source of AST execution events
+     * @param probe source of AST execution events, non-null
      * @param listener receiver of execution events
      * @param instrumentInfo optional documentation about the Instrument
      * @return a handle for access to the binding
      */
-    @SuppressWarnings("static-method")
     public ProbeInstrument attach(Probe probe, StandardInstrumentListener listener, String instrumentInfo) {
+        assert probe.getInstrumenter() == this;
         final ProbeInstrument instrument = new ProbeInstrument.StandardInstrument(listener, instrumentInfo);
         probe.attach(instrument);
         return instrument;
     }
 
     /**
-     * <em>Attaches</em> a {@link AdvancedInstrumentResultListener listener} to a {@link Probe},
-     * creating a <em>binding</em> called an {@link ProbeInstrument}. Until the Instrument is
-     * {@linkplain ProbeInstrument#dispose() disposed}, it routes synchronous notification of
-     * {@linkplain EventHandlerNode execution events} taking place at the Probe's AST location to
-     * the listener.
+     * <em>Attaches</em> a fragment of source text that is to be evaluated just before execution
+     * enters the location of a {@link Probe}, creating a <em>binding</em> called an
+     * {@link ProbeInstrument}. The outcome of the evaluation is reported to an optional
+     * {@link EvalInstrumentListener listener}, but the outcome does not affect the flow of guest
+     * language execution, even if the evaluation produces an exception.
      * <p>
-     * This Instrument executes efficiently, subject to full Truffle optimization, a client-provided
-     * AST fragment every time the Probed node is entered.
+     * The source text is assumed to be expressed in the language identified by its associated
+     * {@linkplain Source#getMimeType() MIME type}, if specified, otherwise by the language
+     * associated with the AST location associated with the {@link Probe}.
      * <p>
-     * Any {@link RuntimeException} thrown by execution of the fragment is caught by the framework
-     * and reported to the listener; there is no other notification.
+     * The source text is parsed in the lexical context of the AST location associated with the
+     * {@link Probe}.
+     * <p>
+     * The source text executes subject to full Truffle optimization.
      *
-     * @param probe source of AST execution events
+     * @param probe source of AST execution events, non-null
+     * @param languageClass the language in which the source text is to be executed
+     * @param source the source code to be evaluated, non-null and non-empty
      * @param listener optional client callback for results/failure notification
-     * @param rootFactory provider of AST fragments on behalf of the client
-     * @param requiredResultType optional requirement, any non-assignable result is reported to the
-     *            the listener, if any, as a failure
      * @param instrumentInfo instrumentInfo optional documentation about the Instrument
      * @return a handle for access to the binding
      */
-    @SuppressWarnings("static-method")
-    public ProbeInstrument attach(Probe probe, AdvancedInstrumentResultListener listener, AdvancedInstrumentRootFactory rootFactory, Class<?> requiredResultType, String instrumentInfo) {
-        final ProbeInstrument instrument = new ProbeInstrument.AdvancedInstrument(listener, rootFactory, requiredResultType, instrumentInfo);
+    @SuppressWarnings("rawtypes")
+    public ProbeInstrument attach(Probe probe, Class<? extends TruffleLanguage> languageClass, Source source, EvalInstrumentListener listener, String instrumentInfo) {
+        assert probe.getInstrumenter() == this;
+        final EvalInstrument instrument = new EvalInstrument(languageClass, source, listener, instrumentInfo);
         probe.attach(instrument);
         return instrument;
     }
@@ -630,7 +636,7 @@
         }
 
         @Override
-        public WrapperNode createWrapperNode(Object vm, Node node) {
+        protected WrapperNode createWrapperNode(Object vm, Node node) {
             return super.createWrapperNode(vm, node);
         }
 
@@ -646,6 +652,12 @@
             return probe.getLanguage();
         }
 
+        @SuppressWarnings("rawtypes")
+        @Override
+        protected CallTarget parse(Class<? extends TruffleLanguage> languageClass, Source code, Node context, String... argumentNames) throws IOException {
+            return super.parse(languageClass, code, context, argumentNames);
+        }
+
         @Override
         protected void probeAST(RootNode rootNode) {
             // Normally null vm argument; can be reflectively set for testing
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Thu Oct 08 16:48:42 2015 -0400
@@ -329,4 +329,8 @@
         sb.append("]");
         return sb.toString();
     }
+
+    Instrumenter getInstrumenter() {
+        return instrumenter;
+    }
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java	Thu Oct 08 16:48:42 2015 -0400
@@ -24,12 +24,18 @@
  */
 package com.oracle.truffle.api.instrument;
 
+import java.io.IOException;
+
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.impl.DefaultDirectCallNode;
+import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 
 /**
@@ -49,15 +55,7 @@
  */
 public abstract class ProbeInstrument extends Instrument {
 
-    /**
-     * Optional documentation, mainly for debugging.
-     */
-    private final String instrumentInfo;
-
-    /**
-     * Has this instrument been disposed? stays true once set.
-     */
-    private boolean isDisposed = false;
+    private static final String[] NO_ARGS = new String[0];
 
     protected Probe probe = null;
 
@@ -117,44 +115,31 @@
      * </ul>
      */
     private ProbeInstrument(String instrumentInfo) {
-        this.instrumentInfo = instrumentInfo;
+        super(instrumentInfo);
     }
 
     /**
      * Removes this Instrument from the Probe to which it attached and renders this Instrument
      * inert.
-     *
-     * @throws IllegalStateException if this instrument has already been disposed
      */
     @Override
-    public void dispose() throws IllegalStateException {
-        if (isDisposed) {
-            throw new IllegalStateException("Attempt to dispose an already disposed Instrumennt");
-        }
+    protected void innerDispose() {
         if (probe != null) {
             // It's attached
             probe.disposeInstrument(this);
             probe = null;
         }
-        this.isDisposed = true;
-    }
-
-    @Override
-    public boolean isDisposed() {
-        return isDisposed;
     }
 
     /**
-     * Gets the {@link Probe} to which this Instrument is currently attached: {@code null} if not
-     * yet attached to a Probe or if this Instrument has been {@linkplain #dispose() disposed}.
+     * Gets the {@link Probe} to which this {@link Instrument} is currently attached: {@code null}
+     * if not yet attached to a Probe or if this Instrument has been {@linkplain #dispose()
+     * disposed}.
      */
     public Probe getProbe() {
         return probe;
     }
 
-    /**
-     * For internal implementation only.
-     */
     void setAttachedTo(Probe probe) {
         this.probe = probe;
     }
@@ -250,6 +235,11 @@
                 final String info = getInstrumentInfo();
                 return info != null ? info : simpleListener.getClass().getSimpleName();
             }
+
+            @Override
+            public Probe getProbe() {
+                return SimpleInstrument.this.probe;
+            }
         }
     }
 
@@ -337,30 +327,36 @@
                 final String info = getInstrumentInfo();
                 return info != null ? info : standardListener.getClass().getSimpleName();
             }
+
+            @Override
+            public Probe getProbe() {
+                return StandardInstrument.this.probe;
+            }
         }
     }
 
     /**
-     * An instrument that allows clients to provide an AST fragment to be executed directly from
+     * An instrument that allows clients to provide guest language code to be executed directly from
      * within a Probe's <em>instrumentation chain</em>, and thus directly in the executing Truffle
      * AST with potential for full optimization.
      */
-    static final class AdvancedInstrument extends ProbeInstrument {
+    static final class EvalInstrument extends ProbeInstrument {
 
-        private final AdvancedInstrumentResultListener resultListener;
-        private final AdvancedInstrumentRootFactory rootFactory;
-        private final Class<?> requiredResultType;
+        @SuppressWarnings("rawtypes") private final Class<? extends TruffleLanguage> languageClass;
+        private final Source source;
+        private final EvalInstrumentListener evalListener;
 
-        AdvancedInstrument(AdvancedInstrumentResultListener resultListener, AdvancedInstrumentRootFactory rootFactory, Class<?> requiredResultType, String instrumentInfo) {
+        @SuppressWarnings("rawtypes")
+        EvalInstrument(Class<? extends TruffleLanguage> languageClass, Source source, EvalInstrumentListener evalListener, String instrumentInfo) {
             super(instrumentInfo);
-            this.resultListener = resultListener;
-            this.rootFactory = rootFactory;
-            this.requiredResultType = requiredResultType;
+            this.languageClass = languageClass;
+            this.source = source;
+            this.evalListener = evalListener;
         }
 
         @Override
         AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
-            return new AdvancedInstrumentNode(nextNode);
+            return new EvalInstrumentNode(nextNode);
         }
 
         @Override
@@ -372,7 +368,7 @@
                     return instrumentNode.nextInstrumentNode;
                 }
                 // Match not at the head of the chain; remove it.
-                found = instrumentNode.removeFromChain(AdvancedInstrument.this);
+                found = instrumentNode.removeFromChain(EvalInstrument.this);
             }
             if (!found) {
                 throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
@@ -381,43 +377,42 @@
         }
 
         /**
-         * Node that implements a {@link AdvancedInstrument} in a particular AST.
+         * Node that implements an {@link EvalInstrument} in a particular AST.
          */
         @NodeInfo(cost = NodeCost.NONE)
-        private final class AdvancedInstrumentNode extends AbstractInstrumentNode {
+        private final class EvalInstrumentNode extends AbstractInstrumentNode {
 
-            @Child private AdvancedInstrumentRoot instrumentRoot;
+            @Child private DirectCallNode callNode;
 
-            private AdvancedInstrumentNode(AbstractInstrumentNode nextNode) {
+            private EvalInstrumentNode(AbstractInstrumentNode nextNode) {
                 super(nextNode);
             }
 
             @Override
             public void enter(Node node, VirtualFrame vFrame) {
-                if (instrumentRoot == null) {
+                if (callNode == null) {
                     try {
-                        final AdvancedInstrumentRoot newInstrumentRoot = AdvancedInstrument.this.rootFactory.createInstrumentRoot(AdvancedInstrument.this.probe, node);
-                        if (newInstrumentRoot != null) {
-                            instrumentRoot = newInstrumentRoot;
+                        final CallTarget callTarget = Instrumenter.ACCESSOR.parse(languageClass, source, node, NO_ARGS);
+                        if (callTarget != null) {
+                            callNode = new DefaultDirectCallNode(callTarget);  // force inlining?
                             adoptChildren();
-                            AdvancedInstrument.this.probe.invalidateProbeUnchanged();
+                            EvalInstrument.this.probe.invalidateProbeUnchanged();
                         }
-                    } catch (RuntimeException ex) {
-                        if (resultListener != null) {
-                            resultListener.onFailure(node, vFrame, ex);
+                    } catch (RuntimeException | IOException ex) {
+                        if (evalListener != null) {
+                            evalListener.onFailure(node, vFrame, ex);
                         }
                     }
                 }
-                if (instrumentRoot != null) {
+                if (callNode != null) {
                     try {
-                        final Object result = instrumentRoot.executeRoot(node, vFrame);
-                        if (resultListener != null) {
-                            checkResultType(result);
-                            resultListener.onExecution(node, vFrame, result);
+                        final Object result = callNode.call(vFrame, null);
+                        if (evalListener != null) {
+                            evalListener.onExecution(node, vFrame, result);
                         }
                     } catch (RuntimeException ex) {
-                        if (resultListener != null) {
-                            resultListener.onFailure(node, vFrame, ex);
+                        if (evalListener != null) {
+                            evalListener.onFailure(node, vFrame, ex);
                         }
                     }
                 }
@@ -426,28 +421,6 @@
                 }
             }
 
-            private void checkResultType(Object result) {
-                if (requiredResultType == null) {
-                    return;
-                }
-                if (result == null) {
-                    throw instrumentResultNull();
-                }
-                if (!(requiredResultType.isAssignableFrom(result.getClass()))) {
-                    throw instrumentResultWrongType(result);
-                }
-            }
-
-            @TruffleBoundary
-            private RuntimeException instrumentResultNull() {
-                return new RuntimeException("Instrument result null: " + requiredResultType.getSimpleName() + " is required");
-            }
-
-            @TruffleBoundary
-            private RuntimeException instrumentResultWrongType(Object result) {
-                return new RuntimeException("Instrument result " + result.toString() + " not assignable to " + requiredResultType.getSimpleName());
-            }
-
             @Override
             public void returnVoid(Node node, VirtualFrame vFrame) {
                 if (nextInstrumentNode != null) {
@@ -472,7 +445,7 @@
             @Override
             public String instrumentationInfo() {
                 final String info = getInstrumentInfo();
-                return info != null ? info : rootFactory.getClass().getSimpleName();
+                return info != null ? info : getInstrumentInfo();
             }
         }
     }
@@ -612,7 +585,7 @@
         }
 
         protected String getInstrumentInfo() {
-            return ProbeInstrument.this.instrumentInfo;
+            return ProbeInstrument.this.getInstrumentInfo();
         }
     }
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TagInstrument.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TagInstrument.java	Thu Oct 08 16:48:42 2015 -0400
@@ -41,38 +41,14 @@
  */
 public abstract class TagInstrument extends Instrument {
 
-    /**
-     * Optional documentation, mainly for debugging.
-     */
-    @SuppressWarnings("unused") private final String instrumentInfo;
-
     protected Instrumenter instrumenter;
 
-    /**
-     * Has this instrument been disposed? stays true once set.
-     */
-    protected boolean isDisposed = false;
-
     private SyntaxTag tag = null;
 
     protected TagInstrument(Instrumenter instrumenter, SyntaxTag tag, String instrumentInfo) {
+        super(instrumentInfo);
         this.instrumenter = instrumenter;
         this.tag = tag;
-        this.instrumentInfo = instrumentInfo;
-    }
-
-    @Override
-    public void dispose() throws IllegalStateException {
-        if (isDisposed) {
-            throw new IllegalStateException("Attempt to dispose an already disposed Instrumennt");
-        }
-        instrumenter.disposeAfterTagInstrument();
-        this.isDisposed = true;
-    }
-
-    @Override
-    public boolean isDisposed() {
-        return isDisposed;
     }
 
     public SyntaxTag getTag() {
@@ -93,12 +69,8 @@
         }
 
         @Override
-        public void dispose() throws IllegalStateException {
-            if (isDisposed) {
-                throw new IllegalStateException("Disposed Instrument can not be disposed again");
-            }
+        protected void innerDispose() {
             instrumenter.disposeBeforeTagInstrument();
-            this.isDisposed = true;
         }
     }
 
@@ -116,12 +88,8 @@
         }
 
         @Override
-        public void dispose() throws IllegalStateException {
-            if (isDisposed) {
-                throw new IllegalStateException("Disposed Instrument can not be disposed again");
-            }
+        protected void innerDispose() {
             instrumenter.disposeAfterTagInstrument();
-            this.isDisposed = true;
         }
     }
 }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Thu Oct 08 16:48:42 2015 -0400
@@ -56,8 +56,6 @@
 import com.oracle.truffle.api.dsl.NodeFactory;
 import com.oracle.truffle.api.dsl.UnsupportedSpecializationException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.Visualizer;
 import com.oracle.truffle.api.instrument.WrapperNode;
 import com.oracle.truffle.api.nodes.GraphPrintVisitor;
@@ -509,11 +507,6 @@
         throw new IllegalStateException("evalInContext not supported in this language");
     }
 
-    @Override
-    protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-        throw new IllegalStateException("createAdvancedInstrumentRootFactory not supported in this language");
-    }
-
     public Node createFindContextNode0() {
         return createFindContextNode();
     }
--- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java	Thu Oct 08 16:48:42 2015 -0400
@@ -111,7 +111,7 @@
         infoMessage.put(REPLMessage.BREAKPOINT_IGNORE_COUNT, Integer.toString(breakpoint.getIgnoreCount()));
         infoMessage.put(REPLMessage.INFO_VALUE, breakpoint.getLocationDescription().toString());
         if (breakpoint.getCondition() != null) {
-            infoMessage.put(REPLMessage.BREAKPOINT_CONDITION, breakpoint.getCondition());
+            infoMessage.put(REPLMessage.BREAKPOINT_CONDITION, breakpoint.getCondition().getCode());
         }
         infoMessage.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
         return infoMessage;
--- a/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/ToolTestUtil.java	Thu Oct 01 20:32:49 2015 +0200
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/ToolTestUtil.java	Thu Oct 08 16:48:42 2015 -0400
@@ -33,8 +33,6 @@
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.instrument.ASTProber;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
-import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
 import com.oracle.truffle.api.instrument.EventHandlerNode;
 import com.oracle.truffle.api.instrument.Instrumenter;
 import com.oracle.truffle.api.instrument.KillException;
@@ -139,11 +137,6 @@
         }
 
         @Override
-        protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
-            return null;
-        }
-
-        @Override
         protected Object createContext(Env env) {
             return null;
         }