Bug 534120. When jsd is paused unhook as much as we can, so we don't interfere with the jit. r=timeless, jorendorff.
authorBoris Zbarsky <bzbarsky@mit.edu>
Sat, 12 Dec 2009 13:35:04 -0800
changeset 35647 119c8036630f15cb4c9bbc051fa9a59e25e742c8
parent 35646 a59c83eda97b21d137aa9c941477189462e53fc8
child 35648 e12ccfe8c5a7cceace95fba2c7c8c467e0d6f43f
push idunknown
push userunknown
push dateunknown
reviewerstimeless, jorendorff
bugs534120
milestone1.9.3a1pre
Bug 534120. When jsd is paused unhook as much as we can, so we don't interfere with the jit. r=timeless, jorendorff.
js/jsd/jsd.h
js/jsd/jsd_high.c
js/jsd/jsd_xpc.cpp
js/jsd/jsdebug.c
js/jsd/jsdebug.h
--- a/js/jsd/jsd.h
+++ b/js/jsd/jsd.h
@@ -343,16 +343,22 @@ jsd_DebuggerOnForUser(JSRuntime*        
                       void*              user);
 extern JSDContext*
 jsd_DebuggerOn(void);
 
 extern void
 jsd_DebuggerOff(JSDContext* jsdc);
 
 extern void
+jsd_DebuggerPause(JSDContext* jsdc, JSBool forceAllHooksOff);
+
+extern void
+jsd_DebuggerUnpause(JSDContext* jsdc);
+
+extern void
 jsd_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user);
 
 extern JSDContext*
 jsd_JSDContextForJSContext(JSContext* context);
 
 extern void*
 jsd_SetContextPrivate(JSDContext* jsdc, void *data);
 
--- a/js/jsd/jsd_high.c
+++ b/js/jsd/jsd_high.c
@@ -198,25 +198,29 @@ jsd_DebuggerOnForUser(JSRuntime*        
 {
     JSDContext* jsdc;
     JSContext* iter = NULL;
 
     jsdc = _newJSDContext(jsrt, callbacks, user);
     if( ! jsdc )
         return NULL;
 
-    /* set hooks here */
+    /*
+     * Set hooks here.  The new/destroy script hooks are on even when
+     * the debugger is paused.  The destroy hook so we'll clean up
+     * internal data structures when scripts are destroyed, and the
+     * newscript hook for backwards compatibility for now.  We'd like
+     * to stop doing that.
+     */
     JS_SetNewScriptHookProc(jsdc->jsrt, jsd_NewScriptHookProc, jsdc);
     JS_SetDestroyScriptHookProc(jsdc->jsrt, jsd_DestroyScriptHookProc, jsdc);
-    JS_SetDebuggerHandler(jsdc->jsrt, jsd_DebuggerHandler, jsdc);
-    JS_SetExecuteHook(jsdc->jsrt, jsd_TopLevelCallHook, jsdc);
-    JS_SetCallHook(jsdc->jsrt, jsd_FunctionCallHook, jsdc);
-    JS_SetObjectHook(jsdc->jsrt, jsd_ObjectHook, jsdc);
-    JS_SetThrowHook(jsdc->jsrt, jsd_ThrowHandler, jsdc);
-    JS_SetDebugErrorHook(jsdc->jsrt, jsd_DebugErrorHook, jsdc);
+    jsd_DebuggerUnpause(jsdc);
+    if (!(jsdc->flags & JSD_DISABLE_OBJECT_TRACE)) {
+        JS_SetObjectHook(jsdc->jsrt, jsd_ObjectHook, jsdc);
+    }
 #ifdef LIVEWIRE
     LWDBG_SetNewScriptHookProc(jsd_NewScriptHookProc, jsdc);
 #endif
     if( jsdc->userCallbacks.setContext )
         jsdc->userCallbacks.setContext(jsdc, jsdc->user);
     return jsdc;
 }
 
@@ -226,25 +230,23 @@ jsd_DebuggerOn(void)
     JS_ASSERT(_jsrt);
     JS_ASSERT(_validateUserCallbacks(&_callbacks));
     return jsd_DebuggerOnForUser(_jsrt, &_callbacks, _user);
 }
 
 void
 jsd_DebuggerOff(JSDContext* jsdc)
 {
+    jsd_DebuggerPause(jsdc, JS_TRUE);
     /* clear hooks here */
     JS_SetNewScriptHookProc(jsdc->jsrt, NULL, NULL);
     JS_SetDestroyScriptHookProc(jsdc->jsrt, NULL, NULL);
-    JS_SetDebuggerHandler(jsdc->jsrt, NULL, NULL);
-    JS_SetExecuteHook(jsdc->jsrt, NULL, NULL);
-    JS_SetCallHook(jsdc->jsrt, NULL, NULL);
+    /* Have to unset these too, since jsd_DebuggerPause only unsets
+       them conditionally */
     JS_SetObjectHook(jsdc->jsrt, NULL, NULL);
-    JS_SetThrowHook(jsdc->jsrt, NULL, NULL);
-    JS_SetDebugErrorHook(jsdc->jsrt, NULL, NULL);
 #ifdef LIVEWIRE
     LWDBG_SetNewScriptHookProc(NULL,NULL);
 #endif
 
     /* clean up */
     JSD_LockScriptSubsystem(jsdc);
     jsd_DestroyScriptManager(jsdc);
     JSD_UnlockScriptSubsystem(jsdc);
@@ -252,16 +254,40 @@ jsd_DebuggerOff(JSDContext* jsdc)
     
     _destroyJSDContext(jsdc);
 
     if( jsdc->userCallbacks.setContext )
         jsdc->userCallbacks.setContext(NULL, jsdc->user);
 }
 
 void
