зеркало из https://github.com/mozilla/pjs.git
246 строки
7.5 KiB
Java
246 строки
7.5 KiB
Java
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
package netscape.jsdebug;
|
|
|
|
/*
|
|
* jband - 03/19/97
|
|
*
|
|
* This is an 'abstracted version of netscape.debug.ThreadState
|
|
*
|
|
* The methods that were 'native' there are 'abstract' here.
|
|
* Changed 'private' data to 'protected' (though native access is immune)
|
|
* Changed 'private' resume0() to 'protected'
|
|
* Removed ThreadHook referneces
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* When a hook is hit, the debugger records the state of the
|
|
* thread before the hook in a ThreadState object. This object
|
|
* is then passed to any hook methods that are called, and can
|
|
* be used to change the state of the thread when it resumes from the
|
|
* hook.
|
|
*
|
|
* @author John Bandhauer
|
|
* @author Nick Thompson
|
|
* @version 1.0
|
|
* @since 1.0
|
|
*/
|
|
public abstract class ThreadStateBase {
|
|
protected Thread thread;
|
|
protected boolean valid;
|
|
protected boolean runningHook;
|
|
protected boolean resumeWhenDone;
|
|
protected int status;
|
|
protected int continueState;
|
|
protected StackFrameInfo[] stack; /* jband - 03/19/97 - had no access modifier */
|
|
protected Object returnValue;
|
|
protected Throwable currentException;
|
|
protected int currentFramePtr; /* used internally */
|
|
protected ThreadStateBase previous;
|
|
|
|
/**
|
|
* <B><font color="red">Not Implemented.</font></B>
|
|
* Always throws <code>InternalError("unimplemented")</code>
|
|
*/
|
|
public static ThreadStateBase getThreadState(Thread t)
|
|
throws InvalidInfoException
|
|
{
|
|
throw new InternalError("unimplemented");
|
|
}
|
|
|
|
/**
|
|
* Get the Thread that this ThreadState came from.
|
|
*/
|
|
public Thread getThread() {
|
|
return thread;
|
|
}
|
|
|
|
/**
|
|
* Return true if the Thread hasn't been resumed since this ThreadState
|
|
* was made.
|
|
*/
|
|
public boolean isValid() {
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
* Return true if the thread is currently running a hook
|
|
* for this ThreadState
|
|
*/
|
|
public boolean isRunningHook() {
|
|
return runningHook;
|
|
}
|
|
|
|
/**
|
|
* partial list of thread states from sun.debug.ThreadInfo.
|
|
* XXX some of these don't apply.
|
|
*/
|
|
public final static int THR_STATUS_UNKNOWN = 0x01;
|
|
public final static int THR_STATUS_ZOMBIE = 0x02;
|
|
public final static int THR_STATUS_RUNNING = 0x03;
|
|
public final static int THR_STATUS_SLEEPING = 0x04;
|
|
public final static int THR_STATUS_MONWAIT = 0x05;
|
|
public final static int THR_STATUS_CONDWAIT = 0x06;
|
|
public final static int THR_STATUS_SUSPENDED = 0x07;
|
|
public final static int THR_STATUS_BREAK = 0x08;
|
|
|
|
/**
|
|
* Get the state of the thread at the time it entered debug mode.
|
|
* This can't be modified directly.
|
|
*/
|
|
public int getStatus() {
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* Get the count of the stackframes
|
|
*/
|
|
public abstract int countStackFrames()
|
|
throws InvalidInfoException;
|
|
/**
|
|
* Get the 'top' stackframe; i.e. the one with the current instruction
|
|
*/
|
|
public abstract StackFrameInfo getCurrentFrame()
|
|
throws InvalidInfoException;
|
|
|
|
/**
|
|
* Get the thread's stack as an array. stack[stack.length-1] is the
|
|
* current frame, and stack[0] is the beginning of the stack.
|
|
*/
|
|
public synchronized StackFrameInfo[] getStack()
|
|
throws InvalidInfoException {
|
|
// XXX check valid?
|
|
if (stack == null) {
|
|
stack = new StackFrameInfo[countStackFrames()];
|
|
}
|
|
|
|
if (stack.length == 0)
|
|
return stack;
|
|
|
|
StackFrameInfo frame = getCurrentFrame();
|
|
stack[stack.length - 1] = frame;
|
|
for (int i = stack.length - 2; i >= 0; i--) {
|
|
frame = frame.getCaller();
|
|
stack[i] = frame;
|
|
}
|
|
|
|
// should really be read-only for safety
|
|
return stack;
|
|
}
|
|
|
|
/**
|
|
* Leave the thread in a suspended state when the hook method(s)
|
|
* finish. This can be undone by calling resume(). This is the
|
|
* default only if the break was the result of
|
|
* DebugController.sendInterrupt().
|
|
*/
|
|
public void leaveSuspended() {
|
|
resumeWhenDone = false;
|
|
}
|
|
|
|
/**
|
|
* Resume the thread. This is the default unless the break was the result
|
|
* of DebugController.sendInterrupt(). This method may be called from a
|
|
* hook method, in which case the thread will resume when the
|
|
* method returns.
|
|
* Alternatively, if there is no active hook method and
|
|
* the thread is suspended around in the DebugFrame, this resumes it
|
|
* immediately.
|
|
*/
|
|
public synchronized void resume() {
|
|
if (runningHook)
|
|
resumeWhenDone = true;
|
|
else
|
|
resume0();
|
|
}
|
|
|
|
protected abstract void resume0();
|
|
|
|
/**
|
|
* if the continueState is DEAD, the thread cannot
|
|
* be restarted.
|
|
*/
|
|
public final static int DEBUG_STATE_DEAD = 0x01;
|
|
|
|
/**
|
|
* if the continueState is RUN, the thread will
|
|
* proceed to the next program counter value when it resumes.
|
|
*/
|
|
public final static int DEBUG_STATE_RUN = 0x02;
|
|
|
|
/**
|
|
* if the continueState is RETURN, the thread will
|
|
* return from the current method with the value in getReturnValue()
|
|
* when it resumes.
|
|
*/
|
|
public final static int DEBUG_STATE_RETURN = 0x03;
|
|
|
|
/**
|
|
* if the continueState is THROW, the thread will
|
|
* throw an exception (accessible with getException()) when it
|
|
* resumes.
|
|
*/
|
|
public final static int DEBUG_STATE_THROW = 0x04;
|
|
|
|
/**
|
|
* This gets the current continue state of the debug frame, which
|
|
* will be one of the DEBUG_STATE_* values above.
|
|
*/
|
|
public int getContinueState() {
|
|
return continueState;
|
|
}
|
|
|
|
public int setContinueState(int state) {
|
|
int old = continueState;
|
|
continueState = state;
|
|
return old;
|
|
}
|
|
|
|
/**
|
|
* If the thread was stopped while in the process of returning
|
|
* a value, this call returns an object representing that value.
|
|
* non-Object values are wrapped as in the java.lang.reflect api.
|
|
* This is only relevant if the continue state is RETURN, and the
|
|
* method throws an IllegalStateException otherwise.
|
|
*/
|
|
public Object getReturnValue() throws IllegalStateException {
|
|
if (continueState != DEBUG_STATE_RETURN)
|
|
throw new IllegalStateException("no value being returned");
|
|
return returnValue;
|
|
}
|
|
|
|
/**
|
|
* If the thread was stopped while in the process of throwing an
|
|
* exception, this call returns that exception.
|
|
* This is only relevant if the continue state is THROW, and it
|
|
* throws an IllegalStateException otherwise.
|
|
*/
|
|
public Throwable getException() throws IllegalStateException {
|
|
if (continueState != DEBUG_STATE_THROW)
|
|
throw new IllegalStateException("no exception throw in progress");
|
|
return currentException;
|
|
}
|
|
}
|
|
|