Mercurial > hg > truffle
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 /** |