Bug 1244897 - Use TimerlineConsumers in PopProfileTimelineMarkers to ensure that all methods acquire TimelineConsumers Mutex. r?vporof draft
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Tue, 01 Mar 2016 19:54:47 +0900
changeset 335742 b8d5580bee8e82028fdd148d297ce250d297dfa3
parent 335409 9da51cb4974e03cdd8fa45a34086fe1033abfeaf
child 515204 87a862ff9e58ba96c6dcf7de9d238c6b66f1aeb8
push id11862
push userhiikezoe@mozilla-japan.org
push dateTue, 01 Mar 2016 11:37:42 +0000
reviewersvporof
bugs1244897
milestone47.0a1
Bug 1244897 - Use TimerlineConsumers in PopProfileTimelineMarkers to ensure that all methods acquire TimelineConsumers Mutex. r?vporof MozReview-Commit-ID: 5VzLfT5SUjI
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/timeline/ObservedDocShell.cpp
docshell/base/timeline/TimelineConsumers.cpp
docshell/base/timeline/TimelineConsumers.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2876,22 +2876,25 @@ nsDocShell::GetRecordProfileTimelineMark
   return NS_OK;
 }
 
 nsresult
 nsDocShell::PopProfileTimelineMarkers(
     JSContext* aCx,
     JS::MutableHandle<JS::Value> aOut)
 {
+  RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
+  if (!timelines) {
+    return NS_OK;
+  }
+
   nsTArray<dom::ProfileTimelineMarker> store;
   SequenceRooter<dom::ProfileTimelineMarker> rooter(aCx, &store);
 
-  if (mObserved) {
-    mObserved->PopMarkers(aCx, store);
-  }
+  timelines->PopMarkers(this, aCx, store);
 
   if (!ToJSValue(aCx, store, aOut)) {
     JS_ClearPendingException(aCx);
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -289,16 +289,18 @@ private:
   friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell*);
   friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell*);
   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
     nsDocShell*, const char*, MarkerTracingType);
   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
     nsDocShell*, const char*, const TimeStamp&, MarkerTracingType);
   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
     nsDocShell*, UniquePtr<AbstractTimelineMarker>&&);
+  friend void mozilla::TimelineConsumers::PopMarkers(nsDocShell*,
+    JSContext*, nsTArray<dom::ProfileTimelineMarker>&);
 
 public:
   // Tell the favicon service that aNewURI has the same favicon as aOldURI.
   static void CopyFavicon(nsIURI* aOldURI,
                           nsIURI* aNewURI,
                           nsIPrincipal* aLoadingPrincipal,
                           bool aInPrivateBrowsing);
 
--- a/docshell/base/timeline/ObservedDocShell.cpp
+++ b/docshell/base/timeline/ObservedDocShell.cpp
@@ -40,16 +40,17 @@ ObservedDocShell::AddOTMTMarker(UniquePt
   MOZ_ASSERT(!NS_IsMainThread());
   MutexAutoLock lock(GetLock()); // for `mOffTheMainThreadTimelineMarkers`.
   mOffTheMainThreadTimelineMarkers.AppendElement(Move(aMarker));
 }
 
 void
 ObservedDocShell::ClearMarkers()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MutexAutoLock lock(GetLock()); // for `mOffTheMainThreadTimelineMarkers`.
   mTimelineMarkers.Clear();
   mOffTheMainThreadTimelineMarkers.Clear();
 }
 
 void
 ObservedDocShell::PopMarkers(JSContext* aCx,
                              nsTArray<dom::ProfileTimelineMarker>& aStore)
--- a/docshell/base/timeline/TimelineConsumers.cpp
+++ b/docshell/base/timeline/TimelineConsumers.cpp
@@ -289,9 +289,24 @@ TimelineConsumers::AddMarkerForAllObserv
     if (isMainThread) {
       storage->AddMarker(Move(clone));
     } else {
       storage->AddOTMTMarker(Move(clone));
     }
   }
 }
 
+void
+TimelineConsumers::PopMarkers(nsDocShell* aDocShell,
+                              JSContext* aCx,
+                              nsTArray<dom::ProfileTimelineMarker>& aStore)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  StaticMutexAutoLock lock(sMutex); // for `mMarkersStores`.
+
+  if (!aDocShell || !aDocShell->mObserved) {
+    return;
+  }
+
+  aDocShell->mObserved->PopMarkers(aCx, aStore);
+}
+
 } // namespace mozilla
--- a/docshell/base/timeline/TimelineConsumers.h
+++ b/docshell/base/timeline/TimelineConsumers.h
@@ -10,22 +10,27 @@
 #include "mozilla/StaticPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/StaticMutex.h"
 #include "TimelineMarkerEnums.h" // for MarkerTracingType
 
 class nsDocShell;
 class nsIDocShell;
+struct JSContext;
 
 namespace mozilla {
 class TimeStamp;
 class MarkersStorage;
 class AbstractTimelineMarker;
 
+namespace dom {
+struct ProfileTimelineMarker;
+}
+
 class TimelineConsumers : public nsIObserver
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
 private:
   TimelineConsumers();
@@ -99,16 +104,20 @@ public:
                                         MarkerTracingType aTracingType,
                                         MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
 
   // This method clones and registers an already instantiated marker,
   // which doesn't have to be relevant to a specific docshell.
   // May be called from any thread.
   void AddMarkerForAllObservedDocShells(UniquePtr<AbstractTimelineMarker>& aMarker);
 
+  void PopMarkers(nsDocShell* aDocShell,
+                  JSContext* aCx,
+                  nsTArray<dom::ProfileTimelineMarker>& aStore);
+
 private:
   static StaticRefPtr<TimelineConsumers> sInstance;
   static bool sInShutdown;
 
   // Counter for how many timelines are currently interested in markers,
   // and a list of the MarkersStorage interfaces representing them.
   unsigned long mActiveConsumers;
   LinkedList<MarkersStorage> mMarkersStores;