Mercurial > hg > graal-compiler
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 } |