mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-10 17:24:29 +00:00
- not built -
large changes to fix the following bugs: 82684, crash manually clearing breakpoint *actually* clearing mValid in jsdScript::Invalidate fixed this one. 85636, assertions on quiting venkman jsdService::Off now disconnects the hooks into JSD, to avoid calling back into js after that. It also processes any pending script delete events that occurred during the last GC. The code to process the gPendingScripts list has been factored out of the gc callback. Processing the dead script list allows us to properly finalize all of the jsdIScript object, which seems to clear up the "gc roots exist at shutdown" assertions. In effect, these changes get rid of *all* of the jsd related assertions on exit. Added isOn attribute to jsdIService. Added isValid attribute to jsdIScript. We now prefetch appropriate properties from the underlying JSDScript, so that it's available after the script is Invalidate()d moved jsdService constructor to jsd_xpc.h Save the runtime passed to OnForRuntime so we can use it to clear the GC Gallback in Off().
This commit is contained in:
parent
10a1f695af
commit
f40fe785c4
@ -43,7 +43,6 @@
|
||||
#include "nsIPref.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsString.h"
|
||||
#include "nsMemory.h"
|
||||
#include "jsdebug.h"
|
||||
#include "nspr.h"
|
||||
@ -54,6 +53,7 @@
|
||||
#include "nsIAppShell.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
|
||||
#define ASSERT_VALID_CONTEXT { if (!mCx) return NS_ERROR_NOT_AVAILABLE; }
|
||||
#define ASSERT_VALID_SCRIPT { if (!mValid) return NS_ERROR_NOT_AVAILABLE; }
|
||||
|
||||
#define JSDSERVICE_CID \
|
||||
@ -109,14 +109,9 @@ static struct DeadScript {
|
||||
* c callbacks
|
||||
*******************************************************************************/
|
||||
|
||||
static JSBool
|
||||
jsds_GCCallbackProc (JSContext *cx, JSGCStatus status)
|
||||
static void
|
||||
jsds_NotifyPendingDeadScripts ()
|
||||
{
|
||||
gGCStatus = status;
|
||||
#ifdef DEBUG
|
||||
printf ("new gc status is %i\n", status);
|
||||
#endif
|
||||
if (status == JSGC_END && gDeadScripts) {
|
||||
nsCOMPtr<jsdIScriptHook> hook = 0;
|
||||
gJsds->GetScriptHook (getter_AddRefs(hook));
|
||||
if (hook)
|
||||
@ -143,7 +138,17 @@ jsds_GCCallbackProc (JSContext *cx, JSGCStatus status)
|
||||
/* keep going until we catch up with our tail */
|
||||
}
|
||||
gDeadScripts = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
jsds_GCCallbackProc (JSContext *cx, JSGCStatus status)
|
||||
{
|
||||
gGCStatus = status;
|
||||
#ifdef DEBUG
|
||||
printf ("new gc status is %i\n", status);
|
||||
#endif
|
||||
if (status == JSGC_END && gDeadScripts)
|
||||
jsds_NotifyPendingDeadScripts ();
|
||||
|
||||
if (gLastGCProc)
|
||||
return gLastGCProc (cx, status);
|
||||
@ -220,6 +225,7 @@ jsds_ScriptHookProc (JSDContext* jsdc, JSDScript* jsdscript, JSBool creating,
|
||||
getter_AddRefs(jsdScript::FromPtr(jsdc, jsdscript));
|
||||
hook->OnScriptCreated (script);
|
||||
} else {
|
||||
|
||||
#ifdef DEBUG_verbose
|
||||
printf ("script deleted.\n");
|
||||
#endif
|
||||
@ -426,19 +432,32 @@ NS_IMETHODIMP
|
||||
jsdScript::Invalidate()
|
||||
{
|
||||
ASSERT_VALID_SCRIPT;
|
||||
mValid = PR_FALSE;
|
||||
|
||||
/* release the addref we do in FromPtr */
|
||||
jsdIScript *script = NS_STATIC_CAST(jsdIScript *,
|
||||
JSD_GetScriptPrivate(mScript));
|
||||
NS_ASSERTION (script == this, "That's not my script!");
|
||||
NS_RELEASE(script);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
jsdScript::GetIsValid(PRBool *_rval)
|
||||
{
|
||||
*_rval = mValid;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
jsdScript::GetIsActive(PRBool *_rval)
|
||||
{
|
||||
ASSERT_VALID_SCRIPT;
|
||||
if (!mValid) {
|
||||
*_rval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSD_LockScriptSubsystem(mCx);
|
||||
*_rval = JSD_IsActiveScript(mCx, mScript);
|
||||
JSD_UnlockScriptSubsystem(mCx);
|
||||
@ -448,40 +467,28 @@ jsdScript::GetIsActive(PRBool *_rval)
|
||||
NS_IMETHODIMP
|
||||
jsdScript::GetFileName(char **_rval)
|
||||
{
|
||||
ASSERT_VALID_SCRIPT;
|
||||
JSD_LockScriptSubsystem(mCx);
|
||||
*_rval = nsCString(JSD_GetScriptFilename(mCx, mScript)).ToNewCString();
|
||||
JSD_UnlockScriptSubsystem(mCx);
|
||||
*_rval = mFileName->ToNewCString();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
jsdScript::GetFunctionName(char **_rval)
|
||||
{
|
||||
ASSERT_VALID_SCRIPT;
|
||||
JSD_LockScriptSubsystem(mCx);
|
||||
*_rval = nsCString(JSD_GetScriptFunctionName(mCx, mScript)).ToNewCString();
|
||||
JSD_UnlockScriptSubsystem(mCx);
|
||||
*_rval = mFunctionName->ToNewCString();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
jsdScript::GetBaseLineNumber(PRUint32 *_rval)
|
||||
{
|
||||
ASSERT_VALID_SCRIPT;
|
||||
JSD_LockScriptSubsystem(mCx);
|
||||
*_rval = JSD_GetScriptBaseLineNumber(mCx, mScript);
|
||||
JSD_UnlockScriptSubsystem(mCx);
|
||||
*_rval = mBaseLineNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
jsdScript::GetLineExtent(PRUint32 *_rval)
|
||||
{
|
||||
ASSERT_VALID_SCRIPT;
|
||||
JSD_LockScriptSubsystem(mCx);
|
||||
*_rval = JSD_GetScriptLineExtent(mCx, mScript);
|
||||
JSD_UnlockScriptSubsystem(mCx);
|
||||
*_rval = mLineExtent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -862,12 +869,11 @@ jsdValue::Refresh()
|
||||
******************************************************************************/
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(jsdService, jsdIDebuggerService);
|
||||
|
||||
jsdService::jsdService() : mOn(PR_FALSE), mNestedLoopLevel(0), mCx(0),
|
||||
mBreakpointHook(0), mErrorHook(0),
|
||||
mDebuggerHook(0), mInterruptHook(0), mScriptHook(0),
|
||||
mThrowHook(0)
|
||||
NS_IMETHODIMP
|
||||
jsdService::GetIsOn (PRBool *_rval)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
*_rval = mOn;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -894,15 +900,33 @@ jsdService::On (void)
|
||||
NS_IMETHODIMP
|
||||
jsdService::OnForRuntime (JSRuntime *rt)
|
||||
{
|
||||
if (mOn)
|
||||
return (rt == mRuntime) ? NS_OK : NS_ERROR_ALREADY_INITIALIZED;
|
||||
|
||||
mRuntime = rt;
|
||||
|
||||
if (gLastGCProc == jsds_GCCallbackProc)
|
||||
/* condition indicates that the callback proc has not been set yet */
|
||||
gLastGCProc = JS_SetGCCallbackRT (rt, jsds_GCCallbackProc);
|
||||
|
||||
if (!mOn)
|
||||
mCx = JSD_DebuggerOnForUser (rt, NULL, NULL);
|
||||
if (!mCx)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
/* If any of these mFooHook objects are installed, do the required JSD
|
||||
* hookup now. See also, jsdService::SetFooHook().
|
||||
*/
|
||||
if (mThrowHook)
|
||||
JSD_SetThrowHook (mCx, jsds_ExecutionHookProc, NULL);
|
||||
if (mScriptHook)
|
||||
JSD_SetScriptHook (mCx, jsds_ScriptHookProc, NULL);
|
||||
if (mInterruptHook)
|
||||
JSD_SetInterruptHook (mCx, jsds_ExecutionHookProc, NULL);
|
||||
if (mDebuggerHook)
|
||||
JSD_SetDebuggerHook (mCx, jsds_ExecutionHookProc, NULL);
|
||||
if (mErrorHook)
|
||||
JSD_SetDebugBreakHook (mCx, jsds_ExecutionHookProc, NULL);
|
||||
|
||||
mOn = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
@ -911,8 +935,30 @@ jsdService::OnForRuntime (JSRuntime *rt)
|
||||
NS_IMETHODIMP
|
||||
jsdService::Off (void)
|
||||
{
|
||||
if (!mCx || !mRuntime)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (gDeadScripts)
|
||||
if (gGCStatus == JSGC_END)
|
||||
jsds_NotifyPendingDeadScripts();
|
||||
else
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
if (gLastGCProc != jsds_GCCallbackProc)
|
||||
JS_SetGCCallbackRT (mRuntime, gLastGCProc);
|
||||
|
||||
ClearAllBreakpoints();
|
||||
|
||||
JSD_SetThrowHook (mCx, NULL, NULL);
|
||||
JSD_SetScriptHook (mCx, NULL, NULL);
|
||||
JSD_SetInterruptHook (mCx, NULL, NULL);
|
||||
JSD_SetDebuggerHook (mCx, NULL, NULL);
|
||||
JSD_SetDebugBreakHook (mCx, NULL, NULL);
|
||||
|
||||
JSD_DebuggerOff (mCx);
|
||||
mCx = 0;
|
||||
|
||||
mCx = nsnull;
|
||||
mRuntime = nsnull;
|
||||
mOn = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -920,6 +966,8 @@ jsdService::Off (void)
|
||||
NS_IMETHODIMP
|
||||
jsdService::EnumerateScripts (jsdIScriptEnumerator *enumerator)
|
||||
{
|
||||
ASSERT_VALID_CONTEXT;
|
||||
|
||||
JSDScript *script;
|
||||
JSDScript *iter = NULL;
|
||||
PRBool cont_flag;
|
||||
@ -940,6 +988,8 @@ jsdService::EnumerateScripts (jsdIScriptEnumerator *enumerator)
|
||||
NS_IMETHODIMP
|
||||
jsdService::ClearAllBreakpoints (void)
|
||||
{
|
||||
ASSERT_VALID_CONTEXT;
|
||||
|
||||
JSD_LockScriptSubsystem(mCx);
|
||||
JSD_ClearAllExecutionHooks (mCx);
|
||||
JSD_UnlockScriptSubsystem(mCx);
|
||||
@ -1027,6 +1077,13 @@ NS_IMETHODIMP
|
||||
jsdService::SetErrorHook (jsdIExecutionHook *aHook)
|
||||
{
|
||||
mErrorHook = aHook;
|
||||
|
||||
/* if the debugger isn't initialized, that's all we can do for now. The
|
||||
* OnForRuntime() method will do the rest when the coast is clear.
|
||||
*/
|
||||
if (!mCx)
|
||||
return NS_OK;
|
||||
|
||||
if (aHook)
|
||||
JSD_SetDebugBreakHook (mCx, jsds_ExecutionHookProc, NULL);
|
||||
else
|
||||
@ -1048,6 +1105,13 @@ NS_IMETHODIMP
|
||||
jsdService::SetDebuggerHook (jsdIExecutionHook *aHook)
|
||||
{
|
||||
mDebuggerHook = aHook;
|
||||
|
||||
/* if the debugger isn't initialized, that's all we can do for now. The
|
||||
* OnForRuntime() method will do the rest when the coast is clear.
|
||||
*/
|
||||
if (!mCx)
|
||||
return NS_OK;
|
||||
|
||||
if (aHook)
|
||||
JSD_SetDebuggerHook (mCx, jsds_ExecutionHookProc, NULL);
|
||||
else
|
||||
@ -1069,6 +1133,13 @@ NS_IMETHODIMP
|
||||
jsdService::SetInterruptHook (jsdIExecutionHook *aHook)
|
||||
{
|
||||
mInterruptHook = aHook;
|
||||
|
||||
/* if the debugger isn't initialized, that's all we can do for now. The
|
||||
* OnForRuntime() method will do the rest when the coast is clear.
|
||||
*/
|
||||
if (!mCx)
|
||||
return NS_OK;
|
||||
|
||||
if (aHook)
|
||||
JSD_SetInterruptHook (mCx, jsds_ExecutionHookProc, NULL);
|
||||
else
|
||||
@ -1090,6 +1161,13 @@ NS_IMETHODIMP
|
||||
jsdService::SetScriptHook (jsdIScriptHook *aHook)
|
||||
{
|
||||
mScriptHook = aHook;
|
||||
|
||||
/* if the debugger isn't initialized, that's all we can do for now. The
|
||||
* OnForRuntime() method will do the rest when the coast is clear.
|
||||
*/
|
||||
if (!mCx)
|
||||
return NS_OK;
|
||||
|
||||
if (aHook)
|
||||
JSD_SetScriptHook (mCx, jsds_ScriptHookProc, NULL);
|
||||
else
|
||||
@ -1111,6 +1189,13 @@ NS_IMETHODIMP
|
||||
jsdService::SetThrowHook (jsdIExecutionHook *aHook)
|
||||
{
|
||||
mThrowHook = aHook;
|
||||
|
||||
/* if the debugger isn't initialized, that's all we can do for now. The
|
||||
* OnForRuntime() method will do the rest when the coast is clear.
|
||||
*/
|
||||
if (!mCx)
|
||||
return NS_OK;
|
||||
|
||||
if (aHook)
|
||||
JSD_SetThrowHook (mCx, jsds_ExecutionHookProc, NULL);
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user