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);