Fix for bug 477688 (nsJSContext CC timer keeps nsJSContext alive). r=bent, sr=jst, a=jst.
authorPeter Van der Beken <peterv@propagandism.org>
Thu, 12 Feb 2009 13:06:59 +0100
changeset 23420 725587d0bbee475af2eacd96217e10964a739213
parent 23419 bcf7787315fb61da3f96da8cd75a862b8bb8b545
child 23421 03324648db5415fc6151fa301598cd608e666f98
push id766
push userpvanderbeken@mozilla.com
push dateWed, 25 Feb 2009 10:30:35 +0000
reviewersbent, jst, jst
bugs477688
milestone1.9.1b3pre
Fix for bug 477688 (nsJSContext CC timer keeps nsJSContext alive). r=bent, sr=jst, a=jst.
dom/src/base/nsJSEnvironment.cpp
dom/src/base/nsJSEnvironment.h
--- a/dom/src/base/nsJSEnvironment.cpp
+++ b/dom/src/base/nsJSEnvironment.cpp
@@ -1335,17 +1335,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGlobalWrapperRef)
   nsContentUtils::XPConnect()->NoteJSContext(tmp->mContext, cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSContext)
   NS_INTERFACE_MAP_ENTRY(nsIScriptContext)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptNotify)
-  NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptContext)
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsJSContext, nsIScriptContext)
 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsJSContext, nsIScriptContext)
 
 nsresult
@@ -3500,42 +3499,39 @@ nsJSContext::CCIfUserInactive()
 {
   if (sUserIsActive) {
     MaybeCC(PR_TRUE);
   } else {
     CC();
   }
 }
 
-NS_IMETHODIMP
-nsJSContext::Notify(nsITimer *timer)
+// static
+void
+GCTimerFired(nsITimer *aTimer, void *aClosure)
 {
-  NS_ASSERTION(mContext, "No context in nsJSContext::Notify()!");
-
   NS_RELEASE(sGCTimer);
 
   if (sPendingLoadCount == 0 || sLoadInProgressGCTimer) {
     sLoadInProgressGCTimer = PR_FALSE;
 
     // Reset sPendingLoadCount in case the timer that fired was a
     // timer we scheduled due to a normal GC timer firing while
     // documents were loading. If this happens we're waiting for a
     // document that is taking a long time to load, and we effectively
     // ignore the fact that the currently loading documents are still
     // loading and move on as if they weren't.
     sPendingLoadCount = 0;
 
-    CCIfUserInactive();
+    nsJSContext::CCIfUserInactive();
   } else {
-    FireGCTimer(PR_TRUE);
+    nsJSContext::FireGCTimer(PR_TRUE);
   }
 
   sReadyForGC = PR_TRUE;
-
-  return NS_OK;
 }
 
 // static
 void
 nsJSContext::LoadStart()
 {
   ++sPendingLoadCount;
 }
@@ -3554,25 +3550,20 @@ nsJSContext::LoadEnd()
     sGCTimer->Cancel();
     NS_RELEASE(sGCTimer);
     sLoadInProgressGCTimer = PR_FALSE;
 
     CCIfUserInactive();
   }
 }
 
