# HG changeset patch # User Thomas Wuerthinger # Date 1426246027 -3600 # Node ID 79682c7f2ec7b18f56728c8e40b6f8ae9123469a # Parent 5d624638e8a55b14ac680af58a368f48bc84f017# Parent e87d55dfbbbb579b16654bcddd0adfac901a36a0 Merge. diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Fri Mar 13 12:27:07 2015 +0100 @@ -42,6 +42,15 @@ @Input ValueNode object; @Input ValueNode mirror; + public static LogicNode create(ConstantReflectionProvider constantReflection, ValueNode mirror, ValueNode object) { + LogicNode synonym = findSynonym(constantReflection, object, mirror); + if (synonym != null) { + return synonym; + } + return new InstanceOfDynamicNode(mirror, object); + + } + public InstanceOfDynamicNode(ValueNode mirror, ValueNode object) { super(TYPE); this.mirror = mirror; @@ -56,9 +65,9 @@ tool.getLowerer().lower(this, tool); } - public LogicNode canonical(CanonicalizerTool tool, ValueNode forObject, ValueNode forMirror) { + private static LogicNode findSynonym(ConstantReflectionProvider constantReflection, ValueNode forObject, ValueNode forMirror) { if (forMirror.isConstant()) { - ResolvedJavaType t = tool.getConstantReflection().asJavaType(forMirror.asConstant()); + ResolvedJavaType t = constantReflection.asJavaType(forMirror.asConstant()); if (t != null) { if (t.isPrimitive()) { return LogicConstantNode.contradiction(); @@ -67,7 +76,15 @@ } } } - return this; + return null; + } + + public LogicNode canonical(CanonicalizerTool tool, ValueNode forObject, ValueNode forMirror) { + LogicNode res = findSynonym(tool.getConstantReflection(), forObject, forMirror); + if (res == null) { + res = this; + } + return res; } public ValueNode object() { diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Fri Mar 13 12:27:07 2015 +0100 @@ -359,7 +359,7 @@ r.register2("isInstance", Receiver.class, Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode type, ValueNode object) { ValueNode nullCheckedType = nullCheckedValue(b, type); - LogicNode condition = b.append(new InstanceOfDynamicNode(nullCheckedType, object).canonical(null, nullCheckedType, object)); + LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getConstantReflection(), nullCheckedType, object)); b.push(Kind.Boolean.getStackKind(), b.append(new ConditionalNode(condition).canonical(null))); return true; } diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/InstrumentationPartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/InstrumentationPartialEvaluationTest.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/InstrumentationPartialEvaluationTest.java Fri Mar 13 12:27:07 2015 +0100 @@ -61,72 +61,144 @@ } @Test - public void constantValueProbedNullInstrument() { + public void constantValueProbedNullInstrument1() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument"); + probe.attach(instrument); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedNullInstrument2() { FrameDescriptor fd = new FrameDescriptor(); AbstractTestNode result = new ConstantTestNode(42); RootTestNode root = new RootTestNode(fd, "constantValue", result); root.adoptChildren(); Probe probe = result.probe(); - Instrument instrument = Instrument.create(new DefaultEventListener(), "Null test Instrument"); + Instrument instrument = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument"); probe.attach(instrument); assertPartialEvalEquals("constant42", root); } @Test - public void constantValueProbedNullInstrumentDisposed() { + public void constantValueProbedNullInstrumentDisposed1() { FrameDescriptor fd = new FrameDescriptor(); AbstractTestNode result = new ConstantTestNode(42); RootTestNode root = new RootTestNode(fd, "constantValue", result); root.adoptChildren(); Probe probe = result.probe(); - Instrument instrument = Instrument.create(new DefaultEventListener(), "Null test Instrument"); + Instrument instrument = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument"); + probe.attach(instrument); + instrument.dispose(); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedNullInstrumentDisposed2() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument"); probe.attach(instrument); instrument.dispose(); assertPartialEvalEquals("constant42", root); } @Test - public void constantValueProbedTwoNullInstruments() { + public void constantValueProbedTwoNullInstruments1() { FrameDescriptor fd = new FrameDescriptor(); AbstractTestNode result = new ConstantTestNode(42); RootTestNode root = new RootTestNode(fd, "constantValue", result); root.adoptChildren(); Probe probe = result.probe(); - Instrument instrument1 = Instrument.create(new DefaultEventListener(), "Null test Instrument 1"); + Instrument instrument1 = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument 1"); probe.attach(instrument1); - Instrument instrument2 = Instrument.create(new DefaultEventListener(), "Null test Instrument 2"); + Instrument instrument2 = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument 2"); probe.attach(instrument2); assertPartialEvalEquals("constant42", root); } @Test - public void constantValueProbedThreeNullInstruments() { + public void constantValueProbedTwoNullInstruments2() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument1 = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument 1"); + probe.attach(instrument1); + Instrument instrument2 = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument 2"); + probe.attach(instrument2); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedThreeNullInstruments1() { FrameDescriptor fd = new FrameDescriptor(); AbstractTestNode result = new ConstantTestNode(42); RootTestNode root = new RootTestNode(fd, "constantValue", result); root.adoptChildren(); Probe probe = result.probe(); - Instrument instrument1 = Instrument.create(new DefaultEventListener(), "Null test Instrument 1"); + Instrument instrument1 = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument 1"); probe.attach(instrument1); - Instrument instrument2 = Instrument.create(new DefaultEventListener(), "Null test Instrument 2"); + Instrument instrument2 = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument 2"); probe.attach(instrument2); - Instrument instrument3 = Instrument.create(new DefaultEventListener(), "Null test Instrument 3"); + Instrument instrument3 = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument 3"); + probe.attach(instrument3); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedThreeNullInstruments2() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument1 = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument 1"); + probe.attach(instrument1); + Instrument instrument2 = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument 2"); + probe.attach(instrument2); + Instrument instrument3 = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument 3"); probe.attach(instrument3); assertPartialEvalEquals("constant42", root); } @Test - public void constantValueProbedThreeNullInstrumentsOneDisposed() { + public void constantValueProbedThreeNullInstrumentsOneDisposed1() { FrameDescriptor fd = new FrameDescriptor(); AbstractTestNode result = new ConstantTestNode(42); RootTestNode root = new RootTestNode(fd, "constantValue", result); root.adoptChildren(); Probe probe = result.probe(); - Instrument instrument1 = Instrument.create(new DefaultEventListener(), "Null test Instrument 1"); + Instrument instrument1 = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument 1"); probe.attach(instrument1); - Instrument instrument2 = Instrument.create(new DefaultEventListener(), "Null test Instrument 2"); + Instrument instrument2 = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument 2"); probe.attach(instrument2); - Instrument instrument3 = Instrument.create(new DefaultEventListener(), "Null test Instrument 3"); + Instrument instrument3 = Instrument.create(new DefaultInstrumentListener(), "Null test Instrument 3"); + probe.attach(instrument3); + instrument2.dispose(); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedThreeNullInstrumentsOneDisposed2() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument1 = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument 1"); + probe.attach(instrument1); + Instrument instrument2 = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument 2"); + probe.attach(instrument2); + Instrument instrument3 = Instrument.create(new DefaultASTInstrumentListener(), "Null test Instrument 3"); probe.attach(instrument3); instrument2.dispose(); assertPartialEvalEquals("constant42", root); @@ -167,13 +239,13 @@ Assert.assertEquals(0, count[0]); // Didn't count anything // Add a counting instrument; this changes the "Probe state" and should cause a deopt - final Instrument countingInstrument = Instrument.create(new DefaultEventListener() { + final Instrument countingInstrument = Instrument.create(new DefaultInstrumentListener() { @Override - public void enter(Node node, VirtualFrame frame) { + public void enter(Probe p) { count[0] = count[0] + 1; } - }); + }, null); probe[0].attach(countingInstrument); Assert.assertEquals(42, callTarget.call()); // Correct result diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Fri Mar 13 12:27:07 2015 +0100 @@ -66,8 +66,17 @@ private final TruffleCache truffleCache; private final GraalTruffleCompilationListener compilationNotify; - private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class, IllegalArgumentException.class, - VirtualMachineError.class, ClassCastException.class}; + // @formatter:off + private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{ + UnexpectedResultException.class, + SlowPathException.class, + ArithmeticException.class, + IllegalArgumentException.class, + VirtualMachineError.class, + StringIndexOutOfBoundsException.class, + ClassCastException.class + }; + // @formatter:off public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability, OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints); diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Fri Mar 13 12:27:07 2015 +0100 @@ -83,7 +83,7 @@ }; @Test - public void testBasicInstrumentation() { + public void testInstrumentationStructure() { // Create a simple addition AST final TruffleRuntime runtime = Truffle.getRuntime(); final TestValueNode leftValueNode = new TestValueNode(6); @@ -117,7 +117,7 @@ assertEquals(13, callTarget1.call()); // Probe the addition node - final Probe probe = addNode.probe(); + addNode.probe(); // Check the modified tree structure assertEquals(addNode, leftValueNode.getParent()); @@ -153,103 +153,129 @@ // Check that the "probed" AST still executes correctly assertEquals(13, callTarget1.call()); + } + + @Test + public void testListeners() { + + // Create a simple addition AST + final TruffleRuntime runtime = Truffle.getRuntime(); + final TestValueNode leftValueNode = new TestValueNode(6); + final TestValueNode rightValueNode = new TestValueNode(7); + final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode); + final TestRootNode rootNode = new TestRootNode(addNode); + + // Creating a call target sets the parent pointers in this tree and is necessary prior to + // checking any parent/child relationships + final CallTarget callTarget = runtime.createCallTarget(rootNode); + // Probe the addition node + final Probe probe = addNode.probe(); + + // Check instrumentation with the simplest kind of counters. + // They should all be removed when the check is finished. + checkCounters(probe, callTarget, rootNode, new TestInstrumentCounter(), new TestInstrumentCounter(), new TestInstrumentCounter()); + + // Now try with the more complex flavor of listener + checkCounters(probe, callTarget, rootNode, new TestASTInstrumentCounter(), new TestASTInstrumentCounter(), new TestASTInstrumentCounter()); + + } + + private static void checkCounters(Probe probe, CallTarget callTarget, RootNode rootNode, TestCounter counterA, TestCounter counterB, TestCounter counterC) { + // Attach a counting instrument to the probe - final TestCounter counterA = new TestCounter(); counterA.attach(probe); // Attach a second counting instrument to the probe - final TestCounter counterB = new TestCounter(); counterB.attach(probe); // Run it again and check that the two instruments are working - assertEquals(13, callTarget1.call()); - assertEquals(counterA.enterCount, 1); - assertEquals(counterA.leaveCount, 1); - assertEquals(counterB.enterCount, 1); - assertEquals(counterB.leaveCount, 1); + assertEquals(13, callTarget.call()); + assertEquals(counterA.enterCount(), 1); + assertEquals(counterA.leaveCount(), 1); + assertEquals(counterB.enterCount(), 1); + assertEquals(counterB.leaveCount(), 1); - // Remove counterA and check the "instrument chain" + // Remove counterA counterA.dispose(); - iterator = probeNode.getChildren().iterator(); // Run it again and check that instrument B is still working but not A - assertEquals(13, callTarget1.call()); - assertEquals(counterA.enterCount, 1); - assertEquals(counterA.leaveCount, 1); - assertEquals(counterB.enterCount, 2); - assertEquals(counterB.leaveCount, 2); + assertEquals(13, callTarget.call()); + assertEquals(counterA.enterCount(), 1); + assertEquals(counterA.leaveCount(), 1); + assertEquals(counterB.enterCount(), 2); + assertEquals(counterB.leaveCount(), 2); // Simulate a split by cloning the AST - final CallTarget callTarget2 = runtime.createCallTarget((TestRootNode) rootNode.copy()); + final CallTarget callTarget2 = Truffle.getRuntime().createCallTarget((TestRootNode) rootNode.copy()); // Run the clone and check that instrument B is still working but not A assertEquals(13, callTarget2.call()); - assertEquals(counterA.enterCount, 1); - assertEquals(counterA.leaveCount, 1); - assertEquals(counterB.enterCount, 3); - assertEquals(counterB.leaveCount, 3); + assertEquals(counterA.enterCount(), 1); + assertEquals(counterA.leaveCount(), 1); + assertEquals(counterB.enterCount(), 3); + assertEquals(counterB.leaveCount(), 3); // Run the original and check that instrument B is still working but not A assertEquals(13, callTarget2.call()); - assertEquals(counterA.enterCount, 1); - assertEquals(counterA.leaveCount, 1); - assertEquals(counterB.enterCount, 4); - assertEquals(counterB.leaveCount, 4); + assertEquals(counterA.enterCount(), 1); + assertEquals(counterA.leaveCount(), 1); + assertEquals(counterB.enterCount(), 4); + assertEquals(counterB.leaveCount(), 4); // Attach a second instrument to the probe - final TestCounter counterC = new TestCounter(); counterC.attach(probe); // Run the original and check that instruments B,C working but not A - assertEquals(13, callTarget1.call()); - assertEquals(counterA.enterCount, 1); - assertEquals(counterA.leaveCount, 1); - assertEquals(counterB.enterCount, 5); - assertEquals(counterB.leaveCount, 5); - assertEquals(counterC.enterCount, 1); - assertEquals(counterC.leaveCount, 1); + assertEquals(13, callTarget.call()); + assertEquals(counterA.enterCount(), 1); + assertEquals(counterA.leaveCount(), 1); + assertEquals(counterB.enterCount(), 5); + assertEquals(counterB.leaveCount(), 5); + assertEquals(counterC.enterCount(), 1); + assertEquals(counterC.leaveCount(), 1); // Run the clone and check that instruments B,C working but not A assertEquals(13, callTarget2.call()); - assertEquals(counterA.enterCount, 1); - assertEquals(counterA.leaveCount, 1); - assertEquals(counterB.enterCount, 6); - assertEquals(counterB.leaveCount, 6); - assertEquals(counterC.enterCount, 2); - assertEquals(counterC.leaveCount, 2); + assertEquals(counterA.enterCount(), 1); + assertEquals(counterA.leaveCount(), 1); + assertEquals(counterB.enterCount(), 6); + assertEquals(counterB.leaveCount(), 6); + assertEquals(counterC.enterCount(), 2); + assertEquals(counterC.leaveCount(), 2); // Remove instrumentC counterC.dispose(); // Run the original and check that instrument B working but not A,C - assertEquals(13, callTarget1.call()); - assertEquals(counterA.enterCount, 1); - assertEquals(counterA.leaveCount, 1); - assertEquals(counterB.enterCount, 7); - assertEquals(counterB.leaveCount, 7); - assertEquals(counterC.enterCount, 2); - assertEquals(counterC.leaveCount, 2); + assertEquals(13, callTarget.call()); + assertEquals(counterA.enterCount(), 1); + assertEquals(counterA.leaveCount(), 1); + assertEquals(counterB.enterCount(), 7); + assertEquals(counterB.leaveCount(), 7); + assertEquals(counterC.enterCount(), 2); + assertEquals(counterC.leaveCount(), 2); // Run the clone and check that instrument B working but not A,C assertEquals(13, callTarget2.call()); - assertEquals(counterA.enterCount, 1); - assertEquals(counterA.leaveCount, 1); - assertEquals(counterB.enterCount, 8); - assertEquals(counterB.leaveCount, 8); - assertEquals(counterC.enterCount, 2); - assertEquals(counterC.leaveCount, 2); + assertEquals(counterA.enterCount(), 1); + assertEquals(counterA.leaveCount(), 1); + assertEquals(counterB.enterCount(), 8); + assertEquals(counterB.leaveCount(), 8); + assertEquals(counterC.enterCount(), 2); + assertEquals(counterC.leaveCount(), 2); // Remove instrumentB counterB.dispose(); // Run both the original and clone, check that no instruments working - assertEquals(13, callTarget1.call()); + assertEquals(13, callTarget.call()); assertEquals(13, callTarget2.call()); - assertEquals(counterA.enterCount, 1); - assertEquals(counterA.leaveCount, 1); - assertEquals(counterB.enterCount, 8); - assertEquals(counterB.leaveCount, 8); - assertEquals(counterC.enterCount, 2); - assertEquals(counterC.leaveCount, 2); + assertEquals(counterA.enterCount(), 1); + assertEquals(counterA.leaveCount(), 1); + assertEquals(counterB.enterCount(), 8); + assertEquals(counterB.leaveCount(), 8); + assertEquals(counterC.enterCount(), 2); + assertEquals(counterC.leaveCount(), 2); + } @Test @@ -313,131 +339,6 @@ } - @Test - public void testProbeLite() { - - // Use the "lite-probing" option, limited to a single pass of - // probing and a single Instrument at each probed node. This - // particular test uses a shared event listener at every - // lite-probed node. - final TestEventListener listener = new TestEventListener(); - - TestASTLiteProber astLiteProber = new TestASTLiteProber(listener); - Probe.registerASTProber(astLiteProber); - - // Create a simple addition AST - final TruffleRuntime runtime = Truffle.getRuntime(); - final TestValueNode leftValueNode = new TestValueNode(6); - final TestValueNode rightValueNode = new TestValueNode(7); - final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode); - final TestRootNode rootNode = new TestRootNode(addNode); - - // Creating a call target sets the parent pointers in this tree and is necessary prior to - // checking any parent/child relationships - final CallTarget callTarget = runtime.createCallTarget(rootNode); - - // Check that the instrument is working as expected. - assertEquals(0, listener.counter); - callTarget.call(); - assertEquals(2, listener.counter); - - // Check that you can't probe a node that's already received a probeLite() call - try { - leftValueNode.probe(); - fail(); - } catch (IllegalStateException e) { - } - - try { - rightValueNode.probe(); - fail(); - } catch (IllegalStateException e) { - } - - // Check tree structure - assertTrue(leftValueNode.getParent() instanceof TestLanguageWrapperNode); - assertTrue(rightValueNode.getParent() instanceof TestLanguageWrapperNode); - TestLanguageWrapperNode leftWrapper = (TestLanguageWrapperNode) leftValueNode.getParent(); - TestLanguageWrapperNode rightWrapper = (TestLanguageWrapperNode) rightValueNode.getParent(); - assertEquals(addNode, leftWrapper.getParent()); - assertEquals(addNode, rightWrapper.getParent()); - Iterator iterator = addNode.getChildren().iterator(); - assertEquals(leftWrapper, iterator.next()); - assertEquals(rightWrapper, iterator.next()); - assertFalse(iterator.hasNext()); - assertEquals(rootNode, addNode.getParent()); - iterator = rootNode.getChildren().iterator(); - assertEquals(addNode, iterator.next()); - assertFalse(iterator.hasNext()); - - // Check that you can't get a probe on the wrappers because they were "lite-probed" - try { - leftWrapper.getProbe(); - fail(); - } catch (IllegalStateException e) { - } - try { - rightWrapper.getProbe(); - fail(); - } catch (IllegalStateException e) { - } - - // Check that you can't probe the wrappers - try { - leftWrapper.probe(); - fail(); - } catch (ProbeException e) { - assertEquals(e.getFailure().getReason(), ProbeFailure.Reason.WRAPPER_NODE); - } - try { - rightWrapper.probe(); - fail(); - } catch (ProbeException e) { - assertEquals(e.getFailure().getReason(), ProbeFailure.Reason.WRAPPER_NODE); - } - try { - leftWrapper.probeLite(null); - fail(); - } catch (ProbeException e) { - assertEquals(e.getFailure().getReason(), ProbeFailure.Reason.WRAPPER_NODE); - } - try { - rightWrapper.probeLite(null); - fail(); - } catch (ProbeException e) { - assertEquals(e.getFailure().getReason(), ProbeFailure.Reason.WRAPPER_NODE); - } - - // Use reflection to check that each WrapperNode has a ProbeLiteNode with a - // SimpleEventListener - try { - java.lang.reflect.Field probeNodeField = leftWrapper.getClass().getDeclaredField("probeNode"); - - // cheat: probeNode is private, so we change it's accessibility at runtime - probeNodeField.setAccessible(true); - ProbeNode probeNode = (ProbeNode) probeNodeField.get(leftWrapper); - - // hack: Since ProbeLiteNode is not visible, we do a string compare here - assertTrue(probeNode.getClass().toString().endsWith("ProbeLiteNode")); - - // Now we do the same to check the type of the eventListener in ProbeLiteNode - java.lang.reflect.Field eventListenerField = probeNode.getClass().getDeclaredField("eventListener"); - eventListenerField.setAccessible(true); - TruffleEventListener eventListener = (TruffleEventListener) eventListenerField.get(probeNode); - assertTrue(eventListener instanceof SimpleEventListener); - - // Reset accessibility - probeNodeField.setAccessible(false); - eventListenerField.setAccessible(false); - - } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { - fail(); - } - - Probe.unregisterASTProber(astLiteProber); - - } - private abstract class TestLanguageNode extends Node { public abstract Object execute(VirtualFrame vFrame); @@ -578,28 +479,51 @@ } } + private interface TestCounter { + + int enterCount(); + + int leaveCount(); + + void attach(Probe probe); + + void dispose(); + + } + /** - * A counter for the number of times execution enters and leaves a probed AST node. + * A counter for the number of times execution enters and leaves a probed AST node, using the + * simplest kind of listener. */ - private class TestCounter { + private class TestInstrumentCounter implements TestCounter { public int enterCount = 0; public int leaveCount = 0; public final Instrument instrument; - public TestCounter() { - instrument = Instrument.create(new SimpleEventListener() { + public TestInstrumentCounter() { + this.instrument = Instrument.create(new SimpleInstrumentListener() { @Override - public void enter(Node node, VirtualFrame vFrame) { + public void enter(Probe probe) { enterCount++; } @Override - public void returnAny(Node node, VirtualFrame vFrame) { + public void returnAny(Probe probe) { leaveCount++; } + }, "Instrumentation Test Counter"); + + } + + public int enterCount() { + return enterCount; + } + + public int leaveCount() { + return leaveCount; } public void attach(Probe probe) { @@ -609,7 +533,50 @@ public void dispose() { instrument.dispose(); } + } + /** + * A counter for the number of times execution enters and leaves a probed AST node, using the + * simplest kind of listener. + */ + private class TestASTInstrumentCounter implements TestCounter { + + public int enterCount = 0; + public int leaveCount = 0; + public final Instrument instrument; + + public TestASTInstrumentCounter() { + this.instrument = Instrument.create(new SimpleASTInstrumentListener() { + + @Override + public void enter(Probe probe, Node node, VirtualFrame vFrame) { + enterCount++; + } + + @Override + public void returnAny(Probe probe, Node node, VirtualFrame vFrame) { + leaveCount++; + } + + }, "Instrumentation Test Counter"); + + } + + public int enterCount() { + return enterCount; + } + + public int leaveCount() { + return leaveCount; + } + + public void attach(Probe probe) { + probe.attach(instrument); + } + + public void dispose() { + instrument.dispose(); + } } /** @@ -641,38 +608,28 @@ } /** - * "lite-probes" every value node with a shared event listener. + * Counts the number of "enter" events at probed nodes using the simplest AST listener. */ - private static final class TestASTLiteProber implements NodeVisitor, ASTProber { - private final TruffleEventListener eventListener; - - public TestASTLiteProber(SimpleEventListener simpleEventListener) { - this.eventListener = simpleEventListener; - } - - public boolean visit(Node node) { - if (node instanceof TestValueNode) { - final TestLanguageNode testNode = (TestValueNode) node; - testNode.probeLite(eventListener); - } - return true; - } - - public void probeAST(Node node) { - node.accept(this); - } - } - - /** - * Counts the number of "enter" events at probed nodes. - * - */ - static final class TestEventListener extends SimpleEventListener { + static final class TestInstrumentListener extends DefaultInstrumentListener { public int counter = 0; @Override - public void enter(Node node, VirtualFrame frame) { + public void enter(Probe probe) { + counter++; + } + + } + + /** + * Counts the number of "enter" events at probed nodes using the AST listener. + */ + static final class TestASTInstrumentListener extends DefaultASTInstrumentListener { + + public int counter = 0; + + @Override + public void enter(Probe probe, Node node, VirtualFrame vFrame) { counter++; } @@ -692,10 +649,10 @@ // where we want to count executions. // it will get copied when ASTs cloned, so // keep the count in this outer class. - probe.attach(Instrument.create(new SimpleEventListener() { + probe.attach(Instrument.create(new DefaultInstrumentListener() { @Override - public void enter(Node node, VirtualFrame vFrame) { + public void enter(Probe p) { count++; } }, "Instrumentation Test MultiCounter")); diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTInstrumentListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTInstrumentListener.java Fri Mar 13 12:27:07 2015 +0100 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.instrument; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * A listener of Truffle AST runtime execution events that can collect information, examine the + * execution state at a particular node, and possibly intervene on behalf of an external tool. + */ +public interface ASTInstrumentListener { + + /** + * Receive notification that an AST node's execute method is about to be called. + */ + void enter(Probe probe, Node node, VirtualFrame vFrame); + + /** + * Receive notification that an AST Node's {@code void}-valued execute method has just returned. + */ + void returnVoid(Probe probe, Node node, VirtualFrame vFrame); + + /** + * Receive notification that an AST Node's execute method has just returned a value (boxed if + * primitive). + */ + void returnValue(Probe probe, Node node, VirtualFrame vFrame, Object result); + + /** + * Receive notification that an AST Node's execute method has just thrown an exception. + */ + void returnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception); + +} diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Fri Mar 13 12:27:07 2015 +0100 @@ -27,45 +27,71 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents; import com.oracle.truffle.api.instrument.impl.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; // TODO (mlvdv) migrate some of this to external documentation. // TODO (mlvdv) move all this to a factory implemented in .impl (together with Probe), // then break out some of the nested classes into package privates. /** * A dynamically added/removed binding between a {@link Probe}, which provides notification of - * {@linkplain TruffleEventListener execution events} taking place at a {@link Node} in a Guest - * Language (GL) Truffle AST, and a {@linkplain TruffleEventListener listener}, which consumes - * notifications on behalf of an external tool. + * execution events taking place at a {@link Node} in a Guest Language (GL) Truffle AST, + * and a listener, which consumes notifications on behalf of an external tool. There are at + * present two kinds of listeners that be used: + *
    + *
  1. {@link InstrumentListener} is the simplest and is intended for tools that require no access + * to the internal execution state of the Truffle execution, only that execution has passed + * through a particular location in the program. Information about that location is made available + * via the {@link Probe} argument in notification methods, including the {@linkplain SourceSection + * source location} of the node and any {@linkplain SyntaxTag tags} that have been applied to the + * node.
  2. + *
  3. {@link ASTInstrumentListener} reports the same events and {@link Probe} argument, but + * additionally provides access to the execution state via the explicit {@link Node} and + * {@link Frame} at the current execution site.
  4. + *
