comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java @ 20893:263ab98b3bf0

Truffle/Instrumentation: rename ASTInstrumentListener to StandardInstrumentListener
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Fri, 10 Apr 2015 21:14:14 -0700
parents 73b1844b5b14
children 129a09815063
comparison
equal deleted inserted replaced
20892:73b1844b5b14 20893:263ab98b3bf0
39 * A dynamically added/removed binding between a {@link Probe}, which provides notification of 39 * A dynamically added/removed binding between a {@link Probe}, which provides notification of
40 * <em>execution events</em> taking place at a {@link Node} in a Guest Language (GL) Truffle AST, 40 * <em>execution events</em> taking place at a {@link Node} in a Guest Language (GL) Truffle AST,
41 * and a <em>listener</em>, which consumes notifications on behalf of an external tool. There are at 41 * and a <em>listener</em>, which consumes notifications on behalf of an external tool. There are at
42 * present two kinds of listeners that be used: 42 * present two kinds of listeners that be used:
43 * <ol> 43 * <ol>
44 * <li>{@link SimpleInstrumentListener} is the simplest and is intended for tools that require no access 44 * <li>{@link SimpleInstrumentListener} is the simplest and is intended for tools that require no
45 * to the <em>internal execution state</em> of the Truffle execution, only that execution has passed 45 * access to the <em>internal execution state</em> of the Truffle execution, only that execution has
46 * through a particular location in the program. Information about that location is made available 46 * passed through a particular location in the program. Information about that location is made
47 * via the {@link Probe} argument in notification methods, including the {@linkplain SourceSection 47 * available via the {@link Probe} argument in notification methods, including the
48 * source location} of the node and any {@linkplain SyntaxTag tags} that have been applied to the 48 * {@linkplain SourceSection source location} of the node and any {@linkplain SyntaxTag tags} that
49 * node.</li> 49 * have been applied to the node.</li>
50 * <li>{@link ASTInstrumentListener} reports the same events and {@link Probe} argument, but 50 * <li>{@link StandardInstrumentListener} reports the same events and {@link Probe} argument, but
51 * additionally provides access to the execution state via the explicit {@link Node} and 51 * additionally provides access to the execution state via the explicit {@link Node} and
52 * {@link Frame} at the current execution site.</li> 52 * {@link Frame} at the current execution site.</li>
53 * </ol> 53 * </ol>
54 * <p> 54 * <p>
55 * <h4>Summary: How to "instrument" an AST location:</h4> 55 * <h4>Summary: How to "instrument" an AST location:</h4>
56 * <p> 56 * <p>
57 * <ol> 57 * <ol>
58 * <li>Create an implementation of a <em>listener</em> interface.</li> 58 * <li>Create an implementation of a <em>listener</em> interface.</li>
59 * <li>Create an Instrument via factory methods 59 * <li>Create an Instrument via factory methods
60 * {@link Instrument#create(SimpleInstrumentListener, String)} or 60 * {@link Instrument#create(SimpleInstrumentListener, String)} or
61 * {@link Instrument#create(ASTInstrumentListener, String)}.</li> 61 * {@link Instrument#create(StandardInstrumentListener, String)}.</li>
62 * <li>"Attach" the Instrument to a Probe via {@link Probe#attach(Instrument)}, at which point event 62 * <li>"Attach" the Instrument to a Probe via {@link Probe#attach(Instrument)}, at which point event
63 * notifications begin to arrive at the listener.</li> 63 * notifications begin to arrive at the listener.</li>
64 * <li>When no longer needed, "detach" the Instrument via {@link ASTInstrument#dispose()}, at which 64 * <li>When no longer needed, "detach" the Instrument via {@link StandardInstrument#dispose()}, at
65 * point event notifications to the listener cease, and the Instrument becomes unusable.</li> 65 * which point event notifications to the listener cease, and the Instrument becomes unusable.</li>
66 * </ol> 66 * </ol>
67 * <p> 67 * <p>
68 * <h4>Options for creating listeners:</h4> 68 * <h4>Options for creating listeners:</h4>
69 * <p> 69 * <p>
70 * <ol> 70 * <ol>
71 * <li>Implement one of the <em>listener interfaces</em>: {@link SimpleInstrumentListener} or 71 * <li>Implement one of the <em>listener interfaces</em>: {@link SimpleInstrumentListener} or
72 * {@link ASTInstrumentListener} . Their event handling methods account for both the entry into an 72 * {@link StandardInstrumentListener} . Their event handling methods account for both the entry into an
73 * AST node (about to call) and three possible kinds of <em>execution return</em> from an AST node.</li> 73 * AST node (about to call) and three possible kinds of <em>execution return</em> from an AST node.</li>
74 * <li>Extend one of the <em>helper implementations</em>: {@link DefaultSimpleInstrumentListener} or 74 * <li>Extend one of the <em>helper implementations</em>: {@link DefaultSimpleInstrumentListener} or
75 * {@link DefaultASTInstrumentListener}. These provide no-op implementation of every listener 75 * {@link DefaultStandardInstrumentListener}. These provide no-op implementation of every listener
76 * method, so only the methods of interest need to be overridden.</li> 76 * method, so only the methods of interest need to be overridden.</li>
77 * </ol> 77 * </ol>
78 * <p> 78 * <p>
79 * <h4>General guidelines for {@link ASTInstrumentListener} implementation:</h4> 79 * <h4>General guidelines for {@link StandardInstrumentListener} implementation:</h4>
80 * <p> 80 * <p>
81 * Unlike the listener interface {@link SimpleInstrumentListener}, which isolates implementations 81 * Unlike the listener interface {@link SimpleInstrumentListener}, which isolates implementations
82 * completely from Truffle internals (and is thus <em>Truffle-safe</em>), implementations of 82 * from Truffle internals (and is thus <em>Truffle-safe</em>), implementations of
83 * {@link ASTInstrumentListener} can interact directly with (and potentially affect) Truffle 83 * {@link StandardInstrumentListener} can interact directly with (and potentially affect) Truffle
84 * execution in general and Truffle optimization in particular. For example, it is possible to 84 * execution in general and Truffle optimization in particular. For example, it is possible to
85 * implement a debugger with this interface. 85 * implement a debugger with this interface.
86 * </p> 86 * </p>
87 * <p> 87 * <p>
88 * As a consequence, implementations of {@link ASTInstrumentListener} effectively become part of the 88 * As a consequence, implementations of {@link StandardInstrumentListener} effectively become part of
89 * Truffle execution and must be coded according to general guidelines for Truffle implementations. 89 * the Truffle execution and must be coded according to general guidelines for Truffle
90 * For example: 90 * implementations. For example:
91 * <ul> 91 * <ul>
92 * <li>Do not store {@link Frame} or {@link Node} references in fields.</li> 92 * <li>Do not store {@link Frame} or {@link Node} references in fields.</li>
93 * <li>Prefer {@code final} fields and (where performance is important) short methods.</li> 93 * <li>Prefer {@code final} fields and (where performance is important) short methods.</li>
94 * <li>If needed, pass along the {@link VirtualFrame} reference from an event notification as far as 94 * <li>If needed, pass along the {@link VirtualFrame} reference from an event notification as far as
95 * possible through code that is expected to be inlined, since this incurs no runtime overhead. When 95 * possible through code that is expected to be inlined, since this incurs no runtime overhead. When
108 * </ul> 108 * </ul>
109 * <p> 109 * <p>
110 * <h4>Allowing for AST cloning:</h4> 110 * <h4>Allowing for AST cloning:</h4>
111 * <p> 111 * <p>
112 * Truffle routinely <em>clones</em> ASTs, which has consequences for implementations of 112 * Truffle routinely <em>clones</em> ASTs, which has consequences for implementations of
113 * {@link ASTInstrumentListener} (but not for implementations of {@link SimpleInstrumentListener}, from 113 * {@link StandardInstrumentListener} (but not for implementations of {@link SimpleInstrumentListener},
114 * which cloning is hidden). 114 * from which cloning is hidden).
115 * <ul> 115 * <ul>
116 * <li>Even though a {@link Probe} is uniquely associated with a particular location in the 116 * <li>Even though a {@link Probe} is uniquely associated with a particular location in the
117 * executing Guest Language program, execution events at that location will in general be 117 * executing Guest Language program, execution events at that location will in general be
118 * implemented by different {@link Node} instances, i.e. <em>clones</em> of the originally probed 118 * implemented by different {@link Node} instances, i.e. <em>clones</em> of the originally probed
119 * node.</li> 119 * node.</li>
120 * <li>Because of <em>cloning</em> the {@link Node} supplied with notifications to a particular 120 * <li>Because of <em>cloning</em> the {@link Node} supplied with notifications to a particular
121 * listener will vary, but because they all represent the same GL program location the events should 121 * listener will vary, but because they all represent the same GL program location the events should
122 * be treated as equivalent for most purposes.</li> 122 * be treated as equivalent for most purposes.</li>
123 * </ul> 123 * </ul>
124 * <p> 124 * <p>
125 * <h4>Access to execution state via {@link ASTInstrumentListener}:</h4> 125 * <h4>Access to execution state via {@link StandardInstrumentListener}:</h4>
126 * <p> 126 * <p>
127 * <ul> 127 * <ul>
128 * <li>Notification arguments provide primary access to the GL program's execution states: 128 * <li>Notification arguments provide primary access to the GL program's execution states:
129 * <ul> 129 * <ul>
130 * <li>{@link Node}: the concrete node (in one of the AST's clones) from which the event originated. 130 * <li>{@link Node}: the concrete node (in one of the AST's clones) from which the event originated.
179 179
180 /** 180 /**
181 * Creates an instrument that will route execution events to a listener, along with access to 181 * Creates an instrument that will route execution events to a listener, along with access to
182 * internal execution state. 182 * internal execution state.
183 * 183 *
184 * @param astListener a listener for event generated by the instrument that provides access to 184 * @param standardListener a listener for event generated by the instrument that provides access to
185 * internal execution state 185 * internal execution state
186 * @param instrumentInfo optional description of the instrument's role, useful for debugging. 186 * @param instrumentInfo optional description of the instrument's role, useful for debugging.
187 * @return a new instrument, ready for attachment at a probe 187 * @return a new instrument, ready for attachment at a probe
188 */ 188 */
189 public static Instrument create(ASTInstrumentListener astListener, String instrumentInfo) { 189 public static Instrument create(StandardInstrumentListener standardListener, String instrumentInfo) {
190 return new ASTInstrument(astListener, instrumentInfo); 190 return new StandardInstrument(standardListener, instrumentInfo);
191 } 191 }
192 192
193 /** 193 /**
194 * Creates an instrument that, when executed the first time in any particular AST location, 194 * Creates an instrument that, when executed the first time in any particular AST location,
195 * invites the tool to provide an AST fragment for attachment/adoption into the running AST. 195 * invites the tool to provide an AST fragment for attachment/adoption into the running AST.
344 * Removes this instrument from an instrument chain. 344 * Removes this instrument from an instrument chain.
345 */ 345 */
346 abstract AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode); 346 abstract AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode);
347 347
348 /** 348 /**
349 * An instrument that propagates events to an instance of {@link ASTInstrumentListener}. 349 * An instrument that propagates events to an instance of {@link StandardInstrumentListener}.
350 */ 350 */
351 private static final class ASTInstrument extends Instrument { 351 private static final class StandardInstrument extends Instrument {
352 352
353 /** 353 /**
354 * Tool-supplied listener for AST events. 354 * Tool-supplied listener for AST events.
355 */ 355 */
356 private final ASTInstrumentListener astListener; 356 private final StandardInstrumentListener standardListener;
357 357
358 private ASTInstrument(ASTInstrumentListener astListener, String instrumentInfo) { 358 private StandardInstrument(StandardInstrumentListener standardListener, String instrumentInfo) {
359 super(instrumentInfo); 359 super(instrumentInfo);
360 this.astListener = astListener; 360 this.standardListener = standardListener;
361 } 361 }
362 362
363 @Override 363 @Override
364 AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) { 364 AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
365 return new ASTInstrumentNode(nextNode); 365 return new StandardInstrumentNode(nextNode);
366 } 366 }
367 367
368 @Override 368 @Override
369 AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) { 369 AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) {
370 boolean found = false; 370 boolean found = false;
372 if (instrumentNode.getInstrument() == this) { 372 if (instrumentNode.getInstrument() == this) {
373 // Found the match at the head of the chain 373 // Found the match at the head of the chain
374 return instrumentNode.nextInstrumentNode; 374 return instrumentNode.nextInstrumentNode;
375 } 375 }
376 // Match not at the head of the chain; remove it. 376 // Match not at the head of the chain; remove it.
377 found = instrumentNode.removeFromChain(ASTInstrument.this); 377 found = instrumentNode.removeFromChain(StandardInstrument.this);
378 } 378 }
379 if (!found) { 379 if (!found) {
380 throw new IllegalStateException("Couldn't find instrument node to remove: " + this); 380 throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
381 } 381 }
382 return instrumentNode; 382 return instrumentNode;
383 } 383 }
384 384
385 @NodeInfo(cost = NodeCost.NONE) 385 @NodeInfo(cost = NodeCost.NONE)
386 private final class ASTInstrumentNode extends AbstractInstrumentNode { 386 private final class StandardInstrumentNode extends AbstractInstrumentNode {
387 387
388 private ASTInstrumentNode(AbstractInstrumentNode nextNode) { 388 private StandardInstrumentNode(AbstractInstrumentNode nextNode) {
389 super(nextNode); 389 super(nextNode);
390 } 390 }
391 391
392 public void enter(Node node, VirtualFrame vFrame) { 392 public void enter(Node node, VirtualFrame vFrame) {
393 ASTInstrument.this.astListener.enter(ASTInstrument.this.probe, node, vFrame); 393 standardListener.enter(StandardInstrument.this.probe, node, vFrame);
394 if (nextInstrumentNode != null) { 394 if (nextInstrumentNode != null) {
395 nextInstrumentNode.enter(node, vFrame); 395 nextInstrumentNode.enter(node, vFrame);
396 } 396 }
397 } 397 }
398 398
399 public void returnVoid(Node node, VirtualFrame vFrame) { 399 public void returnVoid(Node node, VirtualFrame vFrame) {
400 ASTInstrument.this.astListener.returnVoid(ASTInstrument.this.probe, node, vFrame); 400 standardListener.returnVoid(StandardInstrument.this.probe, node, vFrame);
401 if (nextInstrumentNode != null) { 401 if (nextInstrumentNode != null) {
402 nextInstrumentNode.returnVoid(node, vFrame); 402 nextInstrumentNode.returnVoid(node, vFrame);
403 } 403 }
404 } 404 }
405 405
406 public void returnValue(Node node, VirtualFrame vFrame, Object result) { 406 public void returnValue(Node node, VirtualFrame vFrame, Object result) {
407 ASTInstrument.this.astListener.returnValue(ASTInstrument.this.probe, node, vFrame, result); 407 standardListener.returnValue(StandardInstrument.this.probe, node, vFrame, result);
408 if (nextInstrumentNode != null) { 408 if (nextInstrumentNode != null) {
409 nextInstrumentNode.returnValue(node, vFrame, result); 409 nextInstrumentNode.returnValue(node, vFrame, result);
410 } 410 }
411 } 411 }
412 412
413 public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { 413 public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
414 ASTInstrument.this.astListener.returnExceptional(ASTInstrument.this.probe, node, vFrame, exception); 414 standardListener.returnExceptional(StandardInstrument.this.probe, node, vFrame, exception);
415 if (nextInstrumentNode != null) { 415 if (nextInstrumentNode != null) {
416 nextInstrumentNode.returnExceptional(node, vFrame, exception); 416 nextInstrumentNode.returnExceptional(node, vFrame, exception);
417 } 417 }
418 } 418 }
419 419
420 public String instrumentationInfo() { 420 public String instrumentationInfo() {
421 final String info = getInstrumentInfo(); 421 final String info = getInstrumentInfo();
422 return info != null ? info : astListener.getClass().getSimpleName(); 422 return info != null ? info : standardListener.getClass().getSimpleName();
423 } 423 }
424 } 424 }
425 425 }
426 } 426
427 427 /**
428 /** 428 * An instrument that propagates events to an instance of {@link StandardInstrumentListener}.
429 * An instrument that propagates events to an instance of {@link ASTInstrumentListener}.
430 */ 429 */
431 private static final class ToolNodeInstrument extends Instrument { 430 private static final class ToolNodeInstrument extends Instrument {
432 431
433 /** 432 /**
434 * Tool-supplied listener for AST events. 433 * Tool-supplied listener for AST events.
518 public String instrumentationInfo() { 517 public String instrumentationInfo() {
519 final String info = getInstrumentInfo(); 518 final String info = getInstrumentInfo();
520 return info != null ? info : toolNodeListener.getClass().getSimpleName(); 519 return info != null ? info : toolNodeListener.getClass().getSimpleName();
521 } 520 }
522 } 521 }
523
524 } 522 }
525 523
526 public interface TruffleOptListener { 524 public interface TruffleOptListener {
527 void notifyIsCompiled(boolean isCompiled); 525 void notifyIsCompiled(boolean isCompiled);
528 } 526 }
599 public String instrumentationInfo() { 597 public String instrumentationInfo() {
600 final String info = getInstrumentInfo(); 598 final String info = getInstrumentInfo();
601 return info != null ? info : toolOptListener.getClass().getSimpleName(); 599 return info != null ? info : toolOptListener.getClass().getSimpleName();
602 } 600 }
603 } 601 }
604
605 } 602 }
606 603
607 @NodeInfo(cost = NodeCost.NONE) 604 @NodeInfo(cost = NodeCost.NONE)
608 abstract class AbstractInstrumentNode extends Node implements TruffleEvents, InstrumentationNode { 605 abstract class AbstractInstrumentNode extends Node implements TruffleEvents, InstrumentationNode {
609 606
652 } 649 }
653 650
654 protected String getInstrumentInfo() { 651 protected String getInstrumentInfo() {
655 return Instrument.this.instrumentInfo; 652 return Instrument.this.instrumentInfo;
656 } 653 }
657 654 }
658 }
659
660 } 655 }