comparison truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java @ 22219:1c0f490984d5

Merge with f47b601edbc626dcfe8b3636933b4834c89f7779
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Wed, 16 Sep 2015 15:36:22 -0700
parents dc83cc1f94f2 3aad794eec0e
children 20380d1d41f2
comparison
equal deleted inserted replaced
22160:0599e2df6a9f 22219:1c0f490984d5
26 import com.oracle.truffle.api.Truffle; 26 import com.oracle.truffle.api.Truffle;
27 import com.oracle.truffle.api.TruffleRuntime; 27 import com.oracle.truffle.api.TruffleRuntime;
28 import com.oracle.truffle.api.frame.VirtualFrame; 28 import com.oracle.truffle.api.frame.VirtualFrame;
29 import com.oracle.truffle.api.instrument.ASTProber; 29 import com.oracle.truffle.api.instrument.ASTProber;
30 import com.oracle.truffle.api.instrument.Instrument; 30 import com.oracle.truffle.api.instrument.Instrument;
31 import com.oracle.truffle.api.instrument.Instrumenter;
31 import com.oracle.truffle.api.instrument.Probe; 32 import com.oracle.truffle.api.instrument.Probe;
32 import com.oracle.truffle.api.instrument.ProbeException; 33 import com.oracle.truffle.api.instrument.ProbeException;
33 import com.oracle.truffle.api.instrument.ProbeFailure.Reason; 34 import com.oracle.truffle.api.instrument.ProbeFailure.Reason;
34 import com.oracle.truffle.api.instrument.ProbeNode; 35 import com.oracle.truffle.api.instrument.ProbeNode;
35 import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode; 36 import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
45 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestAdditionNode; 46 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestAdditionNode;
46 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestLanguageNode; 47 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestLanguageNode;
47 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestLanguageWrapperNode; 48 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestLanguageWrapperNode;
48 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestRootNode; 49 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestRootNode;
49 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestValueNode; 50 import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestValueNode;
51
50 import java.util.Iterator; 52 import java.util.Iterator;
53
51 import static org.junit.Assert.assertEquals; 54 import static org.junit.Assert.assertEquals;
52 import static org.junit.Assert.assertFalse; 55 import static org.junit.Assert.assertFalse;
53 import static org.junit.Assert.assertTrue; 56 import static org.junit.Assert.assertTrue;
54 import static org.junit.Assert.fail; 57 import static org.junit.Assert.fail;
58
55 import org.junit.Test; 59 import org.junit.Test;
56 60
57 /** 61 /**
58 * <h3>AST Instrumentation</h3> 62 * <h3>AST Instrumentation</h3>
59 * 63 *
99 return "Test Language Value Node"; 103 return "Test Language Value Node";
100 } 104 }
101 }; 105 };
102 106
103 @Test 107 @Test
104 public void testInstrumentationStructure() { 108 public void testInstrumentationStructure() throws IllegalAccessException, SecurityException, IllegalArgumentException, NoSuchFieldException {
109
110 final Instrumenter instrumenter = InstrumentationTestNodes.createInstrumenter();
105 // Create a simple addition AST 111 // Create a simple addition AST
106 final TruffleRuntime runtime = Truffle.getRuntime(); 112 final TruffleRuntime runtime = Truffle.getRuntime();
107 final TestValueNode leftValueNode = new TestValueNode(6); 113 final TestValueNode leftValueNode = new TestValueNode(6);
108 final TestValueNode rightValueNode = new TestValueNode(7); 114 final TestValueNode rightValueNode = new TestValueNode(7);
109 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode); 115 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
110 116
111 try { 117 try {
112 addNode.probe(); 118 instrumenter.probe(addNode);
113 } catch (ProbeException e) { 119 } catch (ProbeException e) {
114 assertEquals(e.getFailure().getReason(), Reason.NO_PARENT); 120 assertEquals(e.getFailure().getReason(), Reason.NO_PARENT);
115 } 121 }
116 final TestRootNode rootNode = new TestRootNode(addNode); 122 final TestRootNode rootNode = new TestRootNode(addNode, instrumenter);
117 123
118 // Creating a call target sets the parent pointers in this tree and is necessary prior to 124 // Creating a call target sets the parent pointers in this tree and is necessary prior to
119 // checking any parent/child relationships 125 // checking any parent/child relationships
120 final CallTarget callTarget1 = runtime.createCallTarget(rootNode); 126 final CallTarget callTarget1 = runtime.createCallTarget(rootNode);
121 127
133 139
134 // Ensure it executes correctly 140 // Ensure it executes correctly
135 assertEquals(13, callTarget1.call()); 141 assertEquals(13, callTarget1.call());
136 142
137 // Probe the addition node 143 // Probe the addition node
138 addNode.probe(); 144 instrumenter.probe(addNode);
139 145
140 // Check the modified tree structure 146 // Check the modified tree structure
141 assertEquals(addNode, leftValueNode.getParent()); 147 assertEquals(addNode, leftValueNode.getParent());
142 assertEquals(addNode, rightValueNode.getParent()); 148 assertEquals(addNode, rightValueNode.getParent());
143 iterator = addNode.getChildren().iterator(); 149 iterator = addNode.getChildren().iterator();
160 assertFalse(iterator.hasNext()); 166 assertFalse(iterator.hasNext());
161 167
162 // Check that you can't probe the WrapperNodes 168 // Check that you can't probe the WrapperNodes
163 TestLanguageWrapperNode wrapper = (TestLanguageWrapperNode) wrapperNode; 169 TestLanguageWrapperNode wrapper = (TestLanguageWrapperNode) wrapperNode;
164 try { 170 try {
165 wrapper.probe(); 171 instrumenter.probe(wrapper);
166 fail(); 172 fail();
167 } catch (ProbeException e) { 173 } catch (ProbeException e) {
168 assertEquals(e.getFailure().getReason(), Reason.WRAPPER_NODE); 174 assertEquals(e.getFailure().getReason(), Reason.WRAPPER_NODE);
169 } 175 }
170 176
171 // Check that the "probed" AST still executes correctly 177 // Check that the "probed" AST still executes correctly
172 assertEquals(13, callTarget1.call()); 178 assertEquals(13, callTarget1.call());
173 } 179 }
174 180
175 @Test 181 @Test
176 public void testListeners() { 182 public void testListeners() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
183
184 final Instrumenter instrumenter = InstrumentationTestNodes.createInstrumenter();
177 185
178 // Create a simple addition AST 186 // Create a simple addition AST
179 final TruffleRuntime runtime = Truffle.getRuntime(); 187 final TruffleRuntime runtime = Truffle.getRuntime();
180 final TestValueNode leftValueNode = new TestValueNode(6); 188 final TestValueNode leftValueNode = new TestValueNode(6);
181 final TestValueNode rightValueNode = new TestValueNode(7); 189 final TestValueNode rightValueNode = new TestValueNode(7);
182 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode); 190 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
183 final TestRootNode rootNode = new TestRootNode(addNode); 191 final TestRootNode rootNode = new TestRootNode(addNode, instrumenter);
184 192
185 // Creating a call target sets the parent pointers in this tree and is necessary prior to 193 // Creating a call target sets the parent pointers in this tree and is necessary prior to
186 // checking any parent/child relationships 194 // checking any parent/child relationships
187 final CallTarget callTarget = runtime.createCallTarget(rootNode); 195 final CallTarget callTarget = runtime.createCallTarget(rootNode);
188 // Probe the addition node 196 // Probe the addition node
189 final Probe probe = addNode.probe(); 197 final Probe probe = instrumenter.probe(addNode);
190 198
191 // Check instrumentation with the simplest kind of counters. 199 // Check instrumentation with the simplest kind of counters.
192 // They should all be removed when the check is finished. 200 // They should all be removed when the check is finished.
193 checkCounters(probe, callTarget, rootNode, new TestSimpleInstrumentCounter(), new TestSimpleInstrumentCounter(), new TestSimpleInstrumentCounter()); 201 checkCounters(probe, callTarget, rootNode, new TestSimpleInstrumentCounter(), new TestSimpleInstrumentCounter(), new TestSimpleInstrumentCounter());
194 202
292 assertEquals(counterC.enterCount(), 2); 300 assertEquals(counterC.enterCount(), 2);
293 assertEquals(counterC.leaveCount(), 2); 301 assertEquals(counterC.leaveCount(), 2);
294 } 302 }
295 303
296 @Test 304 @Test
297 public void testTagging() { 305 public void testTagging() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
306 final Instrumenter instrumenter = InstrumentationTestNodes.createInstrumenter();
307
298 // Applies appropriate tags 308 // Applies appropriate tags
299 final TestASTProber astProber = new TestASTProber(); 309 final TestASTProber astProber = new TestASTProber(instrumenter);
300 Probe.registerASTProber(astProber); 310 instrumenter.registerASTProber(astProber);
301 311
302 // Listens for probes and tags being added 312 // Listens for probes and tags being added
303 final TestProbeListener probeListener = new TestProbeListener(); 313 final TestProbeListener probeListener = new TestProbeListener();
304 Probe.addProbeListener(probeListener); 314 instrumenter.addProbeListener(probeListener);
305 315
306 // Counts all entries to all instances of addition nodes 316 // Counts all entries to all instances of addition nodes
307 final TestMultiCounter additionCounter = new TestMultiCounter(); 317 final TestMultiCounter additionCounter = new TestMultiCounter();
308 318
309 // Counts all entries to all instances of value nodes 319 // Counts all entries to all instances of value nodes
313 final TruffleRuntime runtime = Truffle.getRuntime(); 323 final TruffleRuntime runtime = Truffle.getRuntime();
314 final TestValueNode leftValueNode = new TestValueNode(6); 324 final TestValueNode leftValueNode = new TestValueNode(6);
315 final TestValueNode rightValueNode = new TestValueNode(7); 325 final TestValueNode rightValueNode = new TestValueNode(7);
316 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode); 326 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
317 327
318 final TestRootNode rootNode = new TestRootNode(addNode); 328 final TestRootNode rootNode = new TestRootNode(addNode, instrumenter);
319 329
320 final CallTarget callTarget = runtime.createCallTarget(rootNode); 330 final CallTarget callTarget = runtime.createCallTarget(rootNode);
321 331
322 // Check that the prober added probes to the tree 332 // Check that the prober added probes to the tree
323 assertEquals(probeListener.probeCount, 3); 333 assertEquals(probeListener.probeCount, 3);
324 assertEquals(probeListener.tagCount, 3); 334 assertEquals(probeListener.tagCount, 3);
325 335
326 assertEquals(Probe.findProbesTaggedAs(ADD_TAG).size(), 1); 336 assertEquals(instrumenter.findProbesTaggedAs(ADD_TAG).size(), 1);
327 assertEquals(Probe.findProbesTaggedAs(VALUE_TAG).size(), 2); 337 assertEquals(instrumenter.findProbesTaggedAs(VALUE_TAG).size(), 2);
328 338
329 // Check that it executes correctly 339 // Check that it executes correctly
330 assertEquals(13, callTarget.call()); 340 assertEquals(13, callTarget.call());
331 341
332 // Dynamically attach a counter for all executions of all Addition nodes 342 // Dynamically attach a counter for all executions of all Addition nodes
333 for (Probe probe : Probe.findProbesTaggedAs(ADD_TAG)) { 343 for (Probe probe : instrumenter.findProbesTaggedAs(ADD_TAG)) {
334 additionCounter.attachCounter(probe); 344 additionCounter.attachCounter(probe);
335 } 345 }
336 // Dynamically attach a counter for all executions of all Value nodes 346 // Dynamically attach a counter for all executions of all Value nodes
337 for (Probe probe : Probe.findProbesTaggedAs(VALUE_TAG)) { 347 for (Probe probe : instrumenter.findProbesTaggedAs(VALUE_TAG)) {
338 valueCounter.attachCounter(probe); 348 valueCounter.attachCounter(probe);
339 } 349 }
340 350
341 // Counters initialized at 0 351 // Counters initialized at 0
342 assertEquals(additionCounter.count, 0); 352 assertEquals(additionCounter.count, 0);
347 357
348 // There are two value nodes in the AST, but only one addition node 358 // There are two value nodes in the AST, but only one addition node
349 assertEquals(additionCounter.count, 1); 359 assertEquals(additionCounter.count, 1);
350 assertEquals(valueCounter.count, 2); 360 assertEquals(valueCounter.count, 2);
351 361
352 Probe.unregisterASTProber(astProber); 362 instrumenter.unregisterASTProber(astProber);
353 } 363 }
354 364
355 private interface TestCounter { 365 private interface TestCounter {
356 366
357 int enterCount(); 367 int enterCount();
470 /** 480 /**
471 * Tags selected nodes on newly constructed ASTs. 481 * Tags selected nodes on newly constructed ASTs.
472 */ 482 */
473 private static final class TestASTProber implements NodeVisitor, ASTProber { 483 private static final class TestASTProber implements NodeVisitor, ASTProber {
474 484
485 private final Instrumenter instrumenter;
486
487 TestASTProber(Instrumenter instrumenter) {
488 this.instrumenter = instrumenter;
489 }
490
475 @Override 491 @Override
476 public boolean visit(Node node) { 492 public boolean visit(Node node) {
477 if (node instanceof TestLanguageNode) { 493 if (node instanceof TestLanguageNode) {
478 494
479 final TestLanguageNode testNode = (TestLanguageNode) node; 495 final TestLanguageNode testNode = (TestLanguageNode) node;
480 496
481 if (node instanceof TestValueNode) { 497 if (node instanceof TestValueNode) {
482 testNode.probe().tagAs(VALUE_TAG, null); 498 instrumenter.probe(testNode).tagAs(VALUE_TAG, null);
483 499
484 } else if (node instanceof TestAdditionNode) { 500 } else if (node instanceof TestAdditionNode) {
485 testNode.probe().tagAs(ADD_TAG, null); 501 instrumenter.probe(testNode).tagAs(ADD_TAG, null);
486 502
487 } 503 }
488 } 504 }
489 return true; 505 return true;
490 } 506 }
491 507
492 @Override 508 @Override
493 public void probeAST(Node node) { 509 public void probeAST(Instrumenter inst, Node node) {
494 node.accept(this); 510 node.accept(this);
495 } 511 }
496 } 512 }
497 513
498 /** 514 /**