bug 124474, "add native frame support to jsd"

sr=shaver, r=jband
add JSD_IsStackFrameNative, IsStackFrameDebugger, and IsStackFrameConstructing
add similar attributes to jsdIStackFrame
tweak return values in jsds_FilterHook
don't include dummy stack frames in threadstates

bug 110387, "Crash on exiting venkman"
check to see if the debugger was turned off before going through with an unPause.
This commit is contained in:
rginda%netscape.com 2002-02-14 07:57:30 +00:00
Родитель 6564fd58e3
Коммит 605e3a0d2e
7 изменённых файлов: 331 добавлений и 40 удалений

Просмотреть файл

@ -118,6 +118,16 @@ interface jsdIDebuggerService : nsISupports
*/
attribute jsdICallHook functionHook;
/**
* Link native frames in call stacks.
*/
const unsigned long ENABLE_NATIVE_FRAMES = 0x01;
/**
* Debugger service flags.
*/
attribute unsigned long flags;
/**
* |true| if the debugger should register an app-start observer in order
* to begin collecting debug information when mozilla is launched.
@ -618,6 +628,20 @@ interface jsdIStackFrame : jsdIEphemeral
/** Internal use only. */
[noscript] readonly attribute JSDStackFrameInfo JSDStackFrameInfo;
/**
* True if stack frame represents a native frame.
*/
readonly attribute boolean isNative;
/**
* True if stack frame represents a frame created as a result of a debugger
* evaluation.
*/
readonly attribute boolean isDebugger;
/**
* True if stack frame is constructing a new object.
*/
readonly attribute boolean isConstructing;
/**
* Link to the caller's stack frame.
*/
@ -627,7 +651,11 @@ interface jsdIStackFrame : jsdIEphemeral
*/
readonly attribute jsdIContext executionContext;
/**
* Script running in this stack frame.
* Function name executing in this stack frame.
*/
readonly attribute string functionName;
/**
* Script running in this stack frame, null for native frames.
*/
readonly attribute jsdIScript script;
/**

Просмотреть файл

@ -130,6 +130,7 @@ struct JSDContext
JSCList links; /* we are part of a JSCList */
JSBool inited;
void* data;
uint32 flags;
JSD_ScriptHookProc scriptHook;
void* scriptHookData;
JSD_ExecutionHookProc interruptHook;
@ -620,11 +621,31 @@ jsd_GetScopeChainForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSBool
jsd_IsStackFrameNative(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSBool
jsd_IsStackFrameDebugger(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSBool
jsd_IsStackFrameConstructing(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSDValue*
jsd_GetThisForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern const char*
jsd_GetNameForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSDThreadState*
jsd_NewThreadState(JSDContext* jsdc, JSContext *cx);

Просмотреть файл

@ -63,13 +63,16 @@ _addNewFrame(JSDContext* jsdc,
JSStackFrame* fp)
{
JSDStackFrameInfo* jsdframe;
JSDScript* jsdscript;
JSDScript* jsdscript = NULL;
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindJSDScript(jsdc, script);
JSD_UNLOCK_SCRIPTS(jsdc);
if( ! jsdscript )
return NULL;
if (!JS_IsNativeFrame(jsdthreadstate->context, fp))
{
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindJSDScript(jsdc, script);
JSD_UNLOCK_SCRIPTS(jsdc);
if( ! jsdscript )
return NULL;
}
jsdframe = (JSDStackFrameInfo*) calloc(1, sizeof(JSDStackFrameInfo));
if( ! jsdframe )
@ -116,10 +119,17 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
JSScript* script = JS_GetFrameScript(cx, fp);
jsuword pc = (jsuword) JS_GetFramePC(cx, fp);
if( ! script || ! pc || JS_IsNativeFrame(cx, fp) )
continue;
_addNewFrame( jsdc, jsdthreadstate, script, pc, fp );
/*
* don't construct a JSDStackFrame for dummy frames (those without a
* |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
* isn't set.
*/
if (JS_GetFrameThis(cx, fp) &&
((jsdc->flags & JSD_INCLUDE_NATIVE_FRAMES) ||
!JS_IsNativeFrame(cx, fp)))
{
_addNewFrame( jsdc, jsdthreadstate, script, pc, fp );
}
}
/* if there is no stack, then this threadstate can not be constructed */
@ -303,7 +313,6 @@ jsd_GetThisForStackFrame(JSDContext* jsdc,
{
JSObject* obj;
JSDValue* jsdval = NULL;
JSD_LOCK_THREADSTATES(jsdc);
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
@ -314,10 +323,82 @@ jsd_GetThisForStackFrame(JSDContext* jsdc,
}
JSD_UNLOCK_THREADSTATES(jsdc);
return jsdval;
}
const char*
jsd_GetNameForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe)
{
const char *rv = NULL;
JSD_LOCK_THREADSTATES(jsdc);
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
JSFunction *fun = JS_GetFrameFunction (jsdthreadstate->context,
jsdframe->fp);
if (fun)
rv = JS_GetFunctionName (fun);
}
JSD_UNLOCK_THREADSTATES(jsdc);
return rv;
}
JSBool
jsd_IsStackFrameNative(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe)
{
JSBool rv;
JSD_LOCK_THREADSTATES(jsdc);
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
rv = JS_IsNativeFrame(jsdthreadstate->context, jsdframe->fp);
}
JSD_UNLOCK_THREADSTATES(jsdc);
return rv;
}
JSBool
jsd_IsStackFrameDebugger(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe)
{
JSBool rv = JS_TRUE;
JSD_LOCK_THREADSTATES(jsdc);
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
rv = JS_IsDebuggerFrame(jsdthreadstate->context, jsdframe->fp);
}
JSD_UNLOCK_THREADSTATES(jsdc);
return rv;
}
JSBool
jsd_IsStackFrameConstructing(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe)
{
JSBool rv = JS_TRUE;
JSD_LOCK_THREADSTATES(jsdc);
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
{
rv = JS_IsConstructorFrame(jsdthreadstate->context, jsdframe->fp);
}
JSD_UNLOCK_THREADSTATES(jsdc);
return rv;
}
JSBool
jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,

