comparison graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/Breakpoint.java @ 21568:3b8bbf51d320

Truffle/Debugging: add the Truffle DebugEngine and supporting code, as well as add a crude command-line debugging tool used mainly to test the DebugEngine. Migrate the small tols out of project com.oracle.truffle.api into the new project com.oracle.truffle.tools.
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Tue, 26 May 2015 16:38:13 -0700
parents
children
comparison
equal deleted inserted replaced
21470:1bbef57f9a38 21568:3b8bbf51d320
1 /*
2 * Copyright (c) 2015, 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.tools.debug.engine;
26
27 import com.oracle.truffle.api.instrument.*;
28 import com.oracle.truffle.api.source.*;
29
30 public abstract class Breakpoint {
31
32 /**
33 * A general model of the states occupied by a breakpoint during its lifetime.
34 */
35 public enum BreakpointState {
36
37 /**
38 * Not attached, enabled.
39 * <p>
40 * Created for a source location but not yet attached: perhaps just created and the source
41 * hasn't been loaded yet; perhaps source has been loaded, but the line location isn't
42 * probed so a breakpoint cannot be attached. Can be either enabled or disabled.
43 */
44 ENABLED_UNRESOLVED("Enabled/Unresolved"),
45
46 /**
47 * Not attached, disabled.
48 * <p>
49 * Created for a source location but not yet attached: perhaps just created and the source
50 * hasn't been loaded yet; perhaps source has been loaded, but the line location isn't
51 * probed so a breakpoint cannot be attached.
52 */
53 DISABLED_UNRESOLVED("Disabled/Unresolved"),
54
55 /**
56 * Attached, instrument enabled.
57 * <p>
58 * Is currently implemented by some {@link Instrument}, which is attached to a {@link Probe}
59 * at a specific node in the AST, and the breakpoint is enabled.
60 */
61 ENABLED("Enabled"),
62
63 /**
64 * Attached, instrument disabled.
65 * <p>
66 * Is currently implemented by some {@link Instrument}, which is attached to a {@link Probe}
67 * at a specific node in the AST, and the breakpoint is disabled.
68 */
69 DISABLED("Disabled"),
70
71 /**
72 * Not attached, instrument is permanently disabled.
73 */
74 DISPOSED("Disposed");
75
76 private final String name;
77
78 BreakpointState(String name) {
79 this.name = name;
80 }
81
82 public String getName() {
83 return name;
84 }
85
86 @Override
87 public String toString() {
88 return name;
89 }
90
91 }
92
93 private static int nextBreakpointId = 0;
94
95 private final int id;
96 private final int groupId;
97 private final boolean isOneShot;
98
99 private int ignoreCount;
100
101 private int hitCount = 0;
102
103 private BreakpointState state;
104
105 Breakpoint(BreakpointState state, int groupId, int ignoreCount, boolean isOneShot) {
106 this.state = state;
107 this.id = nextBreakpointId++;
108 this.groupId = groupId;
109 this.isOneShot = isOneShot;
110 this.ignoreCount = ignoreCount;
111 }
112
113 /**
114 * Unique ID.
115 */
116 public final int getId() {
117 return id;
118 }
119
120 /**
121 * Group ID, set when created.
122 */
123 public final int getGroupId() {
124 return groupId;
125 }
126
127 /**
128 * Enables or disables this breakpoint's AST instrumentation. The breakpoint is enabled by
129 * default.
130 *
131 * @param enabled <code>true</code> to activate the instrumentation, <code>false</code> to
132 * deactivate the instrumentation so that it has no effect.
133 */
134 public abstract void setEnabled(boolean enabled);
135
136 /**
137 * Is this breakpoint active?
138 */
139 public abstract boolean isEnabled();
140
141 /**
142 * Sets the condition on this breakpoint, {@code null} to make it unconditional.
143 *
144 * @param expr if non{@code -null}, a boolean expression, expressed in the guest language, to be
145 * evaluated in the lexical context at the breakpoint location.
146 * @throws DebugException if condition is invalid
147 * @throws UnsupportedOperationException if the breakpoint does not support conditions
148 */
149 public abstract void setCondition(String expr) throws DebugException;
150
151 /**
152 * Gets the string, expressed in the Guest Language, that defines the current condition on this
153 * breakpoint; {@code null} if this breakpoint is currently unconditional.
154 */
155 public String getCondition() {
156 return null;
157 }
158
159 /**
160 * Does this breakpoint remove itself after first activation?
161 */
162 public final boolean isOneShot() {
163 return isOneShot;
164 }
165
166 /**
167 * Gets the number of hits left to be ignored before halting.
168 */
169 public final int getIgnoreCount() {
170 return ignoreCount;
171 }
172
173 /**
174 * Change the threshold for when this breakpoint should start causing a break. When both an
175 * ignore count and a {@linkplain #setCondition(String) condition} are specified, the condition
176 * is evaluated first: if {@code false} it is not considered to be a hit. In other words, the
177 * ignore count is for successful conditions only.
178 */
179 public final void setIgnoreCount(int ignoreCount) {
180 this.ignoreCount = ignoreCount;
181 }
182
183 /**
184 * Number of times this breakpoint has reached, with one exception; if the breakpoint has a
185 * condition that evaluates to {@code false}, it does not count as a hit.
186 */
187 public final int getHitCount() {
188 return hitCount;
189 }
190
191 /**
192 * Disables this breakpoint and removes any associated instrumentation; it becomes permanently
193 * inert.
194 */
195 public abstract void dispose();
196
197 /**
198 * Gets a human-sensible description of this breakpoint's location in a {@link Source}.
199 */
200 public abstract String getLocationDescription();
201
202 public final BreakpointState getState() {
203 return state;
204 }
205
206 final void assertState(BreakpointState s) {
207 assert state == s;
208 }
209
210 final void setState(BreakpointState state) {
211 this.state = state;
212 }
213
214 /**
215 * Assumes that all conditions for causing the break have been satisfied, so increments the
216 * <em>hit count</em>. Then checks if the <em>ignore count</em> has been exceeded, and if so
217 * returns {@code true}. If not, it still counts as a <em>hit</em> but should be ignored.
218 *
219 * @return whether to proceed
220 */
221 final boolean incrHitCountCheckIgnore() {
222 return ++hitCount > ignoreCount;
223 }
224
225 @Override
226 public String toString() {
227 final StringBuilder sb = new StringBuilder(getClass().getSimpleName());
228 sb.append(" state=");
229 sb.append(getState() == null ? "<none>" : getState().getName());
230 if (isOneShot()) {
231 sb.append(", " + "One-Shot");
232 }
233 if (getCondition() != null) {
234 sb.append(", condition=\"" + getCondition() + "\"");
235 }
236 return sb.toString();
237 }
238 }