+// static
 void
 nsJSContext::FireGCTimer(PRBool aLoadInProgress)
 {
-  // Always clear the newborn roots.  If there's already a timer, this
-  // will let the GC from that timer clean up properly.  If we're going
-  // to create a timer, we still want to do this now so that XPCOM
-  // shutdown can clean up properly.
-  ::JS_ClearNewbornRoots(mContext);
-
   if (sGCTimer) {
     // There's already a timer for GC'ing, just return
     return;
   }
 
   CallCreateInstance("@mozilla.org/timer;1", &sGCTimer);
 
   if (!sGCTimer) {
@@ -3583,21 +3574,21 @@ nsJSContext::FireGCTimer(PRBool aLoadInP
     sLoadInProgressGCTimer = PR_FALSE;
 
     CCIfUserInactive();
     return;
   }
 
   static PRBool first = PR_TRUE;
 
-  sGCTimer->InitWithCallback(this,
-                             first ? NS_FIRST_GC_DELAY :
-                             aLoadInProgress ? NS_LOAD_IN_PROCESS_GC_DELAY :
-                                               NS_GC_DELAY,
-                             nsITimer::TYPE_ONE_SHOT);
+  sGCTimer->InitWithFuncCallback(GCTimerFired, nsnull,
+                                 first ? NS_FIRST_GC_DELAY :
+                                 aLoadInProgress ? NS_LOAD_IN_PROCESS_GC_DELAY :
+                                                   NS_GC_DELAY,
+                                 nsITimer::TYPE_ONE_SHOT);
 
   sLoadInProgressGCTimer = aLoadInProgress;
 
   first = PR_FALSE;
 }
 
 static JSBool
 DOMGCCallback(JSContext *cx, JSGCStatus status)
--- a/dom/src/base/nsJSEnvironment.h
+++ b/dom/src/base/nsJSEnvironment.h
@@ -38,26 +38,24 @@
 #define nsJSEnvironment_h___
 
 #include "nsIScriptContext.h"
 #include "nsIScriptRuntime.h"
 #include "nsCOMPtr.h"
 #include "jsapi.h"
 #include "nsIObserver.h"
 #include "nsIXPCScriptNotify.h"
-#include "nsITimer.h"
 #include "prtime.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsScriptNameSpaceManager.h"
 
 class nsIXPConnectJSObjectHolder;
 
 class nsJSContext : public nsIScriptContext,
-                    public nsIXPCScriptNotify,
-                    public nsITimerCallback
+                    public nsIXPCScriptNotify
 {
 public:
   nsJSContext(JSRuntime *aRuntime);
   virtual ~nsJSContext();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsJSContext, nsIScriptContext)
 
@@ -165,18 +163,16 @@ public:
 
   virtual nsresult DropScriptObject(void *object);
   virtual nsresult HoldScriptObject(void *object);
 
   virtual void ReportPendingException();
 
   NS_DECL_NSIXPCSCRIPTNOTIFY
 
-  NS_DECL_NSITIMERCALLBACK
-
   static void LoadStart();
   static void LoadEnd();
 
   // CC does always call cycle collector and it also updates the counters
   // that MaybeCC uses.
   static void CC();
 
   // MaybeCC calls cycle collector if certain conditions are fulfilled.
@@ -191,31 +187,32 @@ public:
   //   at least NS_MAX_DELAYED_CCOLLECT MaybeCC calls are needed.
   //   If the previous call to cycle collector did collect something,
   //   MaybeCC works effectively as if aHigherProbability was true.
   // @return PR_TRUE if cycle collector was called.
   static PRBool MaybeCC(PRBool aHigherProbability);
 
   // Calls CC() if user is currently inactive, otherwise MaybeCC(PR_TRUE)
   static void CCIfUserInactive();
+
+  static void FireGCTimer(PRBool aLoadInProgress);
+
 protected:
   nsresult InitializeExternalClasses();
   // aHolder should be holding our global object
   nsresult FindXPCNativeWrapperClass(nsIXPConnectJSObjectHolder *aHolder);
 
   // Helper to convert xpcom datatypes to jsvals.
   nsresult ConvertSupportsTojsvals(nsISupports *aArgs,
                                    void *aScope,
                                    PRUint32 *aArgc, void **aArgv,
                                    void **aMarkp);
 
   nsresult AddSupportsPrimitiveTojsvals(nsISupports *aArg, jsval *aArgv);
 
-  void FireGCTimer(PRBool aLoadInProgress);
-
   // given an nsISupports object (presumably an event target or some other
   // DOM object), get (or create) the JSObject wrapping it.
   nsresult JSObjectFromInterface(nsISupports *aSup, void *aScript, 
                                  JSObject **aRet);
 
 private:
   void Unlink();