*

*

Summary: How to "instrument" an AST location:

+ *

*

    - *
  1. Create an implementation of {@link TruffleEventListener} that responds to events on behalf of - * a tool.
  2. - *
  3. Create an Instrument via factory method {@link Instrument#create(TruffleEventListener)}.
  4. + *
  5. Create an implementation of a listener interface.
  6. + *
  7. Create an Instrument via factory methods + * {@link Instrument#create(InstrumentListener, String)} or + * {@link Instrument#create(ASTInstrumentListener, String)}.
  8. *
  9. "Attach" the Instrument to a Probe via {@link Probe#attach(Instrument)}, at which point event * notifications begin to arrive at the listener.
  10. - *
  11. When no longer needed, "detach" the Instrument via {@link TruffleEventInstrument#dispose()}, - * at which point event notifications to the listener cease, and the Instrument becomes unusable.
  12. + *
  13. When no longer needed, "detach" the Instrument via {@link ASTInstrument#dispose()}, at which + * point event notifications to the listener cease, and the Instrument becomes unusable.
  14. *
*

*

Options for creating listeners:

*

*

    - *
  1. Implement the interface {@link TruffleEventListener}. The event handling methods account for - * both the entry into an AST node (about to call) and several possible kinds of exit from an AST - * node (just returned).
  2. - *
  3. Extend {@link DefaultEventListener}, which provides a no-op implementation of every - * {@link TruffleEventListener} method; override the methods of interest.
  4. - *
  5. Extend {@link SimpleEventListener}, where return values are ignored so only two methods (for - * "enter" and "return") will notify all events.
  6. + *
  7. Implement one of the listener interfaces: {@link InstrumentListener} or + * {@link ASTInstrumentListener} . Their event handling methods account for both the entry into an + * AST node (about to call) and three possible kinds of execution return from an AST node.
  8. + *
  9. Extend one of the helper implementations: {@link DefaultInstrumentListener} or + * {@link DefaultASTInstrumentListener}. These provide no-op implementation of every listener + * method, so only the methods of interest need to be overridden.
  10. + *
  11. Extend one of the helper implementations: {@link SimpleInstrumentListener} or + * {@link SimpleASTInstrumentListener}. These re-route all execution returns to a single + * method, ignoring return values, so only two methods (for "enter" and "return") will notify all + * events.
  12. *
*

- *

General guidelines for listener implementation:

+ *

General guidelines for {@link ASTInstrumentListener} implementation:

*

- * When an Instrument is attached to a Probe, the listener effectively becomes part of the executing - * GL program; performance can be affected by the listener's implementation. + * Unlike the listener interface {@link InstrumentListener}, which isolates implementations + * completely from Truffle internals (and is thus Truffle-safe), implementations of + * {@link ASTInstrumentListener} can interact directly with (and potentially affect) Truffle + * execution in general and Truffle optimization in particular. For example, it is possible to + * implement a debugger with this interface. + *

+ *

+ * As a consequence, implementations of {@link ASTInstrumentListener} effectively become part of the + * Truffle execution and must be coded according to general guidelines for Truffle implementations. + * For example: *

*

*

Allowing for AST cloning:

*

- * Truffle routinely clones ASTs, which has consequences for listener implementation. + * Truffle routinely clones ASTs, which has consequences for implementations of + * {@link ASTInstrumentListener} (but not for implementations of {@link InstrumentListener}, from + * which cloning is hidden). *

*

- *

Access to execution state:

+ *

Access to execution state via {@link ASTInstrumentListener}:

*

*

*

*

Activating and deactivating Instruments:

@@ -125,8 +149,8 @@ * error to attempt attaching a previously attached instrument. *
  • Attaching an instrument modifies every existing clone of the AST to which it is being * attached, which can trigger deoptimization.
  • - *
  • The method {@link TruffleEventInstrument#dispose()} makes an instrument inactive by removing - * it from the Probe to which it was attached and rendering it permanently inert.
  • + *
  • The method {@link Instrument#dispose()} makes an instrument inactive by removing it from the + * Probe to which it was attached and rendering it permanently inert.
  • *
  • Disposal removes the implementation of an instrument from all ASTs to which it was attached, * which can trigger deoptimization.
  • * @@ -142,26 +166,32 @@ * Disclaimer: experimental; under development. * * @see Probe - * @see TruffleEventListener + * @see TruffleEvents */ public abstract class Instrument { /** * Creates an instrument that will route execution events to a listener. * - * @param listener a listener for event generated by the instrument - * @param instrumentInfo optional description of the instrument's role + * @param listener a minimal listener for event generated by the instrument. + * @param instrumentInfo optional description of the instrument's role, useful for debugging. * @return a new instrument, ready for attachment at a probe */ - public static Instrument create(TruffleEventListener listener, String instrumentInfo) { - return new TruffleEventInstrument(listener, instrumentInfo); + public static Instrument create(InstrumentListener listener, String instrumentInfo) { + return new BasicInstrument(listener, instrumentInfo); } /** - * Creates an instrument that will route execution events to a listener. + * Creates an instrument that will route execution events to a listener, along with access to + * internal execution state. + * + * @param astListener a listener for event generated by the instrument that provides access to + * internal execution state + * @param instrumentInfo optional description of the instrument's role, useful for debugging. + * @return a new instrument, ready for attachment at a probe */ - public static Instrument create(TruffleEventListener listener) { - return new TruffleEventInstrument(listener, null); + public static Instrument create(ASTInstrumentListener astListener, String instrumentInfo) { + return new ASTInstrument(astListener, instrumentInfo); } // TODO (mlvdv) experimental @@ -177,7 +207,7 @@ */ private boolean isDisposed = false; - private Probe probe = null; + protected Probe probe = null; /** * Optional documentation, mainly for debugging. @@ -220,32 +250,30 @@ return isDisposed; } - abstract InstrumentNode addToChain(InstrumentNode nextNode); + abstract AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode); /** - * Removes this instrument from an instrument chain. + * An instrument that propagates events to an instance of {@link InstrumentListener}. */ - abstract InstrumentNode removeFromChain(InstrumentNode instrumentNode); - - private static final class TruffleEventInstrument extends Instrument { + private static final class BasicInstrument extends Instrument { /** * Tool-supplied listener for events. */ - private final TruffleEventListener toolEventListener; + private final InstrumentListener instrumentListener; - private TruffleEventInstrument(TruffleEventListener listener, String instrumentInfo) { + private BasicInstrument(InstrumentListener basicListener, String instrumentInfo) { super(instrumentInfo); - this.toolEventListener = listener; + this.instrumentListener = basicListener; } @Override - InstrumentNode addToChain(InstrumentNode nextNode) { - return new TruffleEventInstrumentNode(nextNode); + AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { + return new BasicInstrumentNode(nextNode); } @Override - InstrumentNode removeFromChain(InstrumentNode instrumentNode) { + AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { boolean found = false; if (instrumentNode != null) { if (instrumentNode.getInstrument() == this) { @@ -253,7 +281,7 @@ return instrumentNode.nextInstrument; } // Match not at the head of the chain; remove it. - found = instrumentNode.removeFromChain(TruffleEventInstrument.this); + found = instrumentNode.removeFromChain(BasicInstrument.this); } if (!found) { throw new IllegalStateException("Couldn't find instrument node to remove: " + this); @@ -262,35 +290,35 @@ } @NodeInfo(cost = NodeCost.NONE) - private final class TruffleEventInstrumentNode extends InstrumentNode { + private final class BasicInstrumentNode extends AbstractInstrumentNode { - private TruffleEventInstrumentNode(InstrumentNode nextNode) { + private BasicInstrumentNode(AbstractInstrumentNode nextNode) { super(nextNode); } public void enter(Node node, VirtualFrame vFrame) { - TruffleEventInstrument.this.toolEventListener.enter(node, vFrame); + BasicInstrument.this.instrumentListener.enter(BasicInstrument.this.probe); if (nextInstrument != null) { nextInstrument.enter(node, vFrame); } } public void returnVoid(Node node, VirtualFrame vFrame) { - TruffleEventInstrument.this.toolEventListener.returnVoid(node, vFrame); + BasicInstrument.this.instrumentListener.returnVoid(BasicInstrument.this.probe); if (nextInstrument != null) { nextInstrument.returnVoid(node, vFrame); } } public void returnValue(Node node, VirtualFrame vFrame, Object result) { - TruffleEventInstrument.this.toolEventListener.returnValue(node, vFrame, result); + BasicInstrument.this.instrumentListener.returnValue(BasicInstrument.this.probe, result); if (nextInstrument != null) { nextInstrument.returnValue(node, vFrame, result); } } public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { - TruffleEventInstrument.this.toolEventListener.returnExceptional(node, vFrame, exception); + BasicInstrument.this.instrumentListener.returnExceptional(BasicInstrument.this.probe, exception); if (nextInstrument != null) { nextInstrument.returnExceptional(node, vFrame, exception); } @@ -298,7 +326,91 @@ public String instrumentationInfo() { final String info = getInstrumentInfo(); - return info != null ? info : toolEventListener.getClass().getSimpleName(); + return info != null ? info : instrumentListener.getClass().getSimpleName(); + } + } + } + + /** + * Removes this instrument from an instrument chain. + */ + abstract AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode); + + /** + * An instrument that propagates events to an instance of {@link ASTInstrumentListener}. + */ + private static final class ASTInstrument extends Instrument { + + /** + * Tool-supplied listener for AST events. + */ + private final ASTInstrumentListener astListener; + + private ASTInstrument(ASTInstrumentListener astListener, String instrumentInfo) { + super(instrumentInfo); + this.astListener = astListener; + } + + @Override + AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { + return new ASTInstrumentNode(nextNode); + } + + @Override + AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { + boolean found = false; + if (instrumentNode != null) { + if (instrumentNode.getInstrument() == this) { + // Found the match at the head of the chain + return instrumentNode.nextInstrument; + } + // Match not at the head of the chain; remove it. + found = instrumentNode.removeFromChain(ASTInstrument.this); + } + if (!found) { + throw new IllegalStateException("Couldn't find instrument node to remove: " + this); + } + return instrumentNode; + } + + @NodeInfo(cost = NodeCost.NONE) + private final class ASTInstrumentNode extends AbstractInstrumentNode { + + private ASTInstrumentNode(AbstractInstrumentNode nextNode) { + super(nextNode); + } + + public void enter(Node node, VirtualFrame vFrame) { + ASTInstrument.this.astListener.enter(ASTInstrument.this.probe, node, vFrame); + if (nextInstrument != null) { + nextInstrument.enter(node, vFrame); + } + } + + public void returnVoid(Node node, VirtualFrame vFrame) { + ASTInstrument.this.astListener.returnVoid(ASTInstrument.this.probe, node, vFrame); + if (nextInstrument != null) { + nextInstrument.returnVoid(node, vFrame); + } + } + + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + ASTInstrument.this.astListener.returnValue(ASTInstrument.this.probe, node, vFrame, result); + if (nextInstrument != null) { + nextInstrument.returnValue(node, vFrame, result); + } + } + + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + ASTInstrument.this.astListener.returnExceptional(ASTInstrument.this.probe, node, vFrame, exception); + if (nextInstrument != null) { + nextInstrument.returnExceptional(node, vFrame, exception); + } + } + + public String instrumentationInfo() { + final String info = getInstrumentInfo(); + return info != null ? info : astListener.getClass().getSimpleName(); } } @@ -318,12 +430,12 @@ } @Override - InstrumentNode addToChain(InstrumentNode nextNode) { + AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { return new TruffleOptInstrumentNode(nextNode); } @Override - InstrumentNode removeFromChain(InstrumentNode instrumentNode) { + AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { boolean found = false; if (instrumentNode != null) { if (instrumentNode.getInstrument() == this) { @@ -340,11 +452,11 @@ } @NodeInfo(cost = NodeCost.NONE) - private final class TruffleOptInstrumentNode extends InstrumentNode { + private final class TruffleOptInstrumentNode extends AbstractInstrumentNode { private boolean isCompiled; - private TruffleOptInstrumentNode(InstrumentNode nextNode) { + private TruffleOptInstrumentNode(AbstractInstrumentNode nextNode) { super(nextNode); this.isCompiled = CompilerDirectives.inCompiledCode(); } @@ -386,10 +498,11 @@ } @NodeInfo(cost = NodeCost.NONE) - abstract class InstrumentNode extends Node implements TruffleEventListener, InstrumentationNode { - @Child protected InstrumentNode nextInstrument; + abstract class AbstractInstrumentNode extends Node implements TruffleEvents, InstrumentationNode { - protected InstrumentNode(InstrumentNode nextNode) { + @Child protected AbstractInstrumentNode nextInstrument; + + protected AbstractInstrumentNode(AbstractInstrumentNode nextNode) { this.nextInstrument = nextNode; } diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentListener.java Fri Mar 13 12:27:07 2015 +0100 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.instrument; + +/** + * A listener of Truffle execution events that can collect information on behalf of an external + * tool. Contextual information about the source of the event, if not stored in the implementation + * of the listener, can be obtained via access to the {@link Probe} that generates the event. + */ +public interface InstrumentListener { + + /** + * Receive notification that an AST node's execute method is about to be called. + */ + void enter(Probe probe); + + /** + * Receive notification that an AST Node's {@code void}-valued execute method has just returned. + */ + void returnVoid(Probe probe); + + /** + * Receive notification that an AST Node's execute method has just returned a value (boxed if + * primitive). + */ + void returnValue(Probe probe, Object result); + + /** + * Receive notification that an AST Node's execute method has just thrown an exception. + */ + void returnExceptional(Probe probe, Exception exception); +} diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationNode.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationNode.java Fri Mar 13 12:27:07 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ */ package com.oracle.truffle.api.instrument; +import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; /** @@ -36,4 +37,31 @@ * A short description of the particular role played by the node, intended to support debugging. */ String instrumentationInfo(); + + /** + * Events at a Truffle node that get propagated through the Instrumentation Framework. + */ + interface TruffleEvents { + + /** + * An AST node's execute method is about to be called. + */ + void enter(Node node, VirtualFrame vFrame); + + /** + * An AST Node's {@code void}-valued execute method has just returned. + */ + void returnVoid(Node node, VirtualFrame vFrame); + + /** + * An AST Node's execute method has just returned a value (boxed if primitive). + */ + void returnValue(Node node, VirtualFrame vFrame, Object result); + + /** + * An AST Node's execute method has just thrown an exception. + */ + void returnExceptional(Node node, VirtualFrame vFrame, Exception exception); + + } } diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Fri Mar 13 12:27:07 2015 +0100 @@ -29,6 +29,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.api.utilities.*; @@ -41,9 +42,9 @@ * is intended to persist at the location, even if the specific node instance is * {@linkplain Node#replace(Node) replaced}. *

    - * The effect of a binding is to intercept {@linkplain TruffleEventListener execution events} - * arriving at the node and notify each attached {@link Instrument} before execution is allowed to - * proceed to the child. + * The effect of a binding is to intercept {@linkplain TruffleEvents execution events} arriving at + * the node and notify each attached {@link Instrument} before execution is allowed to proceed to + * the child. *

    * A Probe is "inserted" into a GL node via a call to {@link Node#probe()}. No more than one Probe * can be inserted at a node. diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Fri Mar 13 12:27:07 2015 +0100 @@ -27,14 +27,15 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.instrument.Instrument.InstrumentNode; +import com.oracle.truffle.api.instrument.Instrument.AbstractInstrumentNode; +import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; /** * Implementation interfaces and classes for attaching {@link Probe}s to {@link WrapperNode}s. */ -public abstract class ProbeNode extends Node implements TruffleEventListener, InstrumentationNode { +public abstract class ProbeNode extends Node implements TruffleEvents, InstrumentationNode { /** * A node that can be inserted into a Truffle AST, and which enables {@linkplain Instrument @@ -84,14 +85,14 @@ /** * Gets the node being "wrapped", i.e. the AST node for which - * {@linkplain TruffleEventListener execution events} will be reported through the - * Instrumentation Framework. + * {@linkplain InstrumentationNode.TruffleEvents execution events} will be reported through + * the Instrumentation Framework. */ Node getChild(); /** * Gets the {@link Probe} responsible for installing this wrapper; none if the wrapper - * installed via {@linkplain Node#probeLite(TruffleEventListener) "lite-Probing"}. + * installed via {@linkplain Node#probeLite(ASTInstrumentListener) "lite-Probing"}. */ Probe getProbe(); @@ -119,8 +120,8 @@ * Creates a new {@link ProbeLiteNode} associated with, and attached to, a Guest Language * specific instance of {@link WrapperNode}. */ - public static void insertProbeLite(WrapperNode wrapper, TruffleEventListener eventListener) { - final ProbeLiteNode probeLiteNode = new ProbeLiteNode(eventListener); + public static void insertProbeLite(WrapperNode wrapper, ASTInstrumentListener instrumentListener) { + final ProbeLiteNode probeLiteNode = new ProbeLiteNode(instrumentListener); wrapper.insertProbe(probeLiteNode); } @@ -137,7 +138,7 @@ public abstract Probe getProbe() throws IllegalStateException; /** - * Adds an {@link InstrumentNode} to this chain. + * Adds an {@link AbstractInstrumentNode} to this chain. * * @throws IllegalStateException if at a "lite-Probed" location. */ @@ -168,9 +169,10 @@ private static final class ProbeFullNode extends ProbeNode { /** - * First {@link InstrumentNode} node in chain; {@code null} of no instruments in chain. + * First {@link AbstractInstrumentNode} node in chain; {@code null} of no instruments in + * chain. */ - @Child protected InstrumentNode firstInstrument; + @Child protected AbstractInstrumentNode firstInstrument; // Never changed once set. @CompilationFinal private Probe probe = null; @@ -208,7 +210,7 @@ @TruffleBoundary void removeInstrument(Instrument instrument) { assert instrument.getProbe() == probe; - final InstrumentNode modifiedChain = instrument.removeFromChain(firstInstrument); + final AbstractInstrumentNode modifiedChain = instrument.removeFromChain(firstInstrument); if (modifiedChain == null) { firstInstrument = null; } else { @@ -256,15 +258,15 @@ /** * Implementation of a probe that only ever has a single "instrument" associated with it. No * {@link Instrument} is ever created; instead this method simply delegates the various enter - * and return events to a {@link TruffleEventListener} passed in during construction. + * and return events to a {@link TruffleEvents} passed in during construction. */ @NodeInfo(cost = NodeCost.NONE) private static final class ProbeLiteNode extends ProbeNode { - private final TruffleEventListener eventListener; + private final ASTInstrumentListener instrumentListener; - private ProbeLiteNode(TruffleEventListener eventListener) { - this.eventListener = eventListener; + private ProbeLiteNode(ASTInstrumentListener eventListener) { + this.instrumentListener = eventListener; } @Override @@ -285,19 +287,19 @@ } public void enter(Node node, VirtualFrame vFrame) { - eventListener.enter(node, vFrame); + instrumentListener.enter(getProbe(), node, vFrame); } public void returnVoid(Node node, VirtualFrame vFrame) { - eventListener.returnVoid(node, vFrame); + instrumentListener.returnVoid(getProbe(), node, vFrame); } public void returnValue(Node node, VirtualFrame vFrame, Object result) { - eventListener.returnValue(node, vFrame, result); + instrumentListener.returnValue(getProbe(), node, vFrame, result); } public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { - eventListener.returnExceptional(node, vFrame, exception); + instrumentListener.returnExceptional(getProbe(), node, vFrame, exception); } public String instrumentationInfo() { diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleEventListener.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleEventListener.java Thu Mar 12 23:49:02 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.instrument; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; - -/** - * A listener of Truffle AST runtime execution events that can collect information and possibly - * intervene on behalf of an external tool. - */ -public interface TruffleEventListener { - - /** - * Receive notification that an AST node's execute method is about to be called. - */ - void enter(Node node, VirtualFrame vFrame); - - /** - * Receive notification that an AST Node's {@code void}-valued execute method has just returned. - */ - void returnVoid(Node node, VirtualFrame vFrame); - - /** - * Receive notification that an AST Node'sexecute method has just returned a value (boxed if - * primitive). - */ - void returnValue(Node node, VirtualFrame vFrame, Object result); - - /** - * Receive notification that an AST Node's execute method has just thrown an exception. - */ - void returnExceptional(Node node, VirtualFrame vFrame, Exception exception); - -} diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTInstrumentListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTInstrumentListener.java Fri Mar 13 12:27:07 2015 +0100 @@ -0,0 +1,49 @@ +/* + * 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.impl; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * A listener for AST {@linkplain ASTInstrumentListener execution events} that provides a no-op + * implementation of every event. + */ +public class DefaultASTInstrumentListener implements ASTInstrumentListener { + + public void enter(Probe probe, Node node, VirtualFrame vFrame) { + } + + public void returnVoid(Probe probe, Node node, VirtualFrame vFrame) { + } + + public void returnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) { + } + + public void returnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) { + } + +} diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultEventListener.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultEventListener.java Thu Mar 12 23:49:02 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.instrument.impl; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; - -/** - * A listener for AST {@linkplain TruffleEventListener execution events} that provides a no-op - * implementation of every event. - */ -public class DefaultEventListener implements TruffleEventListener { - - public void enter(Node node, VirtualFrame vFrame) { - } - - public void returnVoid(Node node, VirtualFrame vFrame) { - } - - public void returnValue(Node node, VirtualFrame vFrame, Object result) { - } - - public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { - } - -} diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultInstrumentListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultInstrumentListener.java Fri Mar 13 12:27:07 2015 +0100 @@ -0,0 +1,45 @@ +/* + * 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.impl; + +import com.oracle.truffle.api.instrument.*; + +/** + * A listener for Truffle execution events that provides a no-op implementation of every event. + */ +public class DefaultInstrumentListener implements InstrumentListener { + + public void enter(Probe probe) { + } + + public void returnVoid(Probe probe) { + } + + public void returnValue(Probe probe, Object result) { + } + + public void returnExceptional(Probe probe, Exception exception) { + } +} diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleASTInstrumentListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleASTInstrumentListener.java Fri Mar 13 12:27:07 2015 +0100 @@ -0,0 +1,67 @@ +/* + * 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.impl; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * An abstract listener for AST {@linkplain ASTInstrumentListener execution events} that ignores + * return values and supports handling all events by overriding only two methods: + *

    + */ +public abstract class SimpleASTInstrumentListener implements ASTInstrumentListener { + + public void enter(Probe probe, Node node, VirtualFrame vFrame) { + } + + /** + * Receive notification that one of an AST Node's execute methods has just returned by any + * means: with or without a return value (ignored) or via exception (ignored). + * + * @param probe where the event originated + * @param node specific node of the event + * @param vFrame + */ + protected void returnAny(Probe probe, Node node, VirtualFrame vFrame) { + } + + public final void returnVoid(Probe probe, Node node, VirtualFrame vFrame) { + returnAny(probe, node, vFrame); + } + + public final void returnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) { + returnAny(probe, node, vFrame); + } + + public final void returnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception e) { + returnAny(probe, node, vFrame); + } + +} diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleEventListener.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleEventListener.java Thu Mar 12 23:49:02 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.instrument.impl; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; - -/** - * An abstract listener for AST {@linkplain TruffleEventListener execution events} that ignores - * return values and supports handling all events by overriding only two methods: - * - */ -public abstract class SimpleEventListener implements TruffleEventListener { - - public void enter(Node node, VirtualFrame vFrame) { - } - - /** - * Receive notification that one of an AST Node's execute methods has just returned by any - * means: with or without a return value (ignored) or via exception (ignored). - * - * @param node - * @param vFrame - */ - public void returnAny(Node node, VirtualFrame vFrame) { - } - - public final void returnVoid(Node node, VirtualFrame vFrame) { - returnAny(node, vFrame); - } - - public final void returnValue(Node node, VirtualFrame vFrame, Object result) { - returnAny(node, vFrame); - } - - public final void returnExceptional(Node node, VirtualFrame vFrame, Exception e) { - returnAny(node, vFrame); - } - -} diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleInstrumentListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleInstrumentListener.java Fri Mar 13 12:27:07 2015 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.instrument.impl; + +import com.oracle.truffle.api.instrument.*; + +/** + * An abstract listener for Truffle {@linkplain InstrumentListener execution events} that ignores + * return values and supports handling all events by overriding only two methods: + * + */ +public abstract class SimpleInstrumentListener implements InstrumentListener { + + public void enter(Probe probe) { + } + + /** + * Receive notification that an execute method has just returned by any means: with or without a + * return value (ignored) or via exception (ignored). + * + * @param probe + */ + protected void returnAny(Probe probe) { + } + + public final void returnVoid(Probe probe) { + returnAny(probe); + } + + public final void returnValue(Probe probe, Object result) { + returnAny(probe); + } + + public final void returnExceptional(Probe probe, Exception e) { + returnAny(probe); + } + +} diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Fri Mar 13 12:27:07 2015 +0100 @@ -504,16 +504,16 @@ * its parent; the wrapper node must be provided by implementations of * {@link #createWrapperNode()}. *

    - * Unlike {@link #probe()}, once {@link #probeLite(TruffleEventListener)} is called at a node, + * Unlike {@link #probe()}, once {@link #probeLite(ASTInstrumentListener)} is called at a node, * no additional probing can be added and no additional instrumentation can be attached. *

    * This restricted form of instrumentation is intended for special cases where only one kind of * instrumentation is desired, and for which performance is a concern * - * @param eventListener + * @param instrumentListener * @throws ProbeException (unchecked) when a probe cannot be created, leaving the AST unchanged */ - public final void probeLite(TruffleEventListener eventListener) { + public final void probeLite(ASTInstrumentListener instrumentListener) { if (this instanceof WrapperNode) { throw new ProbeException(ProbeFailure.Reason.WRAPPER_NODE, null, this, null); @@ -545,7 +545,7 @@ } // Connect it to a Probe - ProbeNode.insertProbeLite(wrapper, eventListener); + ProbeNode.insertProbeLite(wrapper, instrumentListener); // Replace this node in the AST with the wrapper this.replace(wrapperNode); diff -r 5d624638e8a5 -r 79682c7f2ec7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java Thu Mar 12 23:49:02 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java Fri Mar 13 12:27:07 2015 +0100 @@ -28,7 +28,6 @@ import java.util.*; import java.util.Map.Entry; -import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.instrument.impl.*; import com.oracle.truffle.api.nodes.*; @@ -49,7 +48,7 @@ *

    *