comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNodeImpl.java @ 15279:0c6d8a08e31b

Truffle: Major cleanup and extension of the Truffle Instrumentation framework in com.oracle.truffle.api
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Sun, 20 Apr 2014 20:37:27 -0700
parents
children
comparison
equal deleted inserted replaced
14862:0e713dba33bb 15279:0c6d8a08e31b
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 InstrumentationNodeImpl extends Node implements ExecutionEvents {
40
41 // TODO (mlvdv) This is a pretty awkward design.
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 InstrumentationNodeImpl next;
58
59 protected InstrumentationNodeImpl() {
60 }
61
62 /**
63 * @return the instance of {@link Probe} to which this instrument is attached.
64 */
65 public Probe getProbe() {
66 final InstrumentationNodeImpl parent = (InstrumentationNodeImpl) getParent();
67 return parent == null ? null : parent.getProbe();
68 }
69
70 /**
71 * Add a probe to the end of this probe chain.
72 */
73 void internalAddInstrument(InstrumentationNodeImpl newInstrument) {
74 if (next == null) {
75 this.next = insert(newInstrument);
76 } else {
77 next.internalAddInstrument(newInstrument);
78 }
79 }
80
81 void internalRemoveInstrument(InstrumentationNodeImpl 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(InstrumentationNodeImpl 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 InstrumentationNodeImpl 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 InstrumentationNodeImpl 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(InstrumentationNodeImpl 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 final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument;
277 super.internalAddInstrument(instrumentImpl);
278 probeUnchanged = Truffle.getRuntime().createAssumption();
279 }
280
281 @CompilerDirectives.SlowPath
282 public void removeInstrument(Instrument instrument) {
283 probeUnchanged.invalidate();
284 final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument;
285 super.internalRemoveInstrument(instrumentImpl);
286 probeUnchanged = Truffle.getRuntime().createAssumption();
287 }
288
289 public void notifyEnter(Node astNode, VirtualFrame frame) {
290 if (stepping || next != null) {
291 if (!probeUnchanged.isValid()) {
292 CompilerDirectives.transferToInterpreter();
293 }
294 if (stepping) {
295 eventListener.haltedAt(astNode, frame.materialize());
296 }
297 if (next != null) {
298 next.internalEnter(astNode, frame);
299 }
300 }
301 }
302
303 public void notifyLeave(Node astNode, VirtualFrame frame) {
304 if (next != null) {
305 if (!probeUnchanged.isValid()) {
306 CompilerDirectives.transferToInterpreter();
307 }
308 next.internalLeave(astNode, frame);
309 }
310 }
311
312 public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) {
313 if (next != null) {
314 if (!probeUnchanged.isValid()) {
315 CompilerDirectives.transferToInterpreter();
316 }
317 next.internalLeave(astNode, frame, result);
318 }
319 }
320
321 public void notifyLeave(Node astNode, VirtualFrame frame, byte result) {
322 if (next != null) {
323 if (!probeUnchanged.isValid()) {
324 CompilerDirectives.transferToInterpreter();
325 }
326 next.internalLeave(astNode, frame, result);
327 }
328 }
329
330 public void notifyLeave(Node astNode, VirtualFrame frame, short result) {
331 if (next != null) {
332 if (!probeUnchanged.isValid()) {
333 CompilerDirectives.transferToInterpreter();
334 }
335 next.internalLeave(astNode, frame, result);
336 }
337 }
338
339 public void notifyLeave(Node astNode, VirtualFrame frame, int result) {
340 if (next != null) {
341 if (!probeUnchanged.isValid()) {
342 CompilerDirectives.transferToInterpreter();
343 }
344 next.internalLeave(astNode, frame, result);
345 }
346 }
347
348 public void notifyLeave(Node astNode, VirtualFrame frame, long result) {
349 if (next != null) {
350 if (!probeUnchanged.isValid()) {
351 CompilerDirectives.transferToInterpreter();
352 }
353 next.internalLeave(astNode, frame, result);
354 }
355 }
356
357 public void notifyLeave(Node astNode, VirtualFrame frame, char result) {
358 if (next != null) {
359 if (!probeUnchanged.isValid()) {
360 CompilerDirectives.transferToInterpreter();
361 }
362 next.internalLeave(astNode, frame, result);
363 }
364 }
365
366 public void notifyLeave(Node astNode, VirtualFrame frame, float result) {
367 if (next != null) {
368 if (!probeUnchanged.isValid()) {
369 CompilerDirectives.transferToInterpreter();
370 }
371 next.internalLeave(astNode, frame, result);
372 }
373 }
374
375 public void notifyLeave(Node astNode, VirtualFrame frame, double result) {
376 if (next != null) {
377 if (!probeUnchanged.isValid()) {
378 CompilerDirectives.transferToInterpreter();
379 }
380 next.internalLeave(astNode, frame, result);
381 }
382 }
383
384 public void notifyLeave(Node astNode, VirtualFrame frame, Object result) {
385 if (next != null) {
386 if (!probeUnchanged.isValid()) {
387 CompilerDirectives.transferToInterpreter();
388 }
389 next.internalLeave(astNode, frame, result);
390 }
391 }
392
393 public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
394 if (next != null) {
395 if (!probeUnchanged.isValid()) {
396 CompilerDirectives.transferToInterpreter();
397 }
398 next.internalLeaveExceptional(astNode, frame, e);
399 }
400 }
401
402 public void enter(Node astNode, VirtualFrame frame) {
403 }
404
405 public void leave(Node astNode, VirtualFrame frame) {
406 }
407
408 public void leave(Node astNode, VirtualFrame frame, boolean result) {
409 leave(astNode, frame, (Object) result);
410 }
411
412 public void leave(Node astNode, VirtualFrame frame, byte result) {
413 leave(astNode, frame, (Object) result);
414 }
415
416 public void leave(Node astNode, VirtualFrame frame, short result) {
417 leave(astNode, frame, (Object) result);
418 }
419
420 public void leave(Node astNode, VirtualFrame frame, int result) {
421 leave(astNode, frame, (Object) result);
422 }
423
424 public void leave(Node astNode, VirtualFrame frame, long result) {
425 leave(astNode, frame, (Object) result);
426 }
427
428 public void leave(Node astNode, VirtualFrame frame, char result) {
429 leave(astNode, frame, (Object) result);
430 }
431
432 public void leave(Node astNode, VirtualFrame frame, float result) {
433 leave(astNode, frame, (Object) result);
434 }
435
436 public void leave(Node astNode, VirtualFrame frame, double result) {
437 leave(astNode, frame, (Object) result);
438 }
439
440 public void leave(Node astNode, VirtualFrame frame, Object result) {
441 }
442
443 public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
444 }
445
446 }
447
448 }