Bug 1129249 - Add a "restyle" feature to profiler and split the style label in Cleopatra based on the restyleSource, r=dholbert,mstange
authorchiajung hung <chung@mozilla.com>
Thu, 19 Mar 2015 02:19:00 +0100
changeset 263559 703caa5d845f02d37f98f099540a00d4f2353af6
parent 263558 8cd33e72eb47595535b3a747875f81c575baf287
child 263560 a29d23e9d4b67cb435ba14e5b9958054bbc930c7
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert, mstange
bugs1129249
milestone39.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 1129249 - Add a "restyle" feature to profiler and split the style label in Cleopatra based on the restyleSource, r=dholbert,mstange
layout/base/RestyleTracker.cpp
layout/base/RestyleTracker.h
tools/profiler/GeckoProfiler.h
tools/profiler/platform.cpp
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -78,16 +78,17 @@ CollectLaterSiblings(nsISupports* aEleme
     collector->elements->AppendElement(element);
   }
 
   return PL_DHASH_NEXT;
 }
 
 struct RestyleEnumerateData : RestyleTracker::Hints {
   nsRefPtr<dom::Element> mElement;
+  UniquePtr<ProfilerBacktrace> mBacktrace;
 };
 
 struct RestyleCollector {
   RestyleTracker* tracker;
   RestyleEnumerateData** restyleArrayPtr;
 #ifdef RESTYLE_LOGGING
   uint32_t count;
 #endif
@@ -135,16 +136,17 @@ CollectRestyles(nsISupports* aElement,
   element->UnsetFlags(collector->tracker->RestyleBit() |
                       collector->tracker->RootBit());
 
   RestyleEnumerateData** restyleArrayPtr = collector->restyleArrayPtr;
   RestyleEnumerateData* currentRestyle = *restyleArrayPtr;
   currentRestyle->mElement = element;
   currentRestyle->mRestyleHint = aData->mRestyleHint;
   currentRestyle->mChangeHint = aData->mChangeHint;
+  currentRestyle->mBacktrace = Move(aData->mBacktrace);
 
 #ifdef RESTYLE_LOGGING
   collector->count++;
 #endif
 
   // Increment to the next slot in the array
   *restyleArrayPtr = currentRestyle + 1;
 
@@ -300,16 +302,20 @@ RestyleTracker::DoProcessRestyles()
         }
 
         nsAutoPtr<RestyleData> data;
         if (!GetRestyleData(element, data)) {
           LOG_RESTYLE("skipping, already restyled");
           continue;
         }
 
+        Maybe<GeckoProfilerTracingRAII> profilerRAII;
+        if (profiler_feature_active("restyle")) {
+          profilerRAII.emplace("Paint", "Styles", Move(data->mBacktrace));
+        }
         ProcessOneRestyle(element, data->mRestyleHint, data->mChangeHint);
         AddRestyleRootsIfAwaitingRestyle(data->mDescendants);
       }
 
       if (mHaveLaterSiblingRestyles) {
         // Keep processing restyles for now
         continue;
       }
@@ -335,16 +341,21 @@ RestyleTracker::DoProcessRestyles()
 #endif
         for (RestyleEnumerateData* currentRestyle = restylesToProcess;
              currentRestyle != lastRestyle;
              ++currentRestyle) {
           LOG_RESTYLE("processing pending restyle %s at index %d/%d",
                       FrameTagToString(currentRestyle->mElement).get(),
                       index++, collector.count);
           LOG_RESTYLE_INDENT();
+
+          Maybe<GeckoProfilerTracingRAII> profilerRAII;
+          if (profiler_feature_active("restyle")) {
+            profilerRAII.emplace("Paint", "Styles", Move(currentRestyle->mBacktrace));
+          }
           ProcessOneRestyle(currentRestyle->mElement,
                             currentRestyle->mRestyleHint,
                             currentRestyle->mChangeHint);
         }
       }
     }
   }
 
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -11,16 +11,18 @@
 #ifndef mozilla_RestyleTracker_h
 #define mozilla_RestyleTracker_h
 
 #include "mozilla/dom/Element.h"
 #include "nsClassHashtable.h"
 #include "nsContainerFrame.h"
 #include "mozilla/SplayTree.h"
 #include "mozilla/RestyleLogging.h"
