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 }