Bug 1183229 - Add a way to count the number of timeline-observed docshells outside of nsDocShell, r=smaug
authorVictor Porof <vporof@mozilla.com>
Sat, 18 Jul 2015 09:35:59 -0400
changeset 253560 080a2d9acd71d3bcc7e7fc0e3d0fb020fd1687eb
parent 253559 6dcdde80d1967ffb64c6f986e95987cc838658a4
child 253561 e9c3cbdce3d577fcddcea3ce15c5c23199c284bb
push id29070
push userttaubert@mozilla.com
push dateMon, 20 Jul 2015 07:15:19 +0000
treeherdermozilla-central@202e9233d130 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1183229
milestone42.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 1183229 - Add a way to count the number of timeline-observed docshells outside of nsDocShell, r=smaug
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/timeline/AutoGlobalTimelineMarker.cpp
docshell/base/timeline/AutoTimelineMarker.cpp
docshell/base/timeline/TimelineConsumers.cpp
docshell/base/timeline/TimelineConsumers.h
docshell/base/timeline/moz.build
dom/events/EventListenerManager.cpp
layout/base/nsRefreshDriver.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2924,34 +2924,32 @@ nsDocShell::HistoryTransactionRemoved(in
     if (shell) {
       static_cast<nsDocShell*>(shell.get())->HistoryTransactionRemoved(aIndex);
     }
   }
 
   return NS_OK;
 }
 
