comparison graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java @ 19825:907128d02b31

Truffle/Instrumentation: For clients of Instrumentation, replace the TruffleEventListener interface with two: InstrumentListener, and ASTInstrumentListener. The former is simple, completely Truffle-safe (can't affect Truffle execution), and designed for simple tools. The latter is similar to the previous interface.
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Thu, 12 Mar 2015 18:03:05 -0700
parents b5467bb34b24
children 1d6a7ea5de59
comparison
equal deleted inserted replaced
19824:8b7a143aea6b 19825:907128d02b31
81 return "Test Language Value Node"; 81 return "Test Language Value Node";
82 } 82 }
83 }; 83 };
84 84
85 @Test 85 @Test
86 public void testBasicInstrumentation() { 86 public void testInstrumentationStructure() {
87 // Create a simple addition AST 87 // Create a simple addition AST
88 final TruffleRuntime runtime = Truffle.getRuntime(); 88 final TruffleRuntime runtime = Truffle.getRuntime();
89 final TestValueNode leftValueNode = new TestValueNode(6); 89 final TestValueNode leftValueNode = new TestValueNode(6);
90 final TestValueNode rightValueNode = new TestValueNode(7); 90 final TestValueNode rightValueNode = new TestValueNode(7);
91 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode); 91 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
115 115
116 // Ensure it executes correctly 116 // Ensure it executes correctly
117 assertEquals(13, callTarget1.call()); 117 assertEquals(13, callTarget1.call());
118 118
119 // Probe the addition node 119 // Probe the addition node
120 final Probe probe = addNode.probe(); 120 addNode.probe();
121 121
122 // Check the modified tree structure 122 // Check the modified tree structure
123 assertEquals(addNode, leftValueNode.getParent()); 123 assertEquals(addNode, leftValueNode.getParent());
124 assertEquals(addNode, rightValueNode.getParent()); 124 assertEquals(addNode, rightValueNode.getParent());
125 iterator = addNode.getChildren().iterator(); 125 iterator = addNode.getChildren().iterator();
151 } 151 }
152 152
153 // Check that the "probed" AST still executes correctly 153 // Check that the "probed" AST still executes correctly
154 assertEquals(13, callTarget1.call()); 154 assertEquals(13, callTarget1.call());
155 155
156 // Attach a counting instrument to the probe
157 final TestCounter counterA = new TestCounter();
158 counterA.attach(probe);
159
160 // Attach a second counting instrument to the probe
161 final TestCounter counterB = new TestCounter();
162 counterB.attach(probe);
163
164 // Run it again and check that the two instruments are working
165 assertEquals(13, callTarget1.call());
166 assertEquals(counterA.enterCount, 1);
167 assertEquals(counterA.leaveCount, 1);
168 assertEquals(counterB.enterCount, 1);
169 assertEquals(counterB.leaveCount, 1);
170
171 // Remove counterA and check the "instrument chain"
172 counterA.dispose();
173 iterator = probeNode.getChildren().iterator();
174
175 // Run it again and check that instrument B is still working but not A
176 assertEquals(13, callTarget1.call());
177 assertEquals(counterA.enterCount, 1);
178 assertEquals(counterA.leaveCount, 1);
179 assertEquals(counterB.enterCount, 2);
180 assertEquals(counterB.leaveCount, 2);
181
182 // Simulate a split by cloning the AST
183 final CallTarget callTarget2 = runtime.createCallTarget((TestRootNode) rootNode.copy());
184 // Run the clone and check that instrument B is still working but not A
185 assertEquals(13, callTarget2.call());
186 assertEquals(counterA.enterCount, 1);
187 assertEquals(counterA.leaveCount, 1);
188 assertEquals(counterB.enterCount, 3);
189 assertEquals(counterB.leaveCount, 3);
190
191 // Run the original and check that instrument B is still working but not A
192 assertEquals(13, callTarget2.call());
193 assertEquals(counterA.enterCount, 1);
194 assertEquals(counterA.leaveCount, 1);
195 assertEquals(counterB.enterCount, 4);
196 assertEquals(counterB.leaveCount, 4);
197
198 // Attach a second instrument to the probe
199 final TestCounter counterC = new TestCounter();
200 counterC.attach(probe);
201
202 // Run the original and check that instruments B,C working but not A
203 assertEquals(13, callTarget1.call());
204 assertEquals(counterA.enterCount, 1);
205 assertEquals(counterA.leaveCount, 1);
206 assertEquals(counterB.enterCount, 5);
207 assertEquals(counterB.leaveCount, 5);
208 assertEquals(counterC.enterCount, 1);
209 assertEquals(counterC.leaveCount, 1);
210
211 // Run the clone and check that instruments B,C working but not A
212 assertEquals(13, callTarget2.call());
213 assertEquals(counterA.enterCount, 1);
214 assertEquals(counterA.leaveCount, 1);
215 assertEquals(counterB.enterCount, 6);
216 assertEquals(counterB.leaveCount, 6);
217 assertEquals(counterC.enterCount, 2);
218 assertEquals(counterC.leaveCount, 2);
219
220 // Remove instrumentC
221 counterC.dispose();
222
223 // Run the original and check that instrument B working but not A,C
224 assertEquals(13, callTarget1.call());
225 assertEquals(counterA.enterCount, 1);
226 assertEquals(counterA.leaveCount, 1);
227 assertEquals(counterB.enterCount, 7);
228 assertEquals(counterB.leaveCount, 7);
229 assertEquals(counterC.enterCount, 2);
230 assertEquals(counterC.leaveCount, 2);
231
232 // Run the clone and check that instrument B working but not A,C
233 assertEquals(13, callTarget2.call());
234 assertEquals(counterA.enterCount, 1);
235 assertEquals(counterA.leaveCount, 1);
236 assertEquals(counterB.enterCount, 8);
237 assertEquals(counterB.leaveCount, 8);
238 assertEquals(counterC.enterCount, 2);
239 assertEquals(counterC.leaveCount, 2);
240
241 // Remove instrumentB
242 counterB.dispose();
243
244 // Run both the original and clone, check that no instruments working
245 assertEquals(13, callTarget1.call());
246 assertEquals(13, callTarget2.call());
247 assertEquals(counterA.enterCount, 1);
248 assertEquals(counterA.leaveCount, 1);
249 assertEquals(counterB.enterCount, 8);
250 assertEquals(counterB.leaveCount, 8);
251 assertEquals(counterC.enterCount, 2);
252 assertEquals(counterC.leaveCount, 2);
253 } 156 }
254 157
255 @Test 158 @Test
256 public void testTagging() { 159 public void testListeners() {
257
258 // Applies appropriate tags
259 final TestASTProber astProber = new TestASTProber();
260 Probe.registerASTProber(astProber);
261
262 // Listens for probes and tags being added
263 final TestProbeListener probeListener = new TestProbeListener();
264 Probe.addProbeListener(probeListener);
265
266 // Counts all entries to all instances of addition nodes
267 final TestMultiCounter additionCounter = new TestMultiCounter();
268
269 // Counts all entries to all instances of value nodes
270 final TestMultiCounter valueCounter = new TestMultiCounter();
271
272 // Create a simple addition AST
273 final TruffleRuntime runtime = Truffle.getRuntime();
274 final TestValueNode leftValueNode = new TestValueNode(6);
275 final TestValueNode rightValueNode = new TestValueNode(7);
276 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
277
278 final TestRootNode rootNode = new TestRootNode(addNode);
279
280 final CallTarget callTarget = runtime.createCallTarget(rootNode);
281
282 // Check that the prober added probes to the tree
283 assertEquals(probeListener.probeCount, 3);
284 assertEquals(probeListener.tagCount, 3);
285
286 assertEquals(Probe.findProbesTaggedAs(ADD_TAG).size(), 1);
287 assertEquals(Probe.findProbesTaggedAs(VALUE_TAG).size(), 2);
288
289 // Check that it executes correctly
290 assertEquals(13, callTarget.call());
291
292 // Dynamically attach a counter for all executions of all Addition nodes
293 for (Probe probe : Probe.findProbesTaggedAs(ADD_TAG)) {
294 additionCounter.attachCounter(probe);
295 }
296 // Dynamically attach a counter for all executions of all Value nodes
297 for (Probe probe : Probe.findProbesTaggedAs(VALUE_TAG)) {
298 valueCounter.attachCounter(probe);
299 }
300
301 // Counters initialized at 0
302 assertEquals(additionCounter.count, 0);
303 assertEquals(valueCounter.count, 0);
304
305 // Execute again
306 assertEquals(13, callTarget.call());
307
308 // There are two value nodes in the AST, but only one addition node
309 assertEquals(additionCounter.count, 1);
310 assertEquals(valueCounter.count, 2);
311
312 Probe.unregisterASTProber(astProber);
313
314 }
315
316 @Test
317 public void testProbeLite() {
318
319 // Use the "lite-probing" option, limited to a single pass of
320 // probing and a single Instrument at each probed node. This
321 // particular test uses a shared event listener at every
322 // lite-probed node.
323 final TestEventListener listener = new TestEventListener();
324
325 TestASTLiteProber astLiteProber = new TestASTLiteProber(listener);
326 Probe.registerASTProber(astLiteProber);
327 160
328 // Create a simple addition AST 161 // Create a simple addition AST
329 final TruffleRuntime runtime = Truffle.getRuntime(); 162 final TruffleRuntime runtime = Truffle.getRuntime();
330 final TestValueNode leftValueNode = new TestValueNode(6); 163 final TestValueNode leftValueNode = new TestValueNode(6);
331 final TestValueNode rightValueNode = new TestValueNode(7); 164 final TestValueNode rightValueNode = new TestValueNode(7);
333 final TestRootNode rootNode = new TestRootNode(addNode); 166 final TestRootNode rootNode = new TestRootNode(addNode);
334 167
335 // Creating a call target sets the parent pointers in this tree and is necessary prior to 168 // Creating a call target sets the parent pointers in this tree and is necessary prior to
336 // checking any parent/child relationships 169 // checking any parent/child relationships
337 final CallTarget callTarget = runtime.createCallTarget(rootNode); 170 final CallTarget callTarget = runtime.createCallTarget(rootNode);
338 171 // Probe the addition node
339 // Check that the instrument is working as expected. 172 final Probe probe = addNode.probe();
340 assertEquals(0, listener.counter); 173
341 callTarget.call(); 174 // Check instrumentation with the simplest kind of counters.
342 assertEquals(2, listener.counter); 175 // They should all be removed when the check is finished.
343 176 checkCounters(probe, callTarget, rootNode, new TestInstrumentCounter(), new TestInstrumentCounter(), new TestInstrumentCounter());
344 // Check that you can't probe a node that's already received a probeLite() call 177
345 try { 178 // Now try with the more complex flavor of listener
346 leftValueNode.probe(); 179 checkCounters(probe, callTarget, rootNode, new TestASTInstrumentCounter(), new TestASTInstrumentCounter(), new TestASTInstrumentCounter());
347 fail(); 180
348 } catch (IllegalStateException e) { 181 }
349 } 182
350 183 private static void checkCounters(Probe probe, CallTarget callTarget, RootNode rootNode, TestCounter counterA, TestCounter counterB, TestCounter counterC) {
351 try { 184
352 rightValueNode.probe(); 185 // Attach a counting instrument to the probe
353 fail(); 186 counterA.attach(probe);
354 } catch (IllegalStateException e) { 187
355 } 188 // Attach a second counting instrument to the probe
356 189 counterB.attach(probe);
357 // Check tree structure 190
358 assertTrue(leftValueNode.getParent() instanceof TestLanguageWrapperNode); 191 // Run it again and check that the two instruments are working
359 assertTrue(rightValueNode.getParent() instanceof TestLanguageWrapperNode); 192 assertEquals(13, callTarget.call());
360 TestLanguageWrapperNode leftWrapper = (TestLanguageWrapperNode) leftValueNode.getParent(); 193 assertEquals(counterA.enterCount(), 1);
361 TestLanguageWrapperNode rightWrapper = (TestLanguageWrapperNode) rightValueNode.getParent(); 194 assertEquals(counterA.leaveCount(), 1);
362 assertEquals(addNode, leftWrapper.getParent()); 195 assertEquals(counterB.enterCount(), 1);
363 assertEquals(addNode, rightWrapper.getParent()); 196 assertEquals(counterB.leaveCount(), 1);
364 Iterator<Node> iterator = addNode.getChildren().iterator(); 197
365 assertEquals(leftWrapper, iterator.next()); 198 // Remove counterA
366 assertEquals(rightWrapper, iterator.next()); 199 counterA.dispose();
367 assertFalse(iterator.hasNext()); 200
368 assertEquals(rootNode, addNode.getParent()); 201 // Run it again and check that instrument B is still working but not A
369 iterator = rootNode.getChildren().iterator(); 202 assertEquals(13, callTarget.call());
370 assertEquals(addNode, iterator.next()); 203 assertEquals(counterA.enterCount(), 1);
371 assertFalse(iterator.hasNext()); 204 assertEquals(counterA.leaveCount(), 1);
372 205 assertEquals(counterB.enterCount(), 2);
373 // Check that you can't get a probe on the wrappers because they were "lite-probed" 206 assertEquals(counterB.leaveCount(), 2);
374 try { 207
375 leftWrapper.getProbe(); 208 // Simulate a split by cloning the AST
376 fail(); 209 final CallTarget callTarget2 = Truffle.getRuntime().createCallTarget((TestRootNode) rootNode.copy());
377 } catch (IllegalStateException e) { 210 // Run the clone and check that instrument B is still working but not A
378 } 211 assertEquals(13, callTarget2.call());
379 try { 212 assertEquals(counterA.enterCount(), 1);
380 rightWrapper.getProbe(); 213 assertEquals(counterA.leaveCount(), 1);
381 fail(); 214 assertEquals(counterB.enterCount(), 3);
382 } catch (IllegalStateException e) { 215 assertEquals(counterB.leaveCount(), 3);
383 } 216
384 217 // Run the original and check that instrument B is still working but not A
385 // Check that you can't probe the wrappers 218 assertEquals(13, callTarget2.call());
386 try { 219 assertEquals(counterA.enterCount(), 1);
387 leftWrapper.probe(); 220 assertEquals(counterA.leaveCount(), 1);
388 fail(); 221 assertEquals(counterB.enterCount(), 4);
389 } catch (ProbeException e) { 222 assertEquals(counterB.leaveCount(), 4);
390 assertEquals(e.getFailure().getReason(), ProbeFailure.Reason.WRAPPER_NODE); 223
391 } 224 // Attach a second instrument to the probe
392 try { 225 counterC.attach(probe);
393 rightWrapper.probe(); 226
394 fail(); 227 // Run the original and check that instruments B,C working but not A
395 } catch (ProbeException e) { 228 assertEquals(13, callTarget.call());
396 assertEquals(e.getFailure().getReason(), ProbeFailure.Reason.WRAPPER_NODE); 229 assertEquals(counterA.enterCount(), 1);
397 } 230 assertEquals(counterA.leaveCount(), 1);
398 try { 231 assertEquals(counterB.enterCount(), 5);
399 leftWrapper.probeLite(null); 232 assertEquals(counterB.leaveCount(), 5);
400 fail(); 233 assertEquals(counterC.enterCount(), 1);
401 } catch (ProbeException e) { 234 assertEquals(counterC.leaveCount(), 1);
402 assertEquals(e.getFailure().getReason(), ProbeFailure.Reason.WRAPPER_NODE); 235
403 } 236 // Run the clone and check that instruments B,C working but not A
404 try { 237 assertEquals(13, callTarget2.call());
405 rightWrapper.probeLite(null); 238 assertEquals(counterA.enterCount(), 1);
406 fail(); 239 assertEquals(counterA.leaveCount(), 1);
407 } catch (ProbeException e) { 240 assertEquals(counterB.enterCount(), 6);
408 assertEquals(e.getFailure().getReason(), ProbeFailure.Reason.WRAPPER_NODE); 241 assertEquals(counterB.leaveCount(), 6);
409 } 242 assertEquals(counterC.enterCount(), 2);
410 243 assertEquals(counterC.leaveCount(), 2);
411 // Use reflection to check that each WrapperNode has a ProbeLiteNode with a 244
412 // SimpleEventListener 245 // Remove instrumentC
413 try { 246 counterC.dispose();
414 java.lang.reflect.Field probeNodeField = leftWrapper.getClass().getDeclaredField("probeNode"); 247
415 248 // Run the original and check that instrument B working but not A,C
416 // cheat: probeNode is private, so we change it's accessibility at runtime 249 assertEquals(13, callTarget.call());
417 probeNodeField.setAccessible(true); 250 assertEquals(counterA.enterCount(), 1);
418 ProbeNode probeNode = (ProbeNode) probeNodeField.get(leftWrapper); 251 assertEquals(counterA.leaveCount(), 1);
419 252 assertEquals(counterB.enterCount(), 7);
420 // hack: Since ProbeLiteNode is not visible, we do a string compare here 253 assertEquals(counterB.leaveCount(), 7);
421 assertTrue(probeNode.getClass().toString().endsWith("ProbeLiteNode")); 254 assertEquals(counterC.enterCount(), 2);
422 255 assertEquals(counterC.leaveCount(), 2);
423 // Now we do the same to check the type of the eventListener in ProbeLiteNode 256
424 java.lang.reflect.Field eventListenerField = probeNode.getClass().getDeclaredField("eventListener"); 257 // Run the clone and check that instrument B working but not A,C
425 eventListenerField.setAccessible(true); 258 assertEquals(13, callTarget2.call());
426 TruffleEventListener eventListener = (TruffleEventListener) eventListenerField.get(probeNode); 259 assertEquals(counterA.enterCount(), 1);
427 assertTrue(eventListener instanceof SimpleEventListener); 260 assertEquals(counterA.leaveCount(), 1);
428 261 assertEquals(counterB.enterCount(), 8);
429 // Reset accessibility 262 assertEquals(counterB.leaveCount(), 8);
430 probeNodeField.setAccessible(false); 263 assertEquals(counterC.enterCount(), 2);
431 eventListenerField.setAccessible(false); 264 assertEquals(counterC.leaveCount(), 2);
432 265
433 } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { 266 // Remove instrumentB
434 fail(); 267 counterB.dispose();
435 } 268
436 269 // Run both the original and clone, check that no instruments working
437 Probe.unregisterASTProber(astLiteProber); 270 assertEquals(13, callTarget.call());
271 assertEquals(13, callTarget2.call());
272 assertEquals(counterA.enterCount(), 1);
273 assertEquals(counterA.leaveCount(), 1);
274 assertEquals(counterB.enterCount(), 8);
275 assertEquals(counterB.leaveCount(), 8);
276 assertEquals(counterC.enterCount(), 2);
277 assertEquals(counterC.leaveCount(), 2);
278
279 }
280
281 @Test
282 public void testTagging() {
283
284 // Applies appropriate tags
285 final TestASTProber astProber = new TestASTProber();
286 Probe.registerASTProber(astProber);
287
288 // Listens for probes and tags being added
289 final TestProbeListener probeListener = new TestProbeListener();
290 Probe.addProbeListener(probeListener);
291
292 // Counts all entries to all instances of addition nodes
293 final TestMultiCounter additionCounter = new TestMultiCounter();
294
295 // Counts all entries to all instances of value nodes
296 final TestMultiCounter valueCounter = new TestMultiCounter();
297
298 // Create a simple addition AST
299 final TruffleRuntime runtime = Truffle.getRuntime();
300 final TestValueNode leftValueNode = new TestValueNode(6);
301 final TestValueNode rightValueNode = new TestValueNode(7);
302 final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
303
304 final TestRootNode rootNode = new TestRootNode(addNode);
305
306 final CallTarget callTarget = runtime.createCallTarget(rootNode);
307
308 // Check that the prober added probes to the tree
309 assertEquals(probeListener.probeCount, 3);
310 assertEquals(probeListener.tagCount, 3);
311
312 assertEquals(Probe.findProbesTaggedAs(ADD_TAG).size(), 1);
313 assertEquals(Probe.findProbesTaggedAs(VALUE_TAG).size(), 2);
314
315 // Check that it executes correctly
316 assertEquals(13, callTarget.call());
317
318 // Dynamically attach a counter for all executions of all Addition nodes
319 for (Probe probe : Probe.findProbesTaggedAs(ADD_TAG)) {
320 additionCounter.attachCounter(probe);
321 }
322 // Dynamically attach a counter for all executions of all Value nodes
323 for (Probe probe : Probe.findProbesTaggedAs(VALUE_TAG)) {
324 valueCounter.attachCounter(probe);
325 }
326
327 // Counters initialized at 0
328 assertEquals(additionCounter.count, 0);
329 assertEquals(valueCounter.count, 0);
330
331 // Execute again
332 assertEquals(13, callTarget.call());
333
334 // There are two value nodes in the AST, but only one addition node
335 assertEquals(additionCounter.count, 1);
336 assertEquals(valueCounter.count, 2);
337
338 Probe.unregisterASTProber(astProber);
438 339
439 } 340 }
440 341
441 private abstract class TestLanguageNode extends Node { 342 private abstract class TestLanguageNode extends Node {
442 public abstract Object execute(VirtualFrame vFrame); 343 public abstract Object execute(VirtualFrame vFrame);
576 public void applyInstrumentation() { 477 public void applyInstrumentation() {
577 Probe.applyASTProbers(body); 478 Probe.applyASTProbers(body);
578 } 479 }
579 } 480 }
580 481
581 /** 482 private interface TestCounter {
582 * A counter for the number of times execution enters and leaves a probed AST node. 483
583 */ 484 int enterCount();
584 private class TestCounter { 485
486 int leaveCount();
487
488 void attach(Probe probe);
489
490 void dispose();
491
492 }
493
494 /**
495 * A counter for the number of times execution enters and leaves a probed AST node, using the
496 * simplest kind of listener.
497 */
498 private class TestInstrumentCounter implements TestCounter {
585 499
586 public int enterCount = 0; 500 public int enterCount = 0;
587 public int leaveCount = 0; 501 public int leaveCount = 0;
588 public final Instrument instrument; 502 public final Instrument instrument;
589 503
590 public TestCounter() { 504 public TestInstrumentCounter() {
591 instrument = Instrument.create(new SimpleEventListener() { 505 this.instrument = Instrument.create(new SimpleInstrumentListener() {
592 506
593 @Override 507 @Override
594 public void enter(Node node, VirtualFrame vFrame) { 508 public void enter(Probe probe) {
595 enterCount++; 509 enterCount++;
596 } 510 }
597 511
598 @Override 512 @Override
599 public void returnAny(Node node, VirtualFrame vFrame) { 513 public void returnAny(Probe probe) {
600 leaveCount++; 514 leaveCount++;
601 } 515 }
516
602 }, "Instrumentation Test Counter"); 517 }, "Instrumentation Test Counter");
518
519 }
520
521 public int enterCount() {
522 return enterCount;
523 }
524
525 public int leaveCount() {
526 return leaveCount;
603 } 527 }
604 528
605 public void attach(Probe probe) { 529 public void attach(Probe probe) {
606 probe.attach(instrument); 530 probe.attach(instrument);
607 } 531 }
608 532
609 public void dispose() { 533 public void dispose() {
610 instrument.dispose(); 534 instrument.dispose();
611 } 535 }
612 536 }
537
538 /**
539 * A counter for the number of times execution enters and leaves a probed AST node, using the
540 * simplest kind of listener.
541 */
542 private class TestASTInstrumentCounter implements TestCounter {
543
544 public int enterCount = 0;
545 public int leaveCount = 0;
546 public final Instrument instrument;
547
548 public TestASTInstrumentCounter() {
549 this.instrument = Instrument.create(new SimpleASTInstrumentListener() {
550
551 @Override
552 public void enter(Probe probe, Node node, VirtualFrame vFrame) {
553 enterCount++;
554 }
555
556 @Override
557 public void returnAny(Probe probe, Node node, VirtualFrame vFrame) {
558 leaveCount++;
559 }
560
561 }, "Instrumentation Test Counter");
562
563 }
564
565 public int enterCount() {
566 return enterCount;
567 }
568
569 public int leaveCount() {
570 return leaveCount;
571 }
572
573 public void attach(Probe probe) {
574 probe.attach(instrument);
575 }
576
577 public void dispose() {
578 instrument.dispose();
579 }
613 } 580 }
614 581
615 /** 582 /**
616 * Tags selected nodes on newly constructed ASTs. 583 * Tags selected nodes on newly constructed ASTs.
617 */ 584 */
639 node.accept(this); 606 node.accept(this);
640 } 607 }
641 } 608 }
642 609
643 /** 610 /**
644 * "lite-probes" every value node with a shared event listener. 611 * Counts the number of "enter" events at probed nodes using the simplest AST listener.
645 */ 612 */
646 private static final class TestASTLiteProber implements NodeVisitor, ASTProber { 613 static final class TestInstrumentListener extends DefaultInstrumentListener {
647 private final TruffleEventListener eventListener;
648
649 public TestASTLiteProber(SimpleEventListener simpleEventListener) {
650 this.eventListener = simpleEventListener;
651 }
652
653 public boolean visit(Node node) {
654 if (node instanceof TestValueNode) {
655 final TestLanguageNode testNode = (TestValueNode) node;
656 testNode.probeLite(eventListener);
657 }
658 return true;
659 }
660
661 public void probeAST(Node node) {
662 node.accept(this);
663 }
664 }
665
666 /**
667 * Counts the number of "enter" events at probed nodes.
668 *
669 */
670 static final class TestEventListener extends SimpleEventListener {
671 614
672 public int counter = 0; 615 public int counter = 0;
673 616
674 @Override 617 @Override
675 public void enter(Node node, VirtualFrame frame) { 618 public void enter(Probe probe) {
619 counter++;
620 }
621
622 }
623
624 /**
625 * Counts the number of "enter" events at probed nodes using the AST listener.
626 */
627 static final class TestASTInstrumentListener extends DefaultASTInstrumentListener {
628
629 public int counter = 0;
630
631 @Override
632 public void enter(Probe probe, Node node, VirtualFrame vFrame) {
676 counter++; 633 counter++;
677 } 634 }
678 635
679 } 636 }
680 637
690 647
691 // Attach a new instrument for every Probe 648 // Attach a new instrument for every Probe
692 // where we want to count executions. 649 // where we want to count executions.
693 // it will get copied when ASTs cloned, so 650 // it will get copied when ASTs cloned, so
694 // keep the count in this outer class. 651 // keep the count in this outer class.
695 probe.attach(Instrument.create(new SimpleEventListener() { 652 probe.attach(Instrument.create(new DefaultInstrumentListener() {
696 653
697 @Override 654 @Override
698 public void enter(Node node, VirtualFrame vFrame) { 655 public void enter(Probe p) {
699 count++; 656 count++;
700 } 657 }
701 }, "Instrumentation Test MultiCounter")); 658 }, "Instrumentation Test MultiCounter"));
702 } 659 }
703 } 660 }