comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java @ 19869:1d6a7ea5de59

Truffle/Instrumentation: remove support for "probe-lite", an optimization for a particular use case that no longer seems worth the complexity.
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Mon, 16 Mar 2015 15:59:57 -0700
parents 907128d02b31
children d7c48ee7ed4b
comparison
equal deleted inserted replaced
19858:1cbbdc29ab45 19869:1d6a7ea5de59
31 import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents; 31 import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents;
32 import com.oracle.truffle.api.nodes.*; 32 import com.oracle.truffle.api.nodes.*;
33 import com.oracle.truffle.api.source.*; 33 import com.oracle.truffle.api.source.*;
34 34
35 /** 35 /**
36 * Implementation interfaces and classes for attaching {@link Probe}s to {@link WrapperNode}s. 36 * Implementation class & interface for enabling the attachment of {@linkplain Probe Probes} to
37 * Truffle ASTs.
38 * <p>
39 * A {@link ProbeNode} is the head of a chain of nodes acting on behalf of {@linkplain Instrument
40 * instruments}. It is attached to an AST as a child of a guest-language-specific
41 * {@link WrapperNode} node.
42 * <p>
43 * When Truffle clones an AST, the chain, including all attached {@linkplain Instrument instruments}
44 * will be cloned along with the {@link WrapperNode} to which it is attached. An instance of
45 * {@link Probe} represents abstractly the instrumentation at a particular location in a GL AST,
46 * tracks the clones of the chain, and keeps the instrumentation attached to the clones consistent.
37 */ 47 */
38 public abstract class ProbeNode extends Node implements TruffleEvents, InstrumentationNode { 48 @NodeInfo(cost = NodeCost.NONE)
49 public final class ProbeNode extends Node implements TruffleEvents, InstrumentationNode {
39 50
40 /** 51 /**
41 * A node that can be inserted into a Truffle AST, and which enables {@linkplain Instrument 52 * A node that can be inserted into a Truffle AST, and which enables {@linkplain Instrument
42 * instrumentation} at a particular Guest Language (GL) node. Implementations must extend 53 * instrumentation} at a particular Guest Language (GL) node. Implementations must extend
43 * {@link Node} and should override {@link Node#isInstrumentable()} to return {@code false}. 54 * {@link Node} and should override {@link Node#isInstrumentable()} to return {@code false}.
89 * the Instrumentation Framework. 100 * the Instrumentation Framework.
90 */ 101 */
91 Node getChild(); 102 Node getChild();
92 103
93 /** 104 /**
94 * Gets the {@link Probe} responsible for installing this wrapper; none if the wrapper 105 * Gets the {@link Probe} responsible for installing this wrapper.
95 * installed via {@linkplain Node#probeLite(ASTInstrumentListener) "lite-Probing"}.
96 */ 106 */
97 Probe getProbe(); 107 Probe getProbe();
98 108
99 /** 109 /**
100 * Implementation support for completing a newly created wrapper node. 110 * Implementation support for completing a newly created wrapper node.
101 */ 111 */
102 void insertProbe(ProbeNode probeNode); 112 void insertProbe(ProbeNode probeNode);
103
104 } 113 }
105 114
106 /** 115 /**
107 * Create a new {@link Probe} associated with, and attached to, a Guest Language specific 116 * Create a new {@link Probe} associated with, and attached to, a Guest Language specific
108 * instance of {@link WrapperNode}. 117 * instance of {@link WrapperNode}.
109 */ 118 */
110 public static Probe insertProbe(WrapperNode wrapper) { 119 public static Probe insertProbe(WrapperNode wrapper) {
111 final SourceSection sourceSection = wrapper.getChild().getSourceSection(); 120 final SourceSection sourceSection = wrapper.getChild().getSourceSection();
112 final ProbeFullNode probeFullNode = new ProbeFullNode(); // private constructor 121 final ProbeNode probeNode = new ProbeNode(); // private constructor
113 final Probe probe = new Probe(probeFullNode, sourceSection); // package private access 122 probeNode.probe = new Probe(probeNode, sourceSection); // package private access
114 probeFullNode.setProbe(probe); 123 wrapper.insertProbe(probeNode);
115 wrapper.insertProbe(probeFullNode); 124 return probeNode.probe;
116 return probe; 125 }
117 } 126
118 127 // Never changed once set.
119 /** 128 @CompilationFinal Probe probe = null;
120 * Creates a new {@link ProbeLiteNode} associated with, and attached to, a Guest Language 129 /**
121 * specific instance of {@link WrapperNode}. 130 * First {@link AbstractInstrumentNode} node in chain; {@code null} of no instruments in chain.
122 */ 131 */
123 public static void insertProbeLite(WrapperNode wrapper, ASTInstrumentListener instrumentListener) { 132 @Child protected AbstractInstrumentNode firstInstrument;
124 final ProbeLiteNode probeLiteNode = new ProbeLiteNode(instrumentListener);
125 wrapper.insertProbe(probeLiteNode);
126 }
127 133
128 @Override 134 @Override
129 public boolean isInstrumentable() { 135 public boolean isInstrumentable() {
130 return false; 136 return false;
131 } 137 }
132 138
139 @Override
140 public Node copy() {
141 Node node = super.copy();
142 probe.registerProbeNodeClone((ProbeNode) node);
143 return node;
144 }
145
133 /** 146 /**
134 * @return the {@link Probe} permanently associated with this {@link ProbeNode}. 147 * @return the {@link Probe} permanently associated with this {@link ProbeNode}.
135 * 148 */
136 * @throws IllegalStateException if this location was "lite-Probed" 149 public Probe getProbe() {
137 */ 150 return probe;
138 public abstract Probe getProbe() throws IllegalStateException; 151 }
152
153 public void enter(Node node, VirtualFrame vFrame) {
154 this.probe.checkProbeUnchanged();
155 final SyntaxTagTrap trap = probe.getTrap();
156 if (trap != null) {
157 trap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
158 }
159 if (firstInstrument != null) {
160 firstInstrument.enter(node, vFrame);
161 }
162 }
163
164 public void returnVoid(Node node, VirtualFrame vFrame) {
165 this.probe.checkProbeUnchanged();
166 if (firstInstrument != null) {
167 firstInstrument.returnVoid(node, vFrame);
168 }
169 }
170
171 public void returnValue(Node node, VirtualFrame vFrame, Object result) {
172 this.probe.checkProbeUnchanged();
173 if (firstInstrument != null) {
174 firstInstrument.returnValue(node, vFrame, result);
175 }
176 }
177
178 public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
179 this.probe.checkProbeUnchanged();
180 if (firstInstrument != null) {
181 firstInstrument.returnExceptional(node, vFrame, exception);
182 }
183 }
184
185 public String instrumentationInfo() {
186 return "Standard probe";
187 }
139 188
140 /** 189 /**
141 * Adds an {@link AbstractInstrumentNode} to this chain. 190 * Adds an {@link AbstractInstrumentNode} to this chain.
142 * 191 */
143 * @throws IllegalStateException if at a "lite-Probed" location. 192 @TruffleBoundary
144 */ 193 void addInstrument(Instrument instrument) {
145 abstract void addInstrument(Instrument instrument); 194 assert instrument.getProbe() == probe;
195 // The existing chain of nodes may be empty
196 // Attach the modified chain.
197 firstInstrument = insert(instrument.addToChain(firstInstrument));
198 }
146 199
147 /** 200 /**
148 * Removes an instrument from this chain of instruments. 201 * Removes an instrument from this chain of instruments.
149 * 202 *
150 * @throws IllegalStateException if at a "lite-Probed" location.
151 * @throws RuntimeException if no matching instrument is found, 203 * @throws RuntimeException if no matching instrument is found,
152 */ 204 */
153 abstract void removeInstrument(Instrument instrument); 205 @TruffleBoundary
154 206 void removeInstrument(Instrument instrument) {
155 /** 207 assert instrument.getProbe() == probe;
156 * Implementation class & interfaces for enabling the attachment of {@linkplain Probe Probes} to 208 final AbstractInstrumentNode modifiedChain = instrument.removeFromChain(firstInstrument);
157 * Truffle ASTs. 209 if (modifiedChain == null) {
158 * <p> 210 firstInstrument = null;
159 * Head of a chain of nodes acting on behalf of {@linkplain Instrument instruments}, attached to 211 } else {
160 * a Guest Language (GL) AST as a child of a GL-specific {@link WrapperNode} node. 212 firstInstrument = insert(modifiedChain);
161 * <p> 213 }
162 * When Truffle clones an AST, the chain, including all attached {@linkplain Instrument 214 }
163 * instruments} will be cloned along with the {@link WrapperNode} to which it is attached. An 215
164 * instance of {@link Probe} represents abstractly the instrumentation at a particular location
165 * in a GL AST, tracks the clones of the chain, and keeps the instrumentation attached to the
166 * clones consistent.
167 */
168 @NodeInfo(cost = NodeCost.NONE)
169 private static final class ProbeFullNode extends ProbeNode {
170
171 /**
172 * First {@link AbstractInstrumentNode} node in chain; {@code null} of no instruments in
173 * chain.
174 */
175 @Child protected AbstractInstrumentNode firstInstrument;
176
177 // Never changed once set.
178 @CompilationFinal private Probe probe = null;
179
180 private ProbeFullNode() {
181 this.firstInstrument = null;
182 }
183
184 @Override
185 public Probe getProbe() throws IllegalStateException {
186 return probe;
187 }
188
189 @Override
190 public Node copy() {
191 Node node = super.copy();
192 probe.registerProbeNodeClone((ProbeNode) node);
193 return node;
194 }
195
196 private void setProbe(Probe probe) {
197 this.probe = probe;
198 }
199
200 @Override
201 @TruffleBoundary
202 void addInstrument(Instrument instrument) {
203 assert instrument.getProbe() == probe;
204 // The existing chain of nodes may be empty
205 // Attach the modified chain.
206 firstInstrument = insert(instrument.addToChain(firstInstrument));
207 }
208
209 @Override
210 @TruffleBoundary
211 void removeInstrument(Instrument instrument) {
212 assert instrument.getProbe() == probe;
213 final AbstractInstrumentNode modifiedChain = instrument.removeFromChain(firstInstrument);
214 if (modifiedChain == null) {
215 firstInstrument = null;
216 } else {
217 firstInstrument = insert(modifiedChain);
218 }
219 }
220
221 public void enter(Node node, VirtualFrame vFrame) {
222 this.probe.checkProbeUnchanged();
223 final SyntaxTagTrap trap = probe.getTrap();
224 if (trap != null) {
225 trap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
226 }
227 if (firstInstrument != null) {
228 firstInstrument.enter(node, vFrame);
229 }
230 }
231
232 public void returnVoid(Node node, VirtualFrame vFrame) {
233 this.probe.checkProbeUnchanged();
234 if (firstInstrument != null) {
235 firstInstrument.returnVoid(node, vFrame);
236 }
237 }
238
239 public void returnValue(Node node, VirtualFrame vFrame, Object result) {
240 this.probe.checkProbeUnchanged();
241 if (firstInstrument != null) {
242 firstInstrument.returnValue(node, vFrame, result);
243 }
244 }
245
246 public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
247 this.probe.checkProbeUnchanged();
248 if (firstInstrument != null) {
249 firstInstrument.returnExceptional(node, vFrame, exception);
250 }
251 }
252
253 public String instrumentationInfo() {
254 return "Standard probe";
255 }
256 }
257
258 /**
259 * Implementation of a probe that only ever has a single "instrument" associated with it. No
260 * {@link Instrument} is ever created; instead this method simply delegates the various enter
261 * and return events to a {@link TruffleEvents} passed in during construction.
262 */
263 @NodeInfo(cost = NodeCost.NONE)
264 private static final class ProbeLiteNode extends ProbeNode {
265
266 private final ASTInstrumentListener instrumentListener;
267
268 private ProbeLiteNode(ASTInstrumentListener eventListener) {
269 this.instrumentListener = eventListener;
270 }
271
272 @Override
273 public Probe getProbe() throws IllegalStateException {
274 throw new IllegalStateException("\"lite-Probed\" nodes have no explicit Probe");
275 }
276
277 @Override
278 @TruffleBoundary
279 void addInstrument(Instrument instrument) {
280 throw new IllegalStateException("Instruments may not be added at a \"lite-probed\" location");
281 }
282
283 @Override
284 @TruffleBoundary
285 void removeInstrument(Instrument instrument) {
286 throw new IllegalStateException("Instruments may not be removed at a \"lite-probed\" location");
287 }
288
289 public void enter(Node node, VirtualFrame vFrame) {
290 instrumentListener.enter(getProbe(), node, vFrame);
291 }
292
293 public void returnVoid(Node node, VirtualFrame vFrame) {
294 instrumentListener.returnVoid(getProbe(), node, vFrame);
295 }
296
297 public void returnValue(Node node, VirtualFrame vFrame, Object result) {
298 instrumentListener.returnValue(getProbe(), node, vFrame, result);
299 }
300
301 public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
302 instrumentListener.returnExceptional(getProbe(), node, vFrame, exception);
303 }
304
305 public String instrumentationInfo() {
306 return "\"Lite\" probe";
307 }
308
309 }
310 } 216 }