Source code: netscape/jsdebug/ThreadStateBase.java
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 *
3 * The contents of this file are subject to the Netscape Public
4 * License Version 1.1 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of
6 * the License at http://www.mozilla.org/NPL/
7 *
8 * Software distributed under the License is distributed on an "AS
9 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10 * implied. See the License for the specific language governing
11 * rights and limitations under the License.
12 *
13 * The Original Code is mozilla.org code.
14 *
15 * The Initial Developer of the Original Code is Netscape
16 * Communications Corporation. Portions created by Netscape are
17 * Copyright (C) 1998 Netscape Communications Corporation. All
18 * Rights Reserved.
19 *
20 * Contributor(s):
21 */
22
23 package netscape.jsdebug;
24
25 /*
26 * jband - 03/19/97
27 *
28 * This is an 'abstracted version of netscape.debug.ThreadState
29 *
30 * The methods that were 'native' there are 'abstract' here.
31 * Changed 'private' data to 'protected' (though native access is immune)
32 * Changed 'private' resume0() to 'protected'
33 * Removed ThreadHook referneces
34 *
35 */
36
37 /**
38 * When a hook is hit, the debugger records the state of the
39 * thread before the hook in a ThreadState object. This object
40 * is then passed to any hook methods that are called, and can
41 * be used to change the state of the thread when it resumes from the
42 * hook.
43 *
44 * @author John Bandhauer
45 * @author Nick Thompson
46 * @version 1.0
47 * @since 1.0
48 */
49 public abstract class ThreadStateBase {
50 protected Thread thread;
51 protected boolean valid;
52 protected boolean runningHook;
53 protected boolean resumeWhenDone;
54 protected int status;
55 protected int continueState;
56 protected StackFrameInfo[] stack; /* jband - 03/19/97 - had no access modifier */
57 protected Object returnValue;
58 protected Throwable currentException;
59 protected int currentFramePtr; /* used internally */
60 protected ThreadStateBase previous;
61
62 /**
63 * <B><font color="red">Not Implemented.</font></B>
64 * Always throws <code>InternalError("unimplemented")</code>
65 */
66 public static ThreadStateBase getThreadState(Thread t)
67 throws InvalidInfoException
68 {
69 throw new InternalError("unimplemented");
70 }
71
72 /**
73 * Get the Thread that this ThreadState came from.
74 */
75 public Thread getThread() {
76 return thread;
77 }
78
79 /**
80 * Return true if the Thread hasn't been resumed since this ThreadState
81 * was made.
82 */
83 public boolean isValid() {
84 return valid;
85 }
86
87 /**
88 * Return true if the thread is currently running a hook
89 * for this ThreadState
90 */
91 public boolean isRunningHook() {
92 return runningHook;
93 }
94
95 /**
96 * partial list of thread states from sun.debug.ThreadInfo.
97 * XXX some of these don't apply.
98 */
99 public final static int THR_STATUS_UNKNOWN = 0x01;
100 public final static int THR_STATUS_ZOMBIE = 0x02;
101 public final static int THR_STATUS_RUNNING = 0x03;
102 public final static int THR_STATUS_SLEEPING = 0x04;
103 public final static int THR_STATUS_MONWAIT = 0x05;
104 public final static int THR_STATUS_CONDWAIT = 0x06;
105 public final static int THR_STATUS_SUSPENDED = 0x07;
106 public final static int THR_STATUS_BREAK = 0x08;
107
108 /**
109 * Get the state of the thread at the time it entered debug mode.
110 * This can't be modified directly.
111 */
112 public int getStatus() {
113 return status;
114 }
115
116 /**
117 * Get the count of the stackframes
118 */
119 public abstract int countStackFrames()
120 throws InvalidInfoException;
121 /**
122 * Get the 'top' stackframe; i.e. the one with the current instruction
123 */
124 public abstract StackFrameInfo getCurrentFrame()
125 throws InvalidInfoException;
126
127 /**
128 * Get the thread's stack as an array. stack[stack.length-1] is the
129 * current frame, and stack[0] is the beginning of the stack.
130 */
131 public synchronized StackFrameInfo[] getStack()
132 throws InvalidInfoException {
133 // XXX check valid?
134 if (stack == null) {
135 stack = new StackFrameInfo[countStackFrames()];
136 }
137
138 if (stack.length == 0)
139 return stack;
140
141 StackFrameInfo frame = getCurrentFrame();
142 stack[stack.length - 1] = frame;
143 for (int i = stack.length - 2; i >= 0; i--) {
144 frame = frame.getCaller();
145 stack[i] = frame;
146 }
147
148 // should really be read-only for safety
149 return stack;
150 }
151
152 /**
153 * Leave the thread in a suspended state when the hook method(s)
154 * finish. This can be undone by calling resume(). This is the
155 * default only if the break was the result of
156 * DebugController.sendInterrupt().
157 */
158 public void leaveSuspended() {
159 resumeWhenDone = false;
160 }
161
162 /**
163 * Resume the thread. This is the default unless the break was the result
164 * of DebugController.sendInterrupt(). This method may be called from a
165 * hook method, in which case the thread will resume when the
166 * method returns.
167 * Alternatively, if there is no active hook method and
168 * the thread is suspended around in the DebugFrame, this resumes it
169 * immediately.
170 */
171 public synchronized void resume() {
172 if (runningHook)
173 resumeWhenDone = true;
174 else
175 resume0();
176 }
177
178 protected abstract void resume0();
179
180 /**
181 * if the continueState is DEAD, the thread cannot
182 * be restarted.
183 */
184 public final static int DEBUG_STATE_DEAD = 0x01;
185
186 /**
187 * if the continueState is RUN, the thread will
188 * proceed to the next program counter value when it resumes.
189 */
190 public final static int DEBUG_STATE_RUN = 0x02;
191
192 /**
193 * if the continueState is RETURN, the thread will
194 * return from the current method with the value in getReturnValue()
195 * when it resumes.
196 */
197 public final static int DEBUG_STATE_RETURN = 0x03;
198
199 /**
200 * if the continueState is THROW, the thread will
201 * throw an exception (accessible with getException()) when it
202 * resumes.
203 */
204 public final static int DEBUG_STATE_THROW = 0x04;
205
206 /**
207 * This gets the current continue state of the debug frame, which
208 * will be one of the DEBUG_STATE_* values above.
209 */
210 public int getContinueState() {
211 return continueState;
212 }
213
214 public int setContinueState(int state) {
215 int old = continueState;
216 continueState = state;
217 return old;
218 }
219
220 /**
221 * If the thread was stopped while in the process of returning
222 * a value, this call returns an object representing that value.
223 * non-Object values are wrapped as in the java.lang.reflect api.
224 * This is only relevant if the continue state is RETURN, and the
225 * method throws an IllegalStateException otherwise.
226 */
227 public Object getReturnValue() throws IllegalStateException {
228 if (continueState != DEBUG_STATE_RETURN)
229 throw new IllegalStateException("no value being returned");
230 return returnValue;
231 }
232
233 /**
234 * If the thread was stopped while in the process of throwing an
235 * exception, this call returns that exception.
236 * This is only relevant if the continue state is THROW, and it
237 * throws an IllegalStateException otherwise.
238 */
239 public Throwable getException() throws IllegalStateException {
240 if (continueState != DEBUG_STATE_THROW)
241 throw new IllegalStateException("no exception throw in progress");
242 return currentException;
243 }
244 }
245