Bug 737075 - unmark gray strongly held observers implemented in JS. r=bsmedberg, smaug
authorAndrew McCreight <amccreight@mozilla.com>
Mon, 30 Apr 2012 12:01:11 -0700
changeset 92743 0e2658794e06408c4b68b3eaf1002a751a92b854
parent 92742 22a3eddd0c5bdc187a61412bd93eff75083872b7
child 92744 5ca3b86976c9a1010a3663c3b2741008b59df89a
push id8850
push useramccreight@mozilla.com
push dateMon, 30 Apr 2012 19:01:43 +0000
treeherdermozilla-inbound@0e2658794e06 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, smaug
bugs737075
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 737075 - unmark gray strongly held observers implemented in JS. r=bsmedberg, smaug
content/base/src/nsCCUncollectableMarker.cpp
xpcom/ds/Makefile.in
xpcom/ds/nsObserverList.cpp
xpcom/ds/nsObserverList.h
xpcom/ds/nsObserverService.cpp
xpcom/ds/nsObserverService.h
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -57,16 +57,17 @@
 #include "nsEventListenerManager.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsJSEnvironment.h"
 #include "nsInProcessTabChildGlobal.h"
 #include "nsFrameLoader.h"
 #include "nsGenericElement.h"
 #include "xpcpublic.h"
+#include "nsObserverService.h"
 
 static bool sInited = 0;
 PRUint32 nsCCUncollectableMarker::sGeneration = 0;
 #ifdef MOZ_XUL
 #include "nsXULPrototypeCache.h"
 #endif
 
 NS_IMPL_ISUPPORTS1(nsCCUncollectableMarker, nsIObserver)
@@ -368,16 +369,20 @@ nsCCUncollectableMarker::Observe(nsISupp
     xulCache->MarkInCCGeneration(sGeneration);
   }
 #endif
 
   static bool previousWasJSCleanup = false;
   if (cleanupJS) {
     nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(sGeneration);
     MarkMessageManagers();
+
+    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+    static_cast<nsObserverService *>(obs.get())->UnmarkGrayStrongObservers();
+
     previousWasJSCleanup = true;
   } else if (previousWasJSCleanup) {
     previousWasJSCleanup = false;
     if (!prepareForCC) {
       xpc_UnmarkSkippableJSHolders();
     }
   }
 
--- a/xpcom/ds/Makefile.in
+++ b/xpcom/ds/Makefile.in
@@ -96,16 +96,17 @@ EXPORTS		= \
 		nsCppSharedAllocator.h \
 		nsCRT.h \
 		nsExpirationTracker.h \
 		nsFixedSizeAllocator.h \
 		nsHashtable.h \
 		nsIByteBuffer.h \
 		nsIUnicharBuffer.h \
 		nsMathUtils.h \
+		nsObserverList.h \
 		nsObserverService.h \
 		nsStaticNameTable.h \
 		nsStaticAtom.h \
 		nsSupportsArray.h \
 		nsSupportsPrimitives.h \
 		nsVariant.h \
 		nsStringEnumerator.h \
 		nsHashPropertyBag.h \
--- a/xpcom/ds/nsObserverList.cpp
+++ b/xpcom/ds/nsObserverList.cpp
@@ -35,16 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsObserverList.h"
 
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsISimpleEnumerator.h"
+#include "xpcpublic.h"
 
 nsresult
 nsObserverList::AddObserver(nsIObserver* anObserver, bool ownsWeak)
 {
     NS_ASSERTION(anObserver, "Null input");
 
     if (!ownsWeak) {
         ObserverRef* o = mObservers.AppendElement(anObserver);
@@ -126,16 +127,26 @@ nsObserverList::NotifyObservers(nsISuppo
     nsCOMArray<nsIObserver> observers;
     FillObserverArray(observers);
 
     for (PRInt32 i = 0; i < observers.Count(); ++i) {
         observers[i]->Observe(aSubject, aTopic, someData);
     }
 }
 
+void
+nsObserverList::UnmarkGrayStrongObservers()
+{
+    for (PRUint32 i = 0; i < mObservers.Length(); ++i) {
+        if (!mObservers[i].isWeakRef) {
+            xpc_TryUnmarkWrappedGrayObject(mObservers[i].asObserver());
+        }
+    }
+}
+
 NS_IMPL_ISUPPORTS1(nsObserverEnumerator, nsISimpleEnumerator)
 
 nsObserverEnumerator::nsObserverEnumerator(nsObserverList* aObserverList)
     : mIndex(0)
 {
     aObserverList->FillObserverArray(mObservers);
 }
 
--- a/xpcom/ds/nsObserverList.h
+++ b/xpcom/ds/nsObserverList.h
@@ -86,16 +86,20 @@ public:
                        const char *aTopic,
                        const PRUnichar *someData);
   nsresult GetObserverList(nsISimpleEnumerator** anEnumerator);
 
   // Fill an array with the observers of this category.
   // The array is filled in last-added-first order.
   void FillObserverArray(nsCOMArray<nsIObserver> &aArray);
 
+  // Unmark any strongly held observers implemented in JS so the cycle
+  // collector will not traverse them.
+  void UnmarkGrayStrongObservers();
+
 private:
   nsTArray<ObserverRef> mObservers;
 };
 
 class nsObserverEnumerator : public nsISimpleEnumerator
 {
 public:
     NS_DECL_ISUPPORTS
--- a/xpcom/ds/nsObserverService.cpp
+++ b/xpcom/ds/nsObserverService.cpp
@@ -185,8 +185,26 @@ NS_IMETHODIMP nsObserverService::NotifyO
     observerList = mObserverTopicTable.GetEntry("*");
     if (observerList)
         observerList->NotifyObservers(aSubject, aTopic, someData);
 #endif
 
     return NS_OK;
 }
 
+static PLDHashOperator
+UnmarkGrayObserverEntry(nsObserverList* aObserverList, void* aClosure)
+{
+    if (aObserverList) {
+        aObserverList->UnmarkGrayStrongObservers();
+    }
+    return PL_DHASH_NEXT;
+}
+
+NS_IMETHODIMP
+nsObserverService::UnmarkGrayStrongObservers()
+{
+    NS_ENSURE_VALIDCALL
+
+    mObserverTopicTable.EnumerateEntries(UnmarkGrayObserverEntry, nsnull);
+
+    return NS_OK;
+}
--- a/xpcom/ds/nsObserverService.h
+++ b/xpcom/ds/nsObserverService.h
@@ -57,16 +57,20 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVERSERVICE
   
   void Shutdown();
 
   static nsresult
   Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
 
+  // Unmark any strongly held observers implemented in JS so the cycle
+  // collector will not traverse them.
+  NS_IMETHOD UnmarkGrayStrongObservers();
+
 private:
   ~nsObserverService(void);
 
   bool mShuttingDown;
   nsTHashtable<nsObserverList> mObserverTopicTable;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsObserverService, NS_OBSERVERSERVICE_CID)