-unsigned long nsDocShell::gProfileTimelineRecordingsCount = 0;
-
 mozilla::LinkedList<nsDocShell::ObservedDocShell>* nsDocShell::gObservedDocShells = nullptr;
 
 NS_IMETHODIMP
 nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
 {
   bool currentValue = nsIDocShell::GetRecordProfileTimelineMarkers();
   if (currentValue != aValue) {
     if (aValue) {
-      ++gProfileTimelineRecordingsCount;
+      TimelineConsumers::AddConsumer();
       UseEntryScriptProfiling();
 
       MOZ_ASSERT(!mObserved);
       mObserved.reset(new ObservedDocShell(this));
       GetOrCreateObservedDocShells().insertFront(mObserved.get());
     } else {
-      --gProfileTimelineRecordingsCount;
+      TimelineConsumers::RemoveConsumer();
       UnuseEntryScriptProfiling();
 
       mObserved.reset(nullptr);
 
       ClearProfileTimelineMarkers();
     }
   }
 
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -29,16 +29,17 @@
 // Helper Classes
 #include "nsCOMPtr.h"
 #include "nsPoint.h" // mCurrent/mDefaultScrollbarPreferences
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
 #include "nsContentUtils.h"
 #include "timeline/TimelineMarker.h"
+#include "timeline/TimelineConsumers.h"
 
 // Threshold value in ms for META refresh based redirects
 #define REFRESH_REDIRECT_TIMER 15000
 
 // Interfaces Needed
 #include "nsIDocCharset.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIRefreshURI.h"
@@ -257,20 +258,16 @@ public:
   void NotifyAsyncPanZoomStopped();
 
   // Add new profile timeline markers to this docShell. This will only add
   // markers if the docShell is currently recording profile timeline markers.
   // See nsIDocShell::recordProfileTimelineMarkers
   void AddProfileTimelineMarker(const char* aName, TracingMetadata aMetaData);
   void AddProfileTimelineMarker(mozilla::UniquePtr<TimelineMarker>&& aMarker);
 
-  // Global counter for how many docShells are currently recording profile
-  // timeline markers
-  static unsigned long gProfileTimelineRecordingsCount;
-
   class ObservedDocShell : public mozilla::LinkedListElement<ObservedDocShell>
   {
   public:
     explicit ObservedDocShell(nsDocShell* aDocShell)
       : mDocShell(aDocShell)
     { }
 
     nsDocShell* operator*() const { return mDocShell.get(); }
--- a/docshell/base/timeline/AutoGlobalTimelineMarker.cpp
+++ b/docshell/base/timeline/AutoGlobalTimelineMarker.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/AutoGlobalTimelineMarker.h"
 
+#include "mozilla/TimelineConsumers.h"
 #include "MainThreadUtils.h"
 #include "nsDocShell.h"
 
 namespace mozilla {
 
 void
 AutoGlobalTimelineMarker::PopulateDocShells()
 {
@@ -32,17 +33,17 @@ AutoGlobalTimelineMarker::AutoGlobalTime
                                                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   : mOk(true)
   , mDocShells()
   , mName(aName)
 {
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (nsDocShell::gProfileTimelineRecordingsCount == 0) {
+  if (TimelineConsumers::IsEmpty()) {
     return;
   }
 
   PopulateDocShells();
   if (!mOk) {
     // If we don't successfully populate our vector with *all* docshells being
     // observed, don't add markers to *any* of them.
     return;
--- a/docshell/base/timeline/AutoTimelineMarker.cpp
+++ b/docshell/base/timeline/AutoTimelineMarker.cpp
@@ -10,17 +10,17 @@
 #include "nsDocShell.h"
 
 namespace mozilla {
 
 bool
 AutoTimelineMarker::DocShellIsRecording(nsDocShell& aDocShell)
 {
   bool isRecording = false;
-  if (nsDocShell::gProfileTimelineRecordingsCount > 0) {
+  if (!TimelineConsumers::IsEmpty()) {
     aDocShell.GetRecordProfileTimelineMarkers(&isRecording);
   }
   return isRecording;
 }
 
 AutoTimelineMarker::AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName
                                        MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   : mDocShell(nullptr)
new file mode 100644
--- /dev/null
+++ b/docshell/base/timeline/TimelineConsumers.cpp
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/TimelineConsumers.h"
+
+namespace mozilla {
+
+unsigned long TimelineConsumers::sActiveConsumers = 0;
+
+void
+TimelineConsumers::AddConsumer()
+{
+  sActiveConsumers++;
+}
+
+void
+TimelineConsumers::RemoveConsumer()
+{
+  sActiveConsumers--;
+}
+
+bool
+TimelineConsumers::IsEmpty()
+{
+  return sActiveConsumers == 0;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/docshell/base/timeline/TimelineConsumers.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_TimelineConsumers_h_
+#define mozilla_TimelineConsumers_h_
+
+class nsDocShell;
+
+namespace mozilla {
+
+// # TimelineConsumers
+//
+// A class to trace how many frontends are interested in markers. Whenever
+// interest is expressed in markers, these fields will keep track of that.
+class TimelineConsumers
+{
+private:
+  // Counter for how many timelines are currently interested in markers.
+  static unsigned long sActiveConsumers;
+
+public:
+  static void AddConsumer();
+  static void RemoveConsumer();
+  static bool IsEmpty();
+};
+
+} // namespace mozilla
+
+#endif /* mozilla_TimelineConsumers_h_ */
--- a/docshell/base/timeline/moz.build
+++ b/docshell/base/timeline/moz.build
@@ -2,21 +2,23 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS.mozilla += [
     'AutoGlobalTimelineMarker.h',
     'AutoTimelineMarker.h',
+    'TimelineConsumers.h',
 ]
 
 UNIFIED_SOURCES += [
     'AutoGlobalTimelineMarker.cpp',
     'AutoTimelineMarker.cpp',
+    'TimelineConsumers.cpp',
     'TimelineMarker.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -18,16 +18,17 @@
 #endif // #ifdef MOZ_B2G
 #include "mozilla/HalSensor.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/JSEventHandler.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
+#include "mozilla/TimelineConsumers.h"
 
 #include "EventListenerService.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsDocShell.h"
 #include "nsDOMCID.h"
 #include "nsError.h"
@@ -1117,17 +1118,17 @@ EventListenerManager::HandleEventInterna
             }
           }
 
           // Maybe add a marker to the docshell's timeline, but only
           // bother with all the logic if some docshell is recording.
           nsCOMPtr<nsIDocShell> docShell;
           bool isTimelineRecording = false;
           if (mIsMainThreadELM &&
-              nsDocShell::gProfileTimelineRecordingsCount > 0 &&
+              !TimelineConsumers::IsEmpty() &&
               listener->mListenerType != Listener::eNativeListener) {
             docShell = GetDocShellForTarget();
             if (docShell) {
               docShell->GetRecordProfileTimelineMarkers(&isTimelineRecording);
             }
             if (isTimelineRecording) {
               nsDocShell* ds = static_cast<nsDocShell*>(docShell.get());
               nsAutoString typeStr;
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -59,16 +59,17 @@
 #include "BackgroundChild.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #include "mozilla/layout/VsyncChild.h"
 #include "VsyncSource.h"
 #include "mozilla/VsyncDispatcher.h"
 #include "nsThreadUtils.h"
 #include "mozilla/unused.h"
+#include "mozilla/TimelineConsumers.h"
 
 #ifdef MOZ_NUWA_PROCESS
 #include "ipc/Nuwa.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::widget;
 using namespace mozilla::ipc;
@@ -988,17 +989,17 @@ nsRefreshDriver::GetRefreshTimerInterval
 {
   return mThrottled ? GetThrottledTimerInterval() : GetRegularTimerInterval();
 }
 
 RefreshDriverTimer*
 nsRefreshDriver::ChooseTimer() const
 {
   if (mThrottled) {
-    if (!sThrottledRateTimer) 
+    if (!sThrottledRateTimer)
       sThrottledRateTimer = new InactiveRefreshDriverTimer(GetThrottledTimerInterval(),
                                                            DEFAULT_INACTIVE_TIMER_DISABLE_SECONDS * 1000.0);
     return sThrottledRateTimer;
   }
 
   if (!sRegularRateTimer) {
     bool isDefault = true;
     double rate = GetRegularTimerInterval(&isDefault);
@@ -1046,17 +1047,17 @@ nsRefreshDriver::nsRefreshDriver(nsPresC
   mNextRecomputeVisibilityTick = mMostRecentTick;
 }
 
 nsRefreshDriver::~nsRefreshDriver()
 {
   MOZ_ASSERT(ObserverCount() == 0,
              "observers should have unregistered");
   MOZ_ASSERT(!mActiveTimer, "timer should be gone");
-  
+
   if (mRootRefresh) {
     mRootRefresh->RemoveRefreshObserver(this, Flush_Style);
     mRootRefresh = nullptr;
   }
   for (nsIPresShell* shell : mPresShellsToInvalidateIfHidden) {
     shell->InvalidatePresShellIfHidden();
   }
   mPresShellsToInvalidateIfHidden.Clear();
@@ -1431,17 +1432,17 @@ HasPendingAnimations(nsIPresShell* aShel
 
 /**
  * Return a list of all the child docShells in a given root docShell that are
  * visible and are recording markers for the profilingTimeline
  */
 static void GetProfileTimelineSubDocShells(nsDocShell* aRootDocShell,
                                            nsTArray<nsDocShell*>& aShells)
 {
-  if (!aRootDocShell || nsDocShell::gProfileTimelineRecordingsCount == 0) {
+  if (!aRootDocShell || TimelineConsumers::IsEmpty()) {
     return;
   }
 
   nsCOMPtr<nsISimpleEnumerator> enumerator;
   nsresult rv = aRootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeAll,
     nsIDocShell::ENUMERATE_BACKWARDS, getter_AddRefs(enumerator));
 
   if (NS_FAILED(rv)) {