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