comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java @ 20900:ca13a009e38b

Truffle/Instrumentation: Javadoc on Instrument now includes more thorough notes describing the implementation; client-oriented notes have been rewritten into a documentation page: https://wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Sun, 12 Apr 2015 22:37:16 -0700
parents 129a09815063
children f166d264af9f
comparison
equal deleted inserted replaced
20899:c7f1ab98d950 20900:ca13a009e38b
23 * questions. 23 * questions.
24 */ 24 */
25 package com.oracle.truffle.api.instrument; 25 package com.oracle.truffle.api.instrument;
26 26
27 import com.oracle.truffle.api.*; 27 import com.oracle.truffle.api.*;
28 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
29 import com.oracle.truffle.api.frame.*; 28 import com.oracle.truffle.api.frame.*;
30 import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents; 29 import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents;
31 import com.oracle.truffle.api.instrument.impl.*;
32 import com.oracle.truffle.api.nodes.*; 30 import com.oracle.truffle.api.nodes.*;
33 import com.oracle.truffle.api.source.*; 31 import com.oracle.truffle.api.source.*;
34 32
35 // TODO (mlvdv) migrate some of this to external documentation.
36 // TODO (mlvdv) move all this to a factory implemented in .impl (together with Probe), 33 // TODO (mlvdv) move all this to a factory implemented in .impl (together with Probe),
37 // then break out some of the nested classes into package privates. 34 // then break out some of the nested classes into package privates.
38 /** 35 /**
39 * A dynamically added/removed binding between a {@link Probe}, which provides notification of 36 * A <em>binding</em> between:
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
42 * present two kinds of listeners that be used:
43 * <ol> 37 * <ol>
44 * <li>{@link SimpleInstrumentListener} is the simplest and is intended for tools that require no 38 * <li>A {@link Probe}: a source of <em>execution events</em> taking place at a program location in
45 * access to the <em>internal execution state</em> of the Truffle execution, only that execution has 39 * an executing Truffle AST, and</li>
46 * passed through a particular location in the program. Information about that location is made 40 * <li>A <em>listener</em>: a consumer of execution events on behalf of an external client.
47 * available via the {@link Probe} argument in notification methods, including the
48 * {@linkplain SourceSection source location} of the node and any {@linkplain SyntaxTag tags} that
49 * have been applied to the node.</li>
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
52 * {@link Frame} at the current execution site.</li>
53 * </ol> 41 * </ol>
54 * <p> 42 * <p>
55 * <h4>Summary: How to "instrument" an AST location:</h4> 43 * Client-oriented documentation for the use of Instruments is available online at <a
44 * HREF="https://wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events">Listening for
45 * Execution Events</a>
56 * <p> 46 * <p>
57 * <ol> 47 * The implementation of Instruments is complicated by the requirement that Truffle be able to clone
58 * <li>Create an implementation of a <em>listener</em> interface.</li> 48 * ASTs at any time. In particular, any instrumentation-supporting Nodes that have been attached to
59 * <li>Create an Instrument via factory methods 49 * an AST must be cloned along with the AST: AST clones are not permitted to share Nodes.
60 * {@link Instrument#create(SimpleInstrumentListener, String)} or
61 * {@link Instrument#create(StandardInstrumentListener, String)}.</li>
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>
64 * <li>When no longer needed, "detach" the Instrument via {@link StandardInstrument#dispose()}, at
65 * which point event notifications to the listener cease, and the Instrument becomes unusable.</li>
66 * </ol>
67 * <p> 50 * <p>
68 * <h4>Options for creating listeners:</h4> 51 * AST cloning is intended to be as <em>transparent</em> as possible to clients. This is encouraged
52 * by providing the {@link SimpleInstrumentListener} for clients that need know nothing more than
53 * the properties associated with a Probe: it's {@link SourceSection} and any associated instances
54 * of {@link SyntaxTag}.
69 * <p> 55 * <p>
70 * <ol> 56 * AST cloning is <em>not transparent</em> to clients that use the
71 * <li>Implement one of the <em>listener interfaces</em>: {@link SimpleInstrumentListener} or 57 * {@link StandardInstrumentListener}, since those event methods identify the concrete Node instance
72 * {@link StandardInstrumentListener} . Their event handling methods account for both the entry into 58 * (and thus the AST instance) where the event takes place.
73 * an AST node (about to call) and three possible kinds of <em>execution return</em> from an AST
74 * node.</li>
75 * <li>Extend one of the <em>helper implementations</em>: {@link DefaultSimpleInstrumentListener} or
76 * {@link DefaultStandardInstrumentListener}. These provide no-op implementation of every listener
77 * method, so only the methods of interest need to be overridden.</li>
78 * </ol>
79 * <p> 59 * <p>
80 * <h4>General guidelines for {@link StandardInstrumentListener} implementation:</h4> 60 * <h4>Implementation Notes: the Life Cycle of an {@link Instrument} at a {@link Probe}</h4>
81 * <p>
82 * Unlike the listener interface {@link SimpleInstrumentListener}, which isolates implementations
83 * from Truffle internals (and is thus <em>Truffle-safe</em>), implementations of
84 * {@link StandardInstrumentListener} can interact directly with (and potentially affect) Truffle
85 * execution in general and Truffle optimization in particular. For example, it is possible to
86 * implement a debugger with this interface.
87 * </p>
88 * <p>
89 * As a consequence, implementations of {@link StandardInstrumentListener} effectively become part
90 * of the Truffle execution and must be coded according to general guidelines for Truffle
91 * implementations. For example:
92 * <ul>
93 * <li>Do not store {@link Frame} or {@link Node} references in fields.</li>
94 * <li>Prefer {@code final} fields and (where performance is important) short methods.</li>
95 * <li>If needed, pass along the {@link VirtualFrame} reference from an event notification as far as
96 * possible through code that is expected to be inlined, since this incurs no runtime overhead. When
97 * access to frame data is needed, substitute a more expensive {@linkplain Frame#materialize()
98 * materialized} representation of the frame.</li>
99 * <li>If a listener calls back to its tool during event handling, and if performance is an issue,
100 * then this should be through a final "callback" field in the instrument, and the called methods
101 * should be minimal.</li>
102 * <li>On the other hand, implementations should prevent Truffle from inlining beyond a reasonable
103 * point with the method annotation {@link TruffleBoundary}.</li>
104 * <li>The implicit "outer" pointer in a non-static inner class is a useful (and
105 * Truffle-optimizable) way to implement callbacks to owner tools.</li>
106 * <li>Primitive-valued return events are boxed for event notification, but Truffle will eliminate
107 * the boxing if they are cast back to their primitive values quickly (in particular before crossing
108 * any {@link TruffleBoundary} annotations).
109 * </ul>
110 * <p>
111 * <h4>Allowing for AST cloning:</h4>
112 * <p>
113 * Truffle routinely <em>clones</em> ASTs, which has consequences for implementations of
114 * {@link StandardInstrumentListener} (but not for implementations of
115 * {@link SimpleInstrumentListener}, from which cloning is hidden).
116 * <ul>
117 * <li>Even though a {@link Probe} is uniquely associated with a particular location in the
118 * executing Guest Language program, execution events at that location will in general be
119 * implemented by different {@link Node} instances, i.e. <em>clones</em> of the originally probed
120 * node.</li>
121 * <li>Because of <em>cloning</em> the {@link Node} supplied with notifications to a particular
122 * listener will vary, but because they all represent the same GL program location the events should
123 * be treated as equivalent for most purposes.</li>
124 * </ul>
125 * <p>
126 * <h4>Access to execution state via {@link StandardInstrumentListener}:</h4>
127 * <p> 61 * <p>
128 * <ul> 62 * <ul>
129 * <li>Notification arguments provide primary access to the GL program's execution states: 63 * <li>A new Instrument is created in permanent association with a client-provided
130 * <ul> 64 * <em>listener.</em></li>
131 * <li>{@link Node}: the concrete node (in one of the AST's clones) from which the event originated. 65 * <li>Multiple Instruments may share a single listener.</li>
66 * <li>An Instrument does nothing until it is {@linkplain Probe#attach(Instrument) attached} to a
67 * Probe, at which time the Instrument begins routing execution events from the Probe's AST location
68 * to the Instrument's listener.</li>
69 * <li>Neither Instruments nor Probes are {@link Node}s.</li>
70 * <li>A Probe has a single source-based location in an AST, but manages a separate
71 * <em>instrumentation chain</em> of Nodes at the equivalent location in each clone of the AST.</li>
72 * <li>When a probed AST is cloned, the instrumentation chain associated with each Probe is cloned
73 * along with the rest of the AST.</li>
74 * <li>When a new Instrument (for example an instance of {@link SimpleInstrument} is attached to a
75 * Probe, the Instrument inserts a new instance of its private Node type,
76 * {@link SimpleInstrument.SimpleInstrumentNode}, into <em>each of the instrument chains</em>
77 * managed by the Probe, i.e. one node instance per existing clone of the AST.</li>
78 * <li>If an Instrument is attached to a Probe in an AST that subsequently gets cloned, then the
79 * Instrument's private Node type will be cloned along with the rest of the the AST.</li>
80 * <li>Each Instrument's private Node type is a dynamic inner class whose only state is in the
81 * shared (outer) Instrument instance; that state includes a reference to the Instrument's listener.
132 * </li> 82 * </li>
133 * <li>{@link VirtualFrame}: the current execution frame. 83 * <li>When an Instrument that has been attached to a Probe is {@linkplain #dispose() disposed}, the
84 * Instrument searches every instrument chain associated with the Probe and removes the instance of
85 * its private Node type.</li>
86 * <li>Attaching and disposing an Instrument at a Probe <em>deoptimizes</em> any compilations of the
87 * AST.</li>
134 * </ul> 88 * </ul>
135 * <li>Truffle global information is available, for example the execution
136 * {@linkplain TruffleRuntime#iterateFrames(FrameInstanceVisitor) stack}.</li>
137 * <li>Additional API access to execution state may be added in the future.</li>
138 * </ul>
139 * <p>
140 * <h4>Activating and deactivating Instruments:</h4>
141 * <p>
142 * Instruments are <em>single-use</em>:
143 * <ul>
144 * <li>An instrument becomes active only when <em>attached</em> to a Probe via
145 * {@link Probe#attach(Instrument)}, and it may only be attached to a single Probe. It is a runtime
146 * error to attempt attaching a previously attached instrument.</li>
147 * <li>Attaching an instrument modifies every existing clone of the AST to which it is being
148 * attached, which can trigger deoptimization.</li>
149 * <li>The method {@link Instrument#dispose()} makes an instrument inactive by removing it from the
150 * Probe to which it was attached and rendering it permanently inert.</li>
151 * <li>Disposal removes the implementation of an instrument from all ASTs to which it was attached,
152 * which can trigger deoptimization.</li>
153 * </ul>
154 * <p>
155 * <h4>Sharing listeners:</h4>
156 * <p>
157 * Although an Instrument may only be attached to a single Probe, a listener can be shared among
158 * multiple Instruments. This can be useful for observing events that might happen at different
159 * locations in a single AST, for example all assignments to a particular variable. In this case a
160 * new Instrument would be created and attached at each assignment node, but all the Instruments
161 * would be created with the same listener.
162 * <p>
163 * <strong>Disclaimer:</strong> experimental; under development.
164 * 89 *
165 * @see Probe 90 * @see Probe
166 * @see TruffleEvents 91 * @see TruffleEvents
167 */ 92 */
168 public abstract class Instrument { 93 public abstract class Instrument {
227 private Instrument(String instrumentInfo) { 152 private Instrument(String instrumentInfo) {
228 this.instrumentInfo = instrumentInfo; 153 this.instrumentInfo = instrumentInfo;
229 } 154 }
230 155
231 /** 156 /**
232 * Removes this instrument (and any clones) from the probe to which it attached and renders the 157 * Removes this instrument from the probe to which it attached and renders the instrument inert.
233 * instrument inert.
234 * 158 *
235 * @throws IllegalStateException if this instrument has already been disposed 159 * @throws IllegalStateException if this instrument has already been disposed
236 */ 160 */
237 public void dispose() throws IllegalStateException { 161 public void dispose() throws IllegalStateException {
238 if (isDisposed) { 162 if (isDisposed) {
423 return info != null ? info : standardListener.getClass().getSimpleName(); 347 return info != null ? info : standardListener.getClass().getSimpleName();
424 } 348 }
425 } 349 }
426 } 350 }
427 351
352 // TODO (mlvdv) EXPERIMENTAL- UNDER DEVELOPMENT
428 /** 353 /**
429 * An instrument that propagates events to an instance of {@link StandardInstrumentListener}. 354 * An instrument that propagates events to an instance of {@link StandardInstrumentListener}.
430 */ 355 */
431 private static final class ToolNodeInstrument extends Instrument { 356 private static final class ToolNodeInstrument extends Instrument {
432 357