comparison truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java @ 22231:59e022cee529

Truffle/Instrumentation: rename InstrumentationTool (abstract parent for CoverageTracker, LineToProbesMap, etc.) to Instrumenter.Tool, eliminating the need for an Accessor instance.
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Sun, 20 Sep 2015 17:19:59 -0700
parents 3f2052afcb6d
children 1f19e3cada3d
comparison
equal deleted inserted replaced
22230:3f2052afcb6d 22231:59e022cee529
65 final FindSourceVisitor visitor = new FindSourceVisitor(); 65 final FindSourceVisitor visitor = new FindSourceVisitor();
66 node.accept(visitor); 66 node.accept(visitor);
67 return visitor.source; 67 return visitor.source;
68 } 68 }
69 69
70 private enum ToolState {
71
72 /** Not yet installed, inert. */
73 UNINSTALLED,
74
75 /** Installed, collecting data. */
76 ENABLED,
77
78 /** Installed, not collecting data. */
79 DISABLED,
80
81 /** Was installed, but now removed, inactive, and no longer usable. */
82 DISPOSED;
83 }
84
85 /**
86 * {@linkplain Instrument Instrumentation}-based tools that gather data during Guest Language
87 * program execution.
88 * <p>
89 * Tools share a common <em>life cycle</em>:
90 * <ul>
91 * <li>A newly created tool is inert until {@linkplain #install(Instrumenter) installed}.</li>
92 * <li>An installed tool becomes <em>enabled</em> and immediately begins installing
93 * {@linkplain Instrument instrumentation} on subsequently created ASTs and collecting data from
94 * those instruments</li>
95 * <li>A tool may only be installed once.</li>
96 * <li>It should be possible to install multiple instances of a tool, possibly (but not
97 * necessarily) configured differently with respect to what data is being collected.</li>
98 * <li>Once installed, a tool can be {@linkplain #setEnabled(boolean) enabled and disabled}
99 * arbitrarily.</li>
100 * <li>A disabled tool:
101 * <ul>
102 * <li>Collects no data;</li>
103 * <li>Retains existing AST instrumentation;</li>
104 * <li>Continues to instrument newly created ASTs; and</li>
105 * <li>Retains previously collected data.</li>
106 * </ul>
107 * </li>
108 * <li>An installed tool may be {@linkplain #reset() reset} at any time, which leaves the tool
109 * installed but with all previously collected data removed.</li>
110 * <li>A {@linkplain #dispose() disposed} tool removes all instrumentation (but not
111 * {@linkplain Probe probes}) and becomes permanently disabled; previously collected data
112 * persists.</li>
113 * </ul>
114 * <p>
115 * Tool-specific methods that access data collected by the tool should:
116 * <ul>
117 * <li>Return modification-safe representations of the data; and</li>
118 * <li>Not change the state of the data.</li>
119 * </ul>
120 * <b>Note:</b><br>
121 * Tool installation is currently <em>global</em> to the Truffle Execution environment. When
122 * language-agnostic management of individual execution environments is added to the platform,
123 * installation will be (optionally) specific to a single execution environment.
124 */
125 public abstract static class Tool {
126 // TODO (mlvdv) still thinking about the most appropriate name for this class of tools
127
128 private ToolState toolState = ToolState.UNINSTALLED;
129
130 private Instrumenter instrumenter;
131
132 protected Tool() {
133 }
134
135 /**
136 * Connect the tool to some part of the Truffle runtime, and enable data collection to
137 * start. Instrumentation will only be added to subsequently created ASTs.
138 *
139 * @throws IllegalStateException if the tool has previously been installed.
140 */
141 public final void install(Instrumenter inst) {
142 checkUninstalled();
143 this.instrumenter = inst;
144
145 if (internalInstall()) {
146 toolState = ToolState.ENABLED;
147 }
148 instrumenter.tools.add(this);
149 }
150
151 /**
152 * @return whether the tool is currently collecting data.
153 */
154 public final boolean isEnabled() {
155 return toolState == ToolState.ENABLED;
156 }
157
158 /**
159 * Switches tool state between <em>enabled</em> (collecting data) and <em>disabled</em> (not
160 * collecting data, but keeping data already collected).
161 *
162 * @throws IllegalStateException if not yet installed or disposed.
163 */
164 public final void setEnabled(boolean isEnabled) {
165 checkInstalled();
166 internalSetEnabled(isEnabled);
167 toolState = isEnabled ? ToolState.ENABLED : ToolState.DISABLED;
168 }
169
170 /**
171 * Clears any data already collected, but otherwise does not change the state of the tool.
172 *
173 * @throws IllegalStateException if not yet installed or disposed.
174 */
175 public final void reset() {
176 checkInstalled();
177 internalReset();
178 }
179
180 /**
181 * Makes the tool permanently <em>disabled</em>, removes instrumentation, but keeps data
182 * already collected.
183 *
184 * @throws IllegalStateException if not yet installed or disposed.
185 */
186 public final void dispose() {
187 checkInstalled();
188 internalDispose();
189 toolState = ToolState.DISPOSED;
190 instrumenter.tools.remove(this);
191 }
192
193 /**
194 * @return whether the installation succeeded.
195 */
196 protected abstract boolean internalInstall();
197
198 /**
199 * No subclass action required.
200 *
201 * @param isEnabled
202 */
203 protected void internalSetEnabled(boolean isEnabled) {
204 }
205
206 protected abstract void internalReset();
207
208 protected abstract void internalDispose();
209
210 protected final Instrumenter getInstrumenter() {
211 return instrumenter;
212 }
213
214 /**
215 * Ensure that the tool is currently installed.
216 *
217 * @throws IllegalStateException
218 */
219 private void checkInstalled() throws IllegalStateException {
220 if (toolState == ToolState.UNINSTALLED) {
221 throw new IllegalStateException("Tool " + getClass().getSimpleName() + " not yet installed");
222 }
223 if (toolState == ToolState.DISPOSED) {
224 throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has been disposed");
225 }
226 }
227
228 /**
229 * Ensure that the tool has not yet been installed.
230 *
231 * @throws IllegalStateException
232 */
233 private void checkUninstalled() {
234 if (toolState != ToolState.UNINSTALLED) {
235 throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has already been installed");
236 }
237 }
238 }
239
70 private final Object vm; 240 private final Object vm;
241
242 /** Tools that have been created, but not yet disposed. */
243 private final Set<Tool> tools = Collections.synchronizedSet(new LinkedHashSet<Tool>());
71 244
72 private final Set<ASTProber> astProbers = Collections.synchronizedSet(new LinkedHashSet<ASTProber>()); 245 private final Set<ASTProber> astProbers = Collections.synchronizedSet(new LinkedHashSet<ASTProber>());
73 246
74 private final List<ProbeListener> probeListeners = new ArrayList<>(); 247 private final List<ProbeListener> probeListeners = new ArrayList<>();
75 248
393 566
394 SyntaxTagTrap getAfterTagTrap() { 567 SyntaxTagTrap getAfterTagTrap() {
395 return afterTagTrap; 568 return afterTagTrap;
396 } 569 }
397 570
571 // TODO (mlvdv) build this in as a VM event?
398 /** 572 /**
399 * Enables instrumentation in a newly created AST by applying all registered instances of 573 * Enables instrumentation in a newly created AST by applying all registered instances of
400 * {@link ASTProber}. 574 * {@link ASTProber}.
401 */ 575 */
402 private void applyInstrumentation(Node node) { 576 private void applyInstrumentation(Node node) {