+jsd_DebuggerPause(JSDContext* jsdc, JSBool forceAllHooksOff)
+{
+    JS_SetDebuggerHandler(jsdc->jsrt, NULL, NULL);
+    if (forceAllHooksOff ||
+        (!(jsdc->flags & JSD_COLLECT_PROFILE_DATA) &&
+         (jsdc->flags & JSD_DISABLE_OBJECT_TRACE))) {
+        JS_SetExecuteHook(jsdc->jsrt, NULL, NULL);
+        JS_SetCallHook(jsdc->jsrt, NULL, NULL);
+    }
+    JS_SetThrowHook(jsdc->jsrt, NULL, NULL);
+    JS_SetDebugErrorHook(jsdc->jsrt, NULL, NULL);
+}
+
+void
+jsd_DebuggerUnpause(JSDContext* jsdc)
+{
+    JS_SetDebuggerHandler(jsdc->jsrt, jsd_DebuggerHandler, jsdc);
+    JS_SetExecuteHook(jsdc->jsrt, jsd_TopLevelCallHook, jsdc);
+    JS_SetCallHook(jsdc->jsrt, jsd_FunctionCallHook, jsdc);
+    JS_SetThrowHook(jsdc->jsrt, jsd_ThrowHandler, jsdc);
+    JS_SetDebugErrorHook(jsdc->jsrt, jsd_DebugErrorHook, jsdc);
+}
+
+void
 jsd_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user)
 {
     _jsrt = jsrt;
     _user = user;
 
 #ifdef JSD_HAS_DANGEROUS_THREAD
     _dangerousThread = JSD_CURRENT_THREAD();
 #endif
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -2651,16 +2651,17 @@ jsdService::Pause(PRUint32 *_rval)
     if (++mPauseLevel == 1) {
         JSD_SetErrorReporter (mCx, NULL, NULL);
         JSD_ClearThrowHook (mCx);
         JSD_ClearInterruptHook (mCx);
         JSD_ClearDebuggerHook (mCx);
         JSD_ClearDebugBreakHook (mCx);
         JSD_ClearTopLevelHook (mCx);
         JSD_ClearFunctionHook (mCx);
+        JSD_DebuggerPause (mCx);
     }
 
     if (_rval)
         *_rval = mPauseLevel;
 
     return NS_OK;
 }
 
