Mercurial > hg > graal-jvmci-8
comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java @ 18985:867058575979
Truffle: Improved support for "probing" AST nodes:
- Node.isSafelyReplacaeableBy(Node) checks in advance if Node.replace(Node) would be unsafe (crash the VM).
- Hoist Probe() from language imlementations into Node; now completely language agnostic.
- Language implementations support probing by implementing Node.isInstrumentable() and Node.createWrapperNode()
- Node.Probe() throws ProbeException (without side effects) if the probe fails.
-- ProbeException contains an instance of ProbeFailure that diagnoses the failure in detail
- Additional measures to prevent instrumentation from being applied to internal InstrumentationNodes.
- Promote ProbeListener to top level interface and add a default implementation
author | Michael Van De Vanter <michael.van.de.vanter@oracle.com> |
---|---|
date | Tue, 27 Jan 2015 20:24:54 -0800 |
parents | e3c95cbbb50c |
children | 128586040207 |
comparison
equal
deleted
inserted
replaced
18984:0f462015296f | 18985:867058575979 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this | 7 * published by the Free Software Foundation. Oracle designates this |
26 | 26 |
27 import java.lang.ref.*; | 27 import java.lang.ref.*; |
28 import java.util.*; | 28 import java.util.*; |
29 | 29 |
30 import com.oracle.truffle.api.*; | 30 import com.oracle.truffle.api.*; |
31 import com.oracle.truffle.api.instrument.ProbeNode.Instrumentable; | |
32 import com.oracle.truffle.api.nodes.*; | 31 import com.oracle.truffle.api.nodes.*; |
33 import com.oracle.truffle.api.source.*; | 32 import com.oracle.truffle.api.source.*; |
34 import com.oracle.truffle.api.utilities.*; | 33 import com.oracle.truffle.api.utilities.*; |
35 | 34 |
36 //TODO (mlvdv) migrate some of this to external documentation. | 35 //TODO (mlvdv) migrate some of this to external documentation. |
37 /** | 36 /** |
38 * A binding between a particular location in the Truffle AST representation of a running Guest | 37 * A binding between a particular <em>location</em> in the Truffle AST representation of a running |
39 * Language (GL) program (i.e. a {@link Node}) and a dynamically managed collection of "attached" | 38 * Guest Language (GL) program (i.e. a {@link Node}) and a dynamically managed collection of |
40 * {@linkplain Instrument instrumentation} for use by external tools. | 39 * "attached" {@linkplain Instrument instrumentation} for use by external tools. The instrumentation |
41 * <p> | 40 * is intended to persist at the location, even if the specific node instance is |
42 * The effect of a binding is to intercept {@linkplain TruffleEventReceiver execution events} at the | 41 * {@linkplain Node#replace(Node) replaced}. |
43 * node and notify each attached {@link Instrument} before execution is allowed to resume. | 42 * <p> |
44 * <p> | 43 * The effect of a binding is to intercept {@linkplain TruffleEventReceiver execution events} |
45 * A Probe is "inserted" into a GL node via a call to {@link Instrumentable#probe()}; a GL node must | 44 * arriving at the node and notify each attached {@link Instrument} before execution is allowed to |
46 * implement {@link Instrumentable} in order to support instrumentation. No more than one Probe can | 45 * proceed to the child. |
47 * be inserted at a node. | 46 * <p> |
47 * A Probe is "inserted" into a GL node via a call to {@link Node#probe()}. No more than one Probe | |
48 * can be inserted at a node. | |
48 * <p> | 49 * <p> |
49 * The "probing" of a Truffle AST must be done after it is complete (i.e. with parent pointers | 50 * The "probing" of a Truffle AST must be done after it is complete (i.e. with parent pointers |
50 * correctly assigned), but before any executions. This is done by creating an instance of | 51 * correctly assigned), but before any executions. This is done by creating an instance of |
51 * {@link ASTProber} and registering it via {@link #registerASTProber(ASTProber)}, after which it | 52 * {@link ASTProber} and registering it via {@link #registerASTProber(ASTProber)}, after which it |
52 * will be automatically applied to newly created ASTs. | 53 * will be automatically applied to newly created ASTs. |
53 * <p> | 54 * <p> |
54 * Each Probe may also have assigned to it one or more {@link SyntaxTag}s, for example identifying a | 55 * Each Probe may also have assigned to it any number of {@link SyntaxTag}s, for example identifying |
55 * node as a {@linkplain StandardSyntaxTag#STATEMENT STATEMENT}. Tags can be queried by tools to | 56 * a node as a {@linkplain StandardSyntaxTag#STATEMENT STATEMENT}. Tags can be queried by tools to |
56 * configure behavior relevant to each probed node. | 57 * configure behavior relevant to each probed node. |
57 * <p> | 58 * <p> |
58 * Instrumentation is implemented by modifying ASTs, both by inserting nodes into each AST at probed | 59 * Instrumentation is implemented by modifying ASTs, both by inserting nodes into each AST at probed |
59 * locations and by attaching additional nodes that implement dynamically attached instruments. | 60 * locations and by attaching additional nodes that implement dynamically attached instruments. |
60 * Attached instrumentation code become, in effect, part of the GL program, and is subject to the | 61 * Attached instrumentation code become, in effect, part of the GL program, and is subject to the |
61 * same levels of optimization as other GL code. This implementation accounts properly for the fact | 62 * same levels of optimization as other GL code. This implementation accounts properly for the fact |
62 * that Truffle frequently <em>clones</em> ASTs, along with any attached instrumentation nodes. A | 63 * that Truffle frequently <em>clones</em> ASTs, along with any attached instrumentation nodes. A |
63 * Probe, along with attached Instruments, represents a <em>logical</em> binding with a source code | 64 * {@link Probe}, along with attached {@link Instrument}s, represents a <em>logical</em> binding |
64 * location, producing event notifications that are (mostly) independent of which AST clone is | 65 * with a source code location, producing event notifications that are (mostly) independent of which |
65 * executing. | 66 * AST clone is executing. |
66 * | 67 * |
67 * @see Instrument | 68 * @see Instrument |
68 * @see Instrumentable | |
69 * @see ASTProber | 69 * @see ASTProber |
70 * @see ProbeListener | |
70 */ | 71 */ |
71 public final class Probe implements SyntaxTagged { | 72 public final class Probe implements SyntaxTagged { |
72 | |
73 /** | |
74 * An observer of events related to {@link Probe}s: creating and tagging. | |
75 */ | |
76 public interface ProbeListener { | |
77 | |
78 /** | |
79 * Notifies that all registered {@link ASTProber}s are about to be applied to a newly | |
80 * constructed AST. | |
81 * | |
82 * @param source source code from which the AST was constructed | |
83 */ | |
84 void startASTProbing(Source source); | |
85 | |
86 /** | |
87 * Notifies that a {@link Probe} has been newly attached to an AST via | |
88 * {@link Instrumentable#probe()}. | |
89 * <p> | |
90 * There can be no more than one {@link Probe} at a node; this notification will only be | |
91 * delivered the first time {@linkplain Instrumentable#probe() probe()} is called at a | |
92 * particular AST node. There will also be no notification when the AST to which the Probe | |
93 * is attached is cloned. | |
94 */ | |
95 void newProbeInserted(Probe probe); | |
96 | |
97 /** | |
98 * Notifies that a {@link SyntaxTag} has been newly added to the set of tags associated with | |
99 * a {@link Probe} via {@link Probe#tagAs(SyntaxTag, Object)}. | |
100 * <p> | |
101 * The {@linkplain SyntaxTag tags} at a {@link Probe} are a <em>set</em>; this notification | |
102 * will only be delivered the first time a particular {@linkplain SyntaxTag tag} is added at | |
103 * a {@link Probe}. | |
104 * <p> | |
105 * An optional value supplied with {@linkplain Probe#tagAs(SyntaxTag, Object) | |
106 * tagAs(SyntaxTag, Object)} is reported to all listeners, but not stored. As a consequence, | |
107 * the optional value will have no effect at all if the tag had already been added. | |
108 * | |
109 * @param probe where a tag has been added | |
110 * @param tag the tag that has been newly added (subsequent additions of the tag are | |
111 * unreported). | |
112 * @param tagValue an optional value associated with the tag for the purposes of reporting. | |
113 */ | |
114 void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue); | |
115 | |
116 /** | |
117 * Notifies that the application of all registered {@link ASTProber}s to a newly constructed | |
118 * AST has completed. | |
119 * | |
120 * @param source source code from which the AST was constructed | |
121 */ | |
122 void endASTProbing(Source source); | |
123 | |
124 } | |
125 | 73 |
126 private static final List<ASTProber> astProbers = new ArrayList<>(); | 74 private static final List<ASTProber> astProbers = new ArrayList<>(); |
127 | 75 |
128 private static final List<ProbeListener> probeListeners = new ArrayList<>(); | 76 private static final List<ProbeListener> probeListeners = new ArrayList<>(); |
129 | 77 |
280 * {@code true} iff the global trap is set and this probe has the matching tag. | 228 * {@code true} iff the global trap is set and this probe has the matching tag. |
281 */ | 229 */ |
282 private boolean trapActive = false; | 230 private boolean trapActive = false; |
283 | 231 |
284 /** | 232 /** |
285 * @see Instrumentable#probe() | 233 * Intended for use only by {@link ProbeNode}. |
286 */ | 234 */ |
287 Probe(ProbeNode probeNode, SourceSection sourceSection) { | 235 Probe(ProbeNode probeNode, SourceSection sourceSection) { |
288 this.sourceSection = sourceSection; | 236 this.sourceSection = sourceSection; |
289 probes.add(new WeakReference<>(this)); | 237 probes.add(new WeakReference<>(this)); |
290 registerProbeNodeClone(probeNode); | 238 registerProbeNodeClone(probeNode); |