diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -271,22 +271,32 @@ nsUserActivityObserver::Observe(nsISuppo
     }
     higherProbability = (mUserActivityCounter > NS_CC_SOFT_LIMIT_INACTIVE);
   } else if (!strcmp(aTopic, "user-interaction-active")) {
 #ifdef DEBUG_smaug
     printf("user-interaction-active\n");
 #endif
     sUserIsActive = PR_TRUE;
     higherProbability = (mUserActivityCounter > NS_CC_SOFT_LIMIT_ACTIVE);
+  } else if (!strcmp(aTopic, "maybe-cycle-collect")) {
+#ifdef DEBUG_smaug
+    printf("maybe-cycle-collect\n");
+#endif
+    if (!sUserIsActive) {
+      nsJSContext::IntervalCC();
+      return NS_OK;
+    }
+    higherProbability = PR_TRUE;
   } else if (!strcmp(aTopic, "xpcom-shutdown")) {
     nsCOMPtr<nsIObserverService> obs =
       do_GetService("@mozilla.org/observer-service;1");
     if (obs) {
       obs->RemoveObserver(this, "user-interaction-active");
       obs->RemoveObserver(this, "user-interaction-inactive");
+      obs->RemoveObserver(this, "cycle-collect");
       obs->RemoveObserver(this, "xpcom-shutdown");
     }
     return NS_OK;
   }
   nsJSContext::MaybeCC(higherProbability);
   return NS_OK;
 }
 
@@ -3982,16 +3992,17 @@ nsJSRuntime::Init()
 
   nsCOMPtr<nsIObserverService> obs =
     do_GetService("@mozilla.org/observer-service;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   nsIObserver* activityObserver = new nsUserActivityObserver();
   NS_ENSURE_TRUE(activityObserver, NS_ERROR_OUT_OF_MEMORY);
   obs->AddObserver(activityObserver, "user-interaction-inactive", PR_FALSE);
   obs->AddObserver(activityObserver, "user-interaction-active", PR_FALSE);
+  obs->AddObserver(activityObserver, "maybe-cycle-collect", PR_FALSE);
   obs->AddObserver(activityObserver, "xpcom-shutdown", PR_FALSE);
 
   nsIObserver* ccMemPressureObserver = new nsCCMemoryPressureObserver();
   NS_ENSURE_TRUE(ccMemPressureObserver, NS_ERROR_OUT_OF_MEMORY);
   obs->AddObserver(ccMemPressureObserver, "memory-pressure", PR_FALSE);
 
   sIsInitialized = PR_TRUE;
 
diff --git a/js/src/xpconnect/src/xpcexception.cpp b/js/src/xpconnect/src/xpcexception.cpp
--- a/js/src/xpconnect/src/xpcexception.cpp
+++ b/js/src/xpconnect/src/xpcexception.cpp
@@ -38,16 +38,20 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* An implementaion of nsIException. */
 
 #include "xpcprivate.h"
 #include "nsNetError.h"
+#include "nsThreadUtils.h"
+#include "nsIServiceManager.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIObserverService.h"
 
 /***************************************************************************/
 /* Quick and dirty mapping of well known result codes to strings. We only
 *  call this when building an exception object, so iterating the short array
 *  is not too bad.
 *
 *  It sure would be nice to have exceptions declared in idl and available
 *  in some more global way at runtime.
@@ -126,34 +130,64 @@ NS_INTERFACE_MAP_BEGIN(nsXPCException)
   NS_IMPL_QUERY_CLASSINFO(nsXPCException)
 NS_INTERFACE_MAP_END_THREADSAFE
 
 NS_IMPL_THREADSAFE_ADDREF(nsXPCException)
 NS_IMPL_THREADSAFE_RELEASE(nsXPCException)
 
 NS_IMPL_CI_INTERFACE_GETTER1(nsXPCException, nsIXPCException)
 
+static PRInt32 gMainThreadExceptions = 0;
+
+class nsExceptionCountNotifier : public nsRunnable
+{
+public:
+  NS_IMETHOD Run()
+  {
+    if (gMainThreadExceptions > 500) {
+      nsCOMPtr<nsIObserverService> obs =
+        do_GetService("@mozilla.org/observer-service;1");
+      if (obs) {
+        gMainThreadExceptions = 0;
+        obs->NotifyObservers(nsnull, "maybe-cycle-collect", nsnull);
+      }
+    }
+    return NS_OK;
+  }
+};
+
 nsXPCException::nsXPCException()
     : mMessage(nsnull),
       mResult(0),
       mName(nsnull),
       mLocation(nsnull),
       mData(nsnull),
       mFilename(nsnull),
       mLineNumber(0),
       mInner(nsnull),
       mInitialized(PR_FALSE)
 {
     MOZ_COUNT_CTOR(nsXPCException);
+    if (NS_IsMainThread()) {
+      ++gMainThreadExceptions;
+      if (gMainThreadExceptions > 500) {
+        nsRefPtr<nsExceptionCountNotifier> event =
+          new nsExceptionCountNotifier();
+        NS_DispatchToCurrentThread(event);
+      }
+    }
 }
 
 nsXPCException::~nsXPCException()
 {
     MOZ_COUNT_DTOR(nsXPCException);
     Reset();
+    if (NS_IsMainThread() && gMainThreadExceptions) {
+      --gMainThreadExceptions;
+    }
 }
 
 /* [noscript] xpcexJSVal stealJSVal (); */
 NS_IMETHODIMP
 nsXPCException::StealJSVal(jsval *vp NS_OUTPARAM)
 {
     if(mThrownJSVal.IsHeld())
     {
