Bug 868139 - Don't redo unmarking work in nsGlobalWindow::CanSkip if we already did it. r=smaug, a=lsblakk
authorAndrew McCreight <continuation@gmail.com>
Thu, 13 Nov 2014 07:11:55 -0800
changeset 235214 4ae20fe9a96e07608742df7ed4eb32cc2212f19f
parent 235213 8e9cc4b2f923da6a0a6c3e8aafaf629607c39fb0
child 235215 982d0fae3965f5ce92fd1350cdbe30dc485a423e
push id611
push userraliiev@mozilla.com
push dateMon, 05 Jan 2015 23:23:16 +0000
treeherdermozilla-release@345cd3b9c445 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, lsblakk
bugs868139
milestone35.0a2
Bug 868139 - Don't redo unmarking work in nsGlobalWindow::CanSkip if we already did it. r=smaug, a=lsblakk This causes quadratic behavior in forgetSkippable when there are many timeouts. To avoid this, we mark the CC generation of the last time we ran CanSkip on the window, and don't do it again if it hasn't changed.
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1123,17 +1123,18 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalW
     mSetOpenerWindowCalled(false),
 #endif
 #ifdef MOZ_B2G
     mNetworkUploadObserverEnabled(false),
     mNetworkDownloadObserverEnabled(false),
 #endif
     mCleanedUp(false),
     mDialogAbuseCount(0),
-    mAreDialogsEnabled(true)
+    mAreDialogsEnabled(true),
+    mCanSkipCCGeneration(0)
 {
   nsLayoutStatics::AddRef();
 
   // Initialize the PRCList (this).
   PR_INIT_CLIST(this);
 
   if (aOuterWindow) {
     // |this| is an inner window, add this inner window to the outer
@@ -1674,16 +1675,20 @@ static PLDHashOperator
 MarkXBLHandlers(nsXBLPrototypeHandler* aKey, JS::Heap<JSObject*>& aData, void* aClosure)
 {
   JS::ExposeObjectToActiveJS(aData);
   return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindow)
   if (tmp->IsBlackForCC(false)) {
+    if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) {
+      return true;
+    }
+    tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
     if (tmp->mCachedXBLPrototypeHandlers) {
       tmp->mCachedXBLPrototypeHandlers->Enumerate(MarkXBLHandlers, nullptr);
     }
     if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
       elm->MarkForCC();
     }
     tmp->UnmarkGrayTimers();
     return true;
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1622,16 +1622,19 @@ protected:
 
   nsTArray<uint32_t> mEnabledSensors;
 
 #ifdef MOZ_WEBSPEECH
   // mSpeechSynthesis is only used on inner windows.
   nsRefPtr<mozilla::dom::SpeechSynthesis> mSpeechSynthesis;
 #endif
 
+  // This is the CC generation the last time we called CanSkip.
+  uint32_t mCanSkipCCGeneration;
+
   friend class nsDOMScriptableHelper;
   friend class nsDOMWindowUtils;
   friend class PostMessageEvent;
   friend class DesktopNotification;
 
   static WindowByIdTable* sWindowsById;
   static bool sWarnedAboutWindowInternal;
 };