+#include "ProfilerBacktrace.h"
+#include "GeckoProfiler.h"
 
 namespace mozilla {
 
 class RestyleManager;
 class ElementRestyler;
 
 /** 
  * Helper class that collects a list of frames that need
@@ -286,16 +288,17 @@ public:
       mChangeHint = aChangeHint;
     }
 
     // Descendant elements we must check that we ended up restyling, ordered
     // with the same invariant as mRestyleRoots.  The elements here are those
     // that we called AddPendingRestyle for and found the element this is
     // the RestyleData for as its nearest restyle root.
     nsTArray<nsRefPtr<Element>> mDescendants;
+    UniquePtr<ProfilerBacktrace> mBacktrace;
   };
 
   /**
    * If the given Element has a restyle pending for it, return the
    * relevant restyle data.  This function will clear everything other
    * than a possible eRestyle_LaterSiblings hint for aElement out of
    * our hashtable.  The returned aData will never have an
    * eRestyle_LaterSiblings hint in it.
@@ -383,18 +386,21 @@ RestyleTracker::AddPendingRestyleToTable
   if (aElement->HasFlag(RestyleBit())) {
     mPendingRestyles.Get(aElement, &existingData);
   } else {
     aElement->SetFlags(RestyleBit());
     existingData = nullptr;
   }
 
   if (!existingData) {
-    mPendingRestyles.Put(aElement,
-                         new RestyleData(aRestyleHint, aMinChangeHint));
+    RestyleData* rd = new RestyleData(aRestyleHint, aMinChangeHint);
+    if (profiler_feature_active("restyle")) {
+      rd->mBacktrace.reset(profiler_get_backtrace());
+    }
+    mPendingRestyles.Put(aElement, rd);
     return false;
   }
 
   bool hadRestyleLaterSiblings =
     (existingData->mRestyleHint & eRestyle_LaterSiblings) != 0;
   existingData->mRestyleHint =
     nsRestyleHint(existingData->mRestyleHint | aRestyleHint);
   NS_UpdateHint(existingData->mChangeHint, aMinChangeHint);
--- a/tools/profiler/GeckoProfiler.h
+++ b/tools/profiler/GeckoProfiler.h
@@ -45,16 +45,17 @@
  * 't' - Elapse time since recording started.
  *
  */
 
 #ifndef SAMPLER_H
 #define SAMPLER_H
 
 #include "js/TypeDecls.h"
+#include "mozilla/UniquePtr.h"
 
 namespace mozilla {
 class TimeStamp;
 }
 
 enum TracingMetadata {
   TRACING_DEFAULT,
   TRACING_INTERVAL_START,
@@ -225,9 +226,33 @@ public:
   GeckoProfilerSleepRAII() {
     profiler_sleep_start();
   }
   ~GeckoProfilerSleepRAII() {
     profiler_sleep_end();
   }
 };
 
+class ProfilerBacktrace;
+
+class MOZ_STACK_CLASS GeckoProfilerTracingRAII {
+public:
+  GeckoProfilerTracingRAII(const char* aCategory, const char* aInfo,
+                           mozilla::UniquePtr<ProfilerBacktrace> aBacktrace
+                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+    : mCategory(aCategory)
+    , mInfo(aInfo)
+  {
+    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    profiler_tracing(mCategory, mInfo, aBacktrace.release(), TRACING_INTERVAL_START);
+  }
+
+  ~GeckoProfilerTracingRAII() {
+    profiler_tracing(mCategory, mInfo, TRACING_INTERVAL_END);
+  }
+
+protected:
+  MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+  const char* mCategory;
+  const char* mInfo;
+};
+
 #endif // ifndef SAMPLER_H
--- a/tools/profiler/platform.cpp
+++ b/tools/profiler/platform.cpp
@@ -43,16 +43,17 @@ mozilla::TimeStamp   sLastTracerEvent; /
 mozilla::TimeStamp   sStartTime;
 int         sFrameNumber = 0;
 int         sLastFrameNumber = 0;
 int         sInitCount = 0; // Each init must have a matched shutdown.
 static bool sIsProfiling = false; // is raced on
 static bool sIsGPUProfiling = false; // is raced on
 static bool sIsLayersDump = false; // is raced on
 static bool sIsDisplayListDump = false; // is raced on
+static bool sIsRestyleProfiling = false; // is raced on
 
 // env variables to control the profiler
 const char* PROFILER_MODE = "MOZ_PROFILER_MODE";
 const char* PROFILER_INTERVAL = "MOZ_PROFILER_INTERVAL";
 const char* PROFILER_ENTRIES = "MOZ_PROFILER_ENTRIES";
 const char* PROFILER_STACK = "MOZ_PROFILER_STACK_SCAN";
 const char* PROFILER_FEATURES = "MOZ_PROFILING_FEATURES";
 
@@ -758,16 +759,17 @@ void mozilla_sampler_start(int aProfileE
     mozilla::IOInterposer::Register(mozilla::IOInterposeObserver::OpAll,
                                     sInterposeObserver);
   }
 
   sIsProfiling = true;
   sIsGPUProfiling = t->ProfileGPU();
   sIsLayersDump = t->LayersDump();
   sIsDisplayListDump = t->DisplayListDump();
+  sIsRestyleProfiling = t->ProfileRestyle();
 
   if (Sampler::CanNotifyObservers()) {
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os) {
       nsTArray<nsCString> featuresArray;
       nsTArray<nsCString> threadNameFiltersArray;
 
       for (size_t i = 0; i < aFeatureCount; ++i) {
@@ -830,16 +832,17 @@ void mozilla_sampler_stop()
   mozilla::IOInterposer::Unregister(mozilla::IOInterposeObserver::OpAll,
                                     sInterposeObserver);
   sInterposeObserver = nullptr;
 
   sIsProfiling = false;
   sIsGPUProfiling = false;
   sIsLayersDump = false;
   sIsDisplayListDump = false;
+  sIsRestyleProfiling = false;
 
   if (Sampler::CanNotifyObservers()) {
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os)
       os->NotifyObservers(nullptr, "profiler-stopped", nullptr);
   }
 
   LOG("END   mozilla_sampler_stop");
@@ -878,16 +881,20 @@ bool mozilla_sampler_feature_active(cons
   if (strcmp(aName, "layersdump") == 0) {
     return sIsLayersDump;
   }
 
   if (strcmp(aName, "displaylistdump") == 0) {
     return sIsDisplayListDump;
   }
 
+  if (strcmp(aName, "restyle") == 0) {
+    return sIsRestyleProfiling;
+  }
+
   return false;
 }
 
 bool mozilla_sampler_is_active()
 {
   return sIsProfiling;
 }