Просмотреть файл

@ -89,7 +89,7 @@ _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
buf = JS_smprintf("%sentering %s %s this: %0x\n",
_indentSpaces(indent++),
funName,
JS_IsContructorFrame(cx, fp) ? "constructing":"",
JS_IsConstructorFrame(cx, fp) ? "constructing":"",
(int)JS_GetFrameThis(cx, fp));
}
else
@ -119,7 +119,7 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
if (!jsdc || !jsdc->inited)
return JS_FALSE;
if (before && JS_IsContructorFrame(cx, fp))
if (before && JS_IsConstructorFrame(cx, fp))
jsd_Constructing(jsdc, cx, JS_GetFrameThis(cx, fp), fp);
if (hook)

Просмотреть файл

@ -358,29 +358,24 @@ jsds_FindFilter (jsdIFilter *filter)
PRBool
jsds_FilterHook (JSDContext *jsdc, JSDThreadState *state)
{
if (!gFilters)
return PR_TRUE;
JSContext *cx = JSD_GetJSContext (jsdc, state);
void *glob = NS_STATIC_CAST(void *, JS_GetGlobalObject (cx));
if (!glob) {
NS_WARNING("No global in threadstate");
return PR_TRUE;
return PR_FALSE;
}
JSDStackFrameInfo *frame = JSD_GetStackFrame (jsdc, state);
if (!frame) {
NS_WARNING("No frame in threadstate");
return PR_TRUE;
return PR_FALSE;
}
JSDScript *script = JSD_GetScriptForStackFrame (jsdc, state, frame);
if (!script) {
NS_WARNING("No script in threadstate");
if (!script)
return PR_TRUE;
}
jsuint pc = JSD_GetPCForStackFrame (jsdc, state, frame);
if (!pc) {
@ -388,13 +383,16 @@ jsds_FilterHook (JSDContext *jsdc, JSDThreadState *state)
return PR_TRUE;
}
PRUint32 currentLine = JSD_GetClosestLine (jsdc, script, pc);
if (!currentLine) {
NS_WARNING("Can't convert pc to line");
return PR_TRUE;
const char *url = JSD_GetScriptFilename (jsdc, script);
if (!url) {
NS_WARNING ("Script with no filename");
return PR_FALSE;
}
const char *url = nsnull;
if (!gFilters)
return PR_TRUE;
PRUint32 currentLine = JSD_GetClosestLine (jsdc, script, pc);
PRUint32 len = 0;
FilterRecord *currentFilter = gFilters;
do {
@ -416,11 +414,8 @@ jsds_FilterHook (JSDContext *jsdc, JSDThreadState *state)
if (currentFilter->patternType == ptIgnore)
return flags & jsdIFilter::FLAG_PASS;
if (!url) {
url = JSD_GetScriptFilename (jsdc, script);
NS_ASSERTION (url, "Script with no filename");
if (!len)
len = PL_strlen(url);
}
if (len >= currentFilter->patternLength) {
switch (currentFilter->patternType) {
@ -1523,6 +1518,48 @@ jsdStackFrame::GetExecutionContext(jsdIContext **_rval)
return NS_OK;
}
NS_IMETHODIMP
jsdStackFrame::GetFunctionName(char **_rval)
{
ASSERT_VALID_EPHEMERAL;
const char *name = JSD_GetNameForStackFrame(mCx, mThreadState,
mStackFrameInfo);
if (!name)
{
/* top level scripts have no function name */
*_rval = nsnull;
return NS_OK;
}
*_rval = ToNewCString(nsDependentCString(name));
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
jsdStackFrame::GetIsNative(PRBool *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_IsStackFrameNative (mCx, mThreadState, mStackFrameInfo);
return NS_OK;
}
NS_IMETHODIMP
jsdStackFrame::GetIsDebugger(PRBool *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_IsStackFrameDebugger (mCx, mThreadState, mStackFrameInfo);
return NS_OK;
}
NS_IMETHODIMP
jsdStackFrame::GetIsConstructing(PRBool *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_IsStackFrameConstructing (mCx, mThreadState, mStackFrameInfo);
return NS_OK;
}
NS_IMETHODIMP
jsdStackFrame::GetScript(jsdIScript **_rval)
{
@ -1539,9 +1576,9 @@ jsdStackFrame::GetPc(PRUint32 *_rval)
ASSERT_VALID_EPHEMERAL;
JSDScript *script = JSD_GetScriptForStackFrame (mCx, mThreadState,
mStackFrameInfo);
jsuword pcbase = JSD_GetClosestPC(mCx, script, 0);
if (!script)
return NS_ERROR_FAILURE;
jsuword pcbase = JSD_GetClosestPC(mCx, script, 0);
jsuword pc = JSD_GetPCForStackFrame (mCx, mThreadState, mStackFrameInfo);
*_rval = pc - pcbase;
@ -1554,8 +1591,14 @@ jsdStackFrame::GetLine(PRUint32 *_rval)
ASSERT_VALID_EPHEMERAL;
JSDScript *script = JSD_GetScriptForStackFrame (mCx, mThreadState,
mStackFrameInfo);
jsuword pc = JSD_GetPCForStackFrame (mCx, mThreadState, mStackFrameInfo);
*_rval = JSD_GetClosestLine (mCx, script, pc);
if (script) {
jsuword pc = JSD_GetPCForStackFrame (mCx, mThreadState, mStackFrameInfo);
*_rval = JSD_GetClosestLine (mCx, script, pc);
} else {
if (!JSD_IsStackFrameNative(mCx, mThreadState, mStackFrameInfo))
return NS_ERROR_FAILURE;
*_rval = 1;
}
return NS_OK;
}
@ -1815,8 +1858,15 @@ NS_IMETHODIMP
jsdValue::GetJsFunctionName(char **_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval =
ToNewCString(nsDependentCString(JSD_GetValueFunctionName(mCx, mValue)));
const char *name = JSD_GetValueFunctionName(mCx, mValue);
if (!name)
{
/* top level scripts have no function name */
*_rval = nsnull;
return NS_OK;
}
*_rval = ToNewCString(nsDependentCString(*_rval));
if (!*_rval)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
@ -2082,6 +2132,19 @@ jsdService::SetInitAtStartup (PRBool state)
return NS_OK;
}
NS_IMETHODIMP
jsdService::GetFlags (PRUint32 *_rval)
{
*_rval = JSD_GetContextFlags (mCx);
return NS_OK;
}
NS_IMETHODIMP
jsdService::SetFlags (PRUint32 flags)
{
JSD_SetContextFlags (mCx, flags);
return NS_OK;
}
NS_IMETHODIMP
jsdService::GetIsOn (PRBool *_rval)
@ -2253,7 +2316,10 @@ jsdService::UnPause(PRUint32 *_rval)
if (mPauseLevel == 0)
return NS_ERROR_NOT_AVAILABLE;
if (--mPauseLevel == 0) {
/* check mOn before we muck with this stuff, it's possible the debugger
* was turned off while we were paused.
*/
if (--mPauseLevel == 0 && mOn) {
if (mErrorHook)
JSD_SetErrorReporter (mCx, jsds_ErrorHookProc, NULL);
if (mThrowHook)

Просмотреть файл

@ -112,6 +112,20 @@ JSD_GetContextPrivate(JSDContext *jsdc)
return jsd_GetContextPrivate (jsdc);
}
JSD_PUBLIC_API(void)
JSD_SetContextFlags(JSDContext *jsdc, uint32 flags)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
jsdc->flags = flags;
}
JSD_PUBLIC_API(uint32)
JSD_GetContextFlags(JSDContext *jsdc)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsdc->flags;
}
JSD_PUBLIC_API(JSDContext*)
JSD_JSDContextForJSContext(JSContext* context)
{
@ -623,6 +637,42 @@ JSD_GetThisForStackFrame(JSDContext* jsdc,
return jsd_GetThisForStackFrame(jsdc, jsdthreadstate, jsdframe);
}
JSD_PUBLIC_API(const char*)
JSD_GetNameForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetNameForStackFrame(jsdc, jsdthreadstate, jsdframe);
}
JSD_PUBLIC_API(JSBool)
JSD_IsStackFrameNative(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_IsStackFrameNative(jsdc, jsdthreadstate, jsdframe);
}
JSD_PUBLIC_API(JSBool)
JSD_IsStackFrameDebugger(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_IsStackFrameDebugger(jsdc, jsdthreadstate, jsdframe);
}
JSD_PUBLIC_API(JSBool)
JSD_IsStackFrameConstructing(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_IsStackFrameConstructing(jsdc, jsdthreadstate, jsdframe);
}
JSD_PUBLIC_API(JSBool)
JSD_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,

Просмотреть файл

@ -179,6 +179,17 @@ JSD_SetContextPrivate(JSDContext *jsdc, void *data);
extern JSD_PUBLIC_API(void *)
JSD_GetContextPrivate(JSDContext *jsdc);
/*
* Context flags.
*/
#define JSD_INCLUDE_NATIVE_FRAMES 0x1
extern JSD_PUBLIC_API(void)
JSD_SetContextFlags (JSDContext* jsdc, uint32 flags);
extern JSD_PUBLIC_API(uint32)
JSD_GetContextFlags (JSDContext* jsdc);
/*
* Notify JSD that this JSContext is 'in use'. This allows JSD to hook the
* ErrorReporter. For the most part this is done automatically whenever
@ -793,6 +804,40 @@ JSD_GetThisForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
/*
* Get the name of the function executing in this stack frame. Especially useful
* for native frames (without script objects.)
*/
extern JSD_PUBLIC_API(const char*)
JSD_GetNameForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
/*
* True if stack frame represents a native frame.
*/
extern JSD_PUBLIC_API(JSBool)
JSD_IsStackFrameNative(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
/*
* True if stack frame represents a frame created as a result of a debugger
* evaluation.
*/
extern JSD_PUBLIC_API(JSBool)
JSD_IsStackFrameDebugger(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
/*
* True if stack frame is constructing a new object.
*/
extern JSD_PUBLIC_API(JSBool)
JSD_IsStackFrameConstructing(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
/*
* Evaluate the given unicode source code in the context of the given stack frame.
* returns JS_TRUE and puts result in rval on success, JS_FALSE on failure.