Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java @ 15450:be0c151d912b
Truffle/Instrumentation: API revisions
author | Michael Van De Vanter <michael.van.de.vanter@oracle.com> |
---|---|
date | Tue, 29 Apr 2014 12:05:58 -0700 |
parents | |
children | bb9473723904 |
comparison
equal
deleted
inserted
replaced
15281:041156bb59b2 | 15450:be0c151d912b |
---|---|
1 /* | |
2 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. Oracle designates this | |
8 * particular file as subject to the "Classpath" exception as provided | |
9 * by Oracle in the LICENSE file that accompanied this code. | |
10 * | |
11 * This code is distributed in the hope that it will be useful, but WITHOUT | |
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 * version 2 for more details (a copy is included in the LICENSE file that | |
15 * accompanied this code). | |
16 * | |
17 * You should have received a copy of the GNU General Public License version | |
18 * 2 along with this work; if not, write to the Free Software Foundation, | |
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
20 * | |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
22 * or visit www.oracle.com if you need additional information or have any | |
23 * questions. | |
24 */ | |
25 package com.oracle.truffle.api.instrument.impl; | |
26 | |
27 import java.util.*; | |
28 | |
29 import com.oracle.truffle.api.*; | |
30 import com.oracle.truffle.api.frame.*; | |
31 import com.oracle.truffle.api.instrument.*; | |
32 import com.oracle.truffle.api.nodes.*; | |
33 | |
34 /** | |
35 * Abstract implementation of Truffle {@link Node} to be used for AST probes and instruments. | |
36 * <p> | |
37 * Coordinates propagation of Truffle AST {@link ExecutionEvents}. | |
38 */ | |
39 public abstract class InstrumentationNode extends Node implements ExecutionEvents { | |
40 | |
41 // TODO (mlvdv) This is a pretty awkward design; it is a priority to revise it. | |
42 | |
43 /** | |
44 * Creates a new {@link Probe}, presumed to be unique to a particular {@linkplain SourceSection} | |
45 * extent of guest language source code. | |
46 * | |
47 * @param eventListener an optional listener for certain instrumentation-related events. | |
48 * @return a new probe | |
49 */ | |
50 static Probe createProbe(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) { | |
51 return new ProbeImpl(instrumentation, sourceSection, eventListener); | |
52 } | |
53 | |
54 /** | |
55 * Next in chain. | |
56 */ | |
57 @Child protected InstrumentationNode next; | |
58 | |
59 protected InstrumentationNode() { | |
60 } | |
61 | |
62 /** | |
63 * @return the instance of {@link Probe} to which this instrument is attached. | |
64 */ | |
65 public Probe getProbe() { | |
66 final InstrumentationNode parent = (InstrumentationNode) getParent(); | |
67 return parent == null ? null : parent.getProbe(); | |
68 } | |
69 | |
70 /** | |
71 * Add a probe to the end of this probe chain. | |
72 */ | |
73 private void internalAddInstrument(Instrument newInstrument) { | |
74 if (next == null) { | |
75 this.next = insert(newInstrument); | |
76 } else { | |
77 next.internalAddInstrument(newInstrument); | |
78 } | |
79 } | |
80 | |
81 private void internalRemoveInstrument(Instrument oldInstrument) { | |
82 if (next == null) { | |
83 throw new RuntimeException("Couldn't find probe to remove: " + oldInstrument); | |
84 } else if (next == oldInstrument) { | |
85 if (oldInstrument.next == null) { | |
86 this.next = null; | |
87 } else { | |
88 this.next = insert(oldInstrument.next); | |
89 oldInstrument.next = null; | |
90 } | |
91 } else { | |
92 next.internalRemoveInstrument(oldInstrument); | |
93 } | |
94 } | |
95 | |
96 /** | |
97 * Reports to the instance of {@link Probe} holding this instrument that some essential state | |
98 * has changed that requires deoptimization. | |
99 */ | |
100 @CompilerDirectives.SlowPath | |
101 protected void notifyProbeChanged(Instrument instrument) { | |
102 final ProbeImpl probe = (ProbeImpl) getProbe(); | |
103 probe.notifyProbeChanged(instrument); | |
104 } | |
105 | |
106 private void internalEnter(Node astNode, VirtualFrame frame) { | |
107 enter(astNode, frame); | |
108 if (next != null) { | |
109 next.internalEnter(astNode, frame); | |
110 } | |
111 } | |
112 | |
113 private void internalLeave(Node astNode, VirtualFrame frame) { | |
114 leave(astNode, frame); | |
115 if (next != null) { | |
116 next.internalLeave(astNode, frame); | |
117 } | |
118 } | |
119 | |
120 private void internalLeave(Node astNode, VirtualFrame frame, boolean result) { | |
121 leave(astNode, frame, result); | |
122 if (next != null) { | |
123 next.internalLeave(astNode, frame, result); | |
124 } | |
125 } | |
126 | |
127 private void internalLeave(Node astNode, VirtualFrame frame, byte result) { | |
128 leave(astNode, frame, result); | |
129 if (next != null) { | |
130 next.internalLeave(astNode, frame, result); | |
131 } | |
132 } | |
133 | |
134 private void internalLeave(Node astNode, VirtualFrame frame, short result) { | |
135 leave(astNode, frame, result); | |
136 if (next != null) { | |
137 next.internalLeave(astNode, frame, result); | |
138 } | |
139 } | |
140 | |
141 private void internalLeave(Node astNode, VirtualFrame frame, int result) { | |
142 leave(astNode, frame, result); | |
143 if (next != null) { | |
144 next.internalLeave(astNode, frame, result); | |
145 } | |
146 } | |
147 | |
148 private void internalLeave(Node astNode, VirtualFrame frame, long result) { | |
149 leave(astNode, frame, result); | |
150 if (next != null) { | |
151 next.internalLeave(astNode, frame, result); | |
152 } | |
153 } | |
154 | |
155 private void internalLeave(Node astNode, VirtualFrame frame, char result) { | |
156 leave(astNode, frame, result); | |
157 if (next != null) { | |
158 next.internalLeave(astNode, frame, result); | |
159 } | |
160 } | |
161 | |
162 private void internalLeave(Node astNode, VirtualFrame frame, float result) { | |
163 leave(astNode, frame, result); | |
164 if (next != null) { | |
165 next.internalLeave(astNode, frame, result); | |
166 } | |
167 } | |
168 | |
169 private void internalLeave(Node astNode, VirtualFrame frame, double result) { | |
170 leave(astNode, frame, result); | |
171 if (next != null) { | |
172 next.internalLeave(astNode, frame, result); | |
173 } | |
174 } | |
175 | |
176 private void internalLeave(Node astNode, VirtualFrame frame, Object result) { | |
177 leave(astNode, frame, result); | |
178 if (next != null) { | |
179 next.internalLeave(astNode, frame, result); | |
180 } | |
181 } | |
182 | |
183 private void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { | |
184 leaveExceptional(astNode, frame, null); | |
185 if (next != null) { | |
186 next.internalLeaveExceptional(astNode, frame, e); | |
187 } | |
188 } | |
189 | |
190 /** | |
191 * Holder of a chain of {@linkplain InstrumentationNode instruments}: manages the | |
192 * {@link Assumption} that none of the instruments have changed since last checked. | |
193 * <p> | |
194 * An instance is intended to be shared by every clone of the AST node with which it is | |
195 * originally attached, so it holds no parent pointer. | |
196 * <p> | |
197 * May be categorized by one or more {@linkplain PhylumTag tags}, signifying information useful | |
198 * for instrumentation about its AST location(s). | |
199 */ | |
200 private static final class ProbeImpl extends InstrumentationNode implements Probe { | |
201 | |
202 final InstrumentationImpl instrumentation; | |
203 | |
204 final InstrumentEventListener eventListener; | |
205 | |
206 @CompilerDirectives.CompilationFinal private Assumption probeUnchanged; | |
207 | |
208 /** | |
209 * When in stepping mode, ordinary line breakpoints are ignored, but every entry at a line | |
210 * will cause a halt. | |
211 */ | |
212 @CompilerDirectives.CompilationFinal private boolean stepping; | |
213 | |
214 /** | |
215 * Source information about the AST node to which this instrumentation is attached. | |
216 */ | |
217 private final SourceSection probedSourceSection; | |
218 | |
219 private final Set<PhylumTag> tags = EnumSet.noneOf(PhylumTag.class); | |
220 | |
221 private ProbeImpl(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) { | |
222 this.instrumentation = instrumentation; | |
223 this.probedSourceSection = sourceSection; | |
224 this.eventListener = eventListener == null ? NullInstrumentEventListener.INSTANCE : eventListener; | |
225 this.probeUnchanged = Truffle.getRuntime().createAssumption(); | |
226 this.next = null; | |
227 } | |
228 | |
229 @Override | |
230 public Probe getProbe() { | |
231 return this; | |
232 } | |
233 | |
234 @Override | |
235 protected void notifyProbeChanged(Instrument instrument) { | |
236 probeUnchanged.invalidate(); | |
237 probeUnchanged = Truffle.getRuntime().createAssumption(); | |
238 } | |
239 | |
240 public SourceSection getSourceLocation() { | |
241 return probedSourceSection; | |
242 } | |
243 | |
244 public void tagAs(PhylumTag tag) { | |
245 assert tag != null; | |
246 if (!tags.contains(tag)) { | |
247 tags.add(tag); | |
248 instrumentation.newTagAdded(this, tag); | |
249 } | |
250 } | |
251 | |
252 public boolean isTaggedAs(PhylumTag tag) { | |
253 assert tag != null; | |
254 return tags.contains(tag); | |
255 } | |
256 | |
257 public Set<PhylumTag> getPhylumTags() { | |
258 return tags; | |
259 } | |
260 | |
261 public void setStepping(boolean stepping) { | |
262 if (this.stepping != stepping) { | |
263 this.stepping = stepping; | |
264 probeUnchanged.invalidate(); | |
265 probeUnchanged = Truffle.getRuntime().createAssumption(); | |
266 } | |
267 } | |
268 | |
269 public boolean isStepping() { | |
270 return stepping; | |
271 } | |
272 | |
273 @CompilerDirectives.SlowPath | |
274 public void addInstrument(Instrument instrument) { | |
275 probeUnchanged.invalidate(); | |
276 super.internalAddInstrument(instrument); | |
277 probeUnchanged = Truffle.getRuntime().createAssumption(); | |
278 } | |
279 | |
280 @CompilerDirectives.SlowPath | |
281 public void removeInstrument(Instrument instrument) { | |
282 probeUnchanged.invalidate(); | |
283 super.internalRemoveInstrument(instrument); | |
284 probeUnchanged = Truffle.getRuntime().createAssumption(); | |
285 } | |
286 | |
287 public void notifyEnter(Node astNode, VirtualFrame frame) { | |
288 if (stepping || next != null) { | |
289 if (!probeUnchanged.isValid()) { | |
290 CompilerDirectives.transferToInterpreter(); | |
291 } | |
292 if (stepping) { | |
293 eventListener.haltedAt(astNode, frame.materialize()); | |
294 } | |
295 if (next != null) { | |
296 next.internalEnter(astNode, frame); | |
297 } | |
298 } | |
299 } | |
300 | |
301 public void notifyLeave(Node astNode, VirtualFrame frame) { | |
302 if (next != null) { | |
303 if (!probeUnchanged.isValid()) { | |
304 CompilerDirectives.transferToInterpreter(); | |
305 } | |
306 next.internalLeave(astNode, frame); | |
307 } | |
308 } | |
309 | |
310 public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) { | |
311 if (next != null) { | |
312 if (!probeUnchanged.isValid()) { | |
313 CompilerDirectives.transferToInterpreter(); | |
314 } | |
315 next.internalLeave(astNode, frame, result); | |
316 } | |
317 } | |
318 | |
319 public void notifyLeave(Node astNode, VirtualFrame frame, byte result) { | |
320 if (next != null) { | |
321 if (!probeUnchanged.isValid()) { | |
322 CompilerDirectives.transferToInterpreter(); | |
323 } | |
324 next.internalLeave(astNode, frame, result); | |
325 } | |
326 } | |
327 | |
328 public void notifyLeave(Node astNode, VirtualFrame frame, short result) { | |
329 if (next != null) { | |
330 if (!probeUnchanged.isValid()) { | |
331 CompilerDirectives.transferToInterpreter(); | |
332 } | |
333 next.internalLeave(astNode, frame, result); | |
334 } | |
335 } | |
336 | |
337 public void notifyLeave(Node astNode, VirtualFrame frame, int result) { | |
338 if (next != null) { | |
339 if (!probeUnchanged.isValid()) { | |
340 CompilerDirectives.transferToInterpreter(); | |
341 } | |
342 next.internalLeave(astNode, frame, result); | |
343 } | |
344 } | |
345 | |
346 public void notifyLeave(Node astNode, VirtualFrame frame, long result) { | |
347 if (next != null) { | |
348 if (!probeUnchanged.isValid()) { | |
349 CompilerDirectives.transferToInterpreter(); | |
350 } | |
351 next.internalLeave(astNode, frame, result); | |
352 } | |
353 } | |
354 | |
355 public void notifyLeave(Node astNode, VirtualFrame frame, char result) { | |
356 if (next != null) { | |
357 if (!probeUnchanged.isValid()) { | |
358 CompilerDirectives.transferToInterpreter(); | |
359 } | |
360 next.internalLeave(astNode, frame, result); | |
361 } | |
362 } | |
363 | |
364 public void notifyLeave(Node astNode, VirtualFrame frame, float result) { | |
365 if (next != null) { | |
366 if (!probeUnchanged.isValid()) { | |
367 CompilerDirectives.transferToInterpreter(); | |
368 } | |
369 next.internalLeave(astNode, frame, result); | |
370 } | |
371 } | |
372 | |
373 public void notifyLeave(Node astNode, VirtualFrame frame, double result) { | |
374 if (next != null) { | |
375 if (!probeUnchanged.isValid()) { | |
376 CompilerDirectives.transferToInterpreter(); | |
377 } | |
378 next.internalLeave(astNode, frame, result); | |
379 } | |
380 } | |
381 | |
382 public void notifyLeave(Node astNode, VirtualFrame frame, Object result) { | |
383 if (next != null) { | |
384 if (!probeUnchanged.isValid()) { | |
385 CompilerDirectives.transferToInterpreter(); | |
386 } | |
387 next.internalLeave(astNode, frame, result); | |
388 } | |
389 } | |
390 | |
391 public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { | |
392 if (next != null) { | |
393 if (!probeUnchanged.isValid()) { | |
394 CompilerDirectives.transferToInterpreter(); | |
395 } | |
396 next.internalLeaveExceptional(astNode, frame, e); | |
397 } | |
398 } | |
399 | |
400 public void enter(Node astNode, VirtualFrame frame) { | |
401 } | |
402 | |
403 public void leave(Node astNode, VirtualFrame frame) { | |
404 } | |
405 | |
406 public void leave(Node astNode, VirtualFrame frame, boolean result) { | |
407 leave(astNode, frame, (Object) result); | |
408 } | |
409 | |
410 public void leave(Node astNode, VirtualFrame frame, byte result) { | |
411 leave(astNode, frame, (Object) result); | |
412 } | |
413 | |
414 public void leave(Node astNode, VirtualFrame frame, short result) { | |
415 leave(astNode, frame, (Object) result); | |
416 } | |
417 | |
418 public void leave(Node astNode, VirtualFrame frame, int result) { | |
419 leave(astNode, frame, (Object) result); | |
420 } | |
421 | |
422 public void leave(Node astNode, VirtualFrame frame, long result) { | |
423 leave(astNode, frame, (Object) result); | |
424 } | |
425 | |
426 public void leave(Node astNode, VirtualFrame frame, char result) { | |
427 leave(astNode, frame, (Object) result); | |
428 } | |
429 | |
430 public void leave(Node astNode, VirtualFrame frame, float result) { | |
431 leave(astNode, frame, (Object) result); | |
432 } | |
433 | |
434 public void leave(Node astNode, VirtualFrame frame, double result) { | |
435 leave(astNode, frame, (Object) result); | |
436 } | |
437 | |
438 public void leave(Node astNode, VirtualFrame frame, Object result) { | |
439 } | |
440 | |
441 public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { | |
442 } | |
443 | |
444 } | |
445 | |
446 } |