@@ -2672,16 +2673,17 @@ jsdService::UnPause(PRUint32 *_rval)
 
     if (mPauseLevel == 0)
         return NS_ERROR_NOT_AVAILABLE;
 
     /* check mOn before we muck with this stuff, it's possible the debugger
      * was turned off while we were paused.
      */
     if (--mPauseLevel == 0 && mOn) {
+        JSD_DebuggerUnpause (mCx);
         if (mErrorHook)
             JSD_SetErrorReporter (mCx, jsds_ErrorHookProc, NULL);
         if (mThrowHook)
             JSD_SetThrowHook (mCx, jsds_ExecutionHookProc, NULL);
         if (mInterruptHook)
             JSD_SetInterruptHook (mCx, jsds_ExecutionHookProc, NULL);
         if (mDebuggerHook)
             JSD_SetDebuggerHook (mCx, jsds_ExecutionHookProc, NULL);
--- a/js/jsd/jsdebug.c
+++ b/js/jsd/jsdebug.c
@@ -60,16 +60,29 @@ JSD_DebuggerOn(void)
 
 JSD_PUBLIC_API(void)
 JSD_DebuggerOff(JSDContext* jsdc)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     jsd_DebuggerOff(jsdc);
 }
 
+JSD_PUBLIC_API(void)
+JSD_DebuggerPause(JSDContext* jsdc)
+{
+    JSD_ASSERT_VALID_CONTEXT(jsdc);
+    jsd_DebuggerPause(jsdc, JS_FALSE);
+}
+
+JSD_PUBLIC_API(void)
+JSD_DebuggerUnpause(JSDContext* jsdc)
+{
+    JSD_ASSERT_VALID_CONTEXT(jsdc);
+    jsd_DebuggerUnpause(jsdc);
+}
 
 JSD_PUBLIC_API(uintN)
 JSD_GetMajorVersion(void)
 {
     return JSD_MAJOR_VERSION;
 }
 
 JSD_PUBLIC_API(uintN)
@@ -118,17 +131,35 @@ JSD_ClearAllProfileData(JSDContext *jsdc
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     jsd_ClearAllProfileData(jsdc);    
 }
 
 JSD_PUBLIC_API(void)
 JSD_SetContextFlags(JSDContext *jsdc, uint32 flags)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
+    uint32 oldFlags = jsdc->flags;
     jsdc->flags = flags;
+    if ((flags & JSD_COLLECT_PROFILE_DATA) ||
+        !(flags & JSD_DISABLE_OBJECT_TRACE)) {
+        // Need to reenable our call hooks now
+        JS_SetExecuteHook(jsdc->jsrt, jsd_TopLevelCallHook, jsdc);
+        JS_SetCallHook(jsdc->jsrt, jsd_FunctionCallHook, jsdc);
+    }
+    if ((oldFlags ^ flags) & JSD_DISABLE_OBJECT_TRACE) {
+        // Changing our JSD_DISABLE_OBJECT_TRACE flag
+        if (!(flags & JSD_DISABLE_OBJECT_TRACE)) {
+            // Need to reenable our object hooks now
+            if (jsd_InitObjectManager(jsdc))
+                JS_SetObjectHook(jsdc->jsrt, jsd_ObjectHook, jsdc);
+        } else {
+            jsd_DestroyObjectManager(jsdc);
+            JS_SetObjectHook(jsdc->jsrt, NULL, NULL);
+        }
+    }
 }
 
 JSD_PUBLIC_API(uint32)
 JSD_GetContextFlags(JSDContext *jsdc)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsdc->flags;
 }
--- a/js/jsd/jsdebug.h
+++ b/js/jsd/jsdebug.h
@@ -146,16 +146,28 @@ JSD_DebuggerOnForUser(JSRuntime*        
 
 /*
 * Shutdown JSD for this JSDContext
 */
 extern JSD_PUBLIC_API(void)
 JSD_DebuggerOff(JSDContext* jsdc);
 
 /*
+ * Pause JSD for this JSDContext
+ */
+extern JSD_PUBLIC_API(void)
+JSD_DebuggerPause(JSDContext* jsdc);
+
+/*
+ * Unpause JSD for this JSDContext
+ */
+extern JSD_PUBLIC_API(void)
+JSD_DebuggerUnpause(JSDContext* jsdc);
+
+/*
 * Get the Major Version (initial JSD release used major version = 1)
 */
 extern JSD_PUBLIC_API(uintN)
 JSD_GetMajorVersion(void);
 
 /*
 * Get the Minor Version (initial JSD release used minor version = 0)
 */