Bug 1100360: Convert ChromeHang annotations to use UniquePtr; r=vladan
authorAaron Klotz <aklotz@mozilla.com>
Tue, 30 Dec 2014 14:52:39 -0700
changeset 247521 0365efa5999a2a3536b598a76f2f28786b4da29b
parent 247520 f93e28755637c2bc51527442375bf5f23ec4a44b
child 247522 3f4164d111f6d662bb77ce2f925509231e5d26db
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvladan
bugs1100360
milestone37.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 1100360: Convert ChromeHang annotations to use UniquePtr; r=vladan
toolkit/components/telemetry/Telemetry.cpp
toolkit/components/telemetry/Telemetry.h
xpcom/threads/HangMonitor.cpp
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -229,82 +229,92 @@ CombinedStacks::SizeOfExcludingThis() co
 class HangReports {
 public:
   /**
    * This struct encapsulates information for an individual ChromeHang annotation.
    * mHangIndex is the index of the corresponding ChromeHang.
    */
   struct AnnotationInfo {
     AnnotationInfo(uint32_t aHangIndex,
-                   HangAnnotations* aAnnotations)
+                   UniquePtr<HangAnnotations> aAnnotations)
       : mHangIndex(aHangIndex)
-      , mAnnotations(aAnnotations)
+      , mAnnotations(Move(aAnnotations))
     {}
-    AnnotationInfo(const AnnotationInfo& aOther)
+    AnnotationInfo(AnnotationInfo&& aOther)
       : mHangIndex(aOther.mHangIndex)
-      , mAnnotations(aOther.mAnnotations)
+      , mAnnotations(Move(aOther.mAnnotations))
     {}
     ~AnnotationInfo() {}
+    AnnotationInfo& operator=(AnnotationInfo&& aOther)
+    {
+      mHangIndex = aOther.mHangIndex;
+      mAnnotations = Move(aOther.mAnnotations);
+      return *this;
+    }
     uint32_t mHangIndex;
-    mutable nsAutoPtr<HangAnnotations> mAnnotations;
+    UniquePtr<HangAnnotations> mAnnotations;
+
+  private:
+    // Force move constructor
+    AnnotationInfo(const AnnotationInfo& aOther) MOZ_DELETE;
+    void operator=(const AnnotationInfo& aOther) MOZ_DELETE;
   };
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   void AddHang(const Telemetry::ProcessedStack& aStack, uint32_t aDuration,
                int32_t aSystemUptime, int32_t aFirefoxUptime,
-               HangAnnotations* aAnnotations);
+               UniquePtr<HangAnnotations> aAnnotations);
   uint32_t GetDuration(unsigned aIndex) const;
   int32_t GetSystemUptime(unsigned aIndex) const;
   int32_t GetFirefoxUptime(unsigned aIndex) const;
-  const std::vector<AnnotationInfo>& GetAnnotationInfo() const;
+  const nsTArray<AnnotationInfo>& GetAnnotationInfo() const;
   const CombinedStacks& GetStacks() const;
 private:
   /**
    * This struct encapsulates the data for an individual ChromeHang, excluding
    * annotations.
    */
   struct HangInfo {
     // Hang duration (in seconds)
     uint32_t mDuration;
     // System uptime (in minutes) at the time of the hang
     int32_t mSystemUptime;
     // Firefox uptime (in minutes) at the time of the hang
     int32_t mFirefoxUptime;
   };
   std::vector<HangInfo> mHangInfo;
-  std::vector<AnnotationInfo> mAnnotationInfo;
+  nsTArray<AnnotationInfo> mAnnotationInfo;
   CombinedStacks mStacks;
 };
 
 void
 HangReports::AddHang(const Telemetry::ProcessedStack& aStack,
                      uint32_t aDuration,
                      int32_t aSystemUptime,
                      int32_t aFirefoxUptime,
-                     HangAnnotations* aAnnotations) {
+                     UniquePtr<HangAnnotations> aAnnotations) {
   HangInfo info = { aDuration, aSystemUptime, aFirefoxUptime };
   mHangInfo.push_back(info);
   if (aAnnotations) {
     AnnotationInfo ainfo(static_cast<uint32_t>(mHangInfo.size() - 1),
-                         aAnnotations);
-    mAnnotationInfo.push_back(ainfo);
+                         Move(aAnnotations));
+    mAnnotationInfo.AppendElement(Move(ainfo));
   }
   mStacks.AddStack(aStack);
 }
 
 size_t
 HangReports::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
   size_t n = 0;
   n += mStacks.SizeOfExcludingThis();
   // This is a crude approximation. See comment on
   // CombinedStacks::SizeOfExcludingThis.
   n += mHangInfo.capacity() * sizeof(HangInfo);
-  n += mAnnotationInfo.capacity() * sizeof(AnnotationInfo);
-  for (std::vector<AnnotationInfo>::const_iterator i = mAnnotationInfo.begin(),
-       e = mAnnotationInfo.end(); i != e; ++i) {
-    n += i->mAnnotations->SizeOfIncludingThis(aMallocSizeOf);
+  n += mAnnotationInfo.Capacity() * sizeof(AnnotationInfo);
+  for (int32_t i = 0, l = mAnnotationInfo.Length(); i < l; ++i) {
+    n += mAnnotationInfo[i].mAnnotations->SizeOfIncludingThis(aMallocSizeOf);
   }
   return n;
 }
 
 const CombinedStacks&
 HangReports::GetStacks() const {
   return mStacks;
 }
@@ -319,17 +329,17 @@ HangReports::GetSystemUptime(unsigned aI
   return mHangInfo[aIndex].mSystemUptime;
 }
 
 int32_t
 HangReports::GetFirefoxUptime(unsigned aIndex) const {
   return mHangInfo[aIndex].mFirefoxUptime;
 }
 
-const std::vector<HangReports::AnnotationInfo>&
+const nsTArray<HangReports::AnnotationInfo>&
 HangReports::GetAnnotationInfo() const {
   return mAnnotationInfo;
 }
 
 /**
  * IOInterposeObserver recording statistics of main-thread I/O during execution,
  * aimed at consumption by TelemetryImpl
  */
@@ -811,17 +821,17 @@ public:
   static void ShutdownTelemetry();
   static void RecordSlowStatement(const nsACString &sql, const nsACString &dbName,
                                   uint32_t delay);
 #if defined(MOZ_ENABLE_PROFILER_SPS)
   static void RecordChromeHang(uint32_t aDuration,
                                Telemetry::ProcessedStack &aStack,
                                int32_t aSystemUptime,
                                int32_t aFirefoxUptime,
-                               HangAnnotations* aAnnotations);
+                               UniquePtr<HangAnnotations> aAnnotations);
 #endif
   static void RecordThreadHangStats(Telemetry::ThreadHangStats& aStats);
   static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id);
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
   struct Stat {
     uint32_t hitCount;
     uint32_t totalTime;
   };
@@ -2400,55 +2410,54 @@ TelemetryImpl::GetChromeHangs(JSContext 
       return NS_ERROR_FAILURE;
     }
     if (!JS_SetElement(cx, systemUptimeArray, i, mHangReports.GetSystemUptime(i))) {
       return NS_ERROR_FAILURE;
     }
     if (!JS_SetElement(cx, firefoxUptimeArray, i, mHangReports.GetFirefoxUptime(i))) {
       return NS_ERROR_FAILURE;
     }
-    const std::vector<HangReports::AnnotationInfo>& annotationInfo =
+    const nsTArray<HangReports::AnnotationInfo>& annotationInfo =
                                                 mHangReports.GetAnnotationInfo();
-    uint32_t annotationsArrayIndex = 0;
-    for (std::vector<HangReports::AnnotationInfo>::const_iterator
-         ai = annotationInfo.begin(), e = annotationInfo.end(); ai != e;
-         ++ai, ++annotationsArrayIndex) {
+    for (uint32_t iterIndex = 0, arrayLen = annotationInfo.Length();
+         iterIndex < arrayLen; ++iterIndex) {
       JS::Rooted<JSObject*> keyValueArray(cx, JS_NewArrayObject(cx, 0));
       if (!keyValueArray) {
         return NS_ERROR_FAILURE;
       }
       JS::RootedValue indexValue(cx);
-      indexValue.setNumber(ai->mHangIndex);
+      indexValue.setNumber(annotationInfo[iterIndex].mHangIndex);
       if (!JS_SetElement(cx, keyValueArray, 0, indexValue)) {
         return NS_ERROR_FAILURE;
       }
       JS::Rooted<JSObject*> jsAnnotation(cx, JS_NewObject(cx, nullptr,
                                                           JS::NullPtr(),
                                                           JS::NullPtr()));
       if (!jsAnnotation) {
         return NS_ERROR_FAILURE;
       }
       nsAutoPtr<HangAnnotations::Enumerator> annotationsEnum;
-      if (!ai->mAnnotations->GetEnumerator(annotationsEnum.StartAssignment())) {
+      if (!annotationInfo[iterIndex].mAnnotations->GetEnumerator(
+            annotationsEnum.StartAssignment())) {
         return NS_ERROR_FAILURE;
       }
       nsAutoString  key;
       nsAutoString  value;
       while (annotationsEnum->Next(key, value)) {
         JS::RootedValue jsValue(cx);
         jsValue.setString(JS_NewUCStringCopyN(cx, value.get(), value.Length()));
         if (!JS_DefineUCProperty(cx, jsAnnotation, key.get(), key.Length(),
                                  jsValue, JSPROP_ENUMERATE)) {
           return NS_ERROR_FAILURE;
         }
       }
       if (!JS_SetElement(cx, keyValueArray, 1, jsAnnotation)) {
         return NS_ERROR_FAILURE;
       }
-      if (!JS_SetElement(cx, annotationsArray, annotationsArrayIndex,
+      if (!JS_SetElement(cx, annotationsArray, iterIndex,
                          keyValueArray)) {
         return NS_ERROR_FAILURE;
       }
     }
   }
 
   return NS_OK;
 }
@@ -3195,26 +3204,26 @@ TelemetryImpl::RecordSlowStatement(const
 }
 
 #if defined(MOZ_ENABLE_PROFILER_SPS)
 void
 TelemetryImpl::RecordChromeHang(uint32_t aDuration,
                                 Telemetry::ProcessedStack &aStack,
                                 int32_t aSystemUptime,
                                 int32_t aFirefoxUptime,
-                                HangAnnotations* aAnnotations)
+                                UniquePtr<HangAnnotations> aAnnotations)
 {
   if (!sTelemetry || !sTelemetry->mCanRecord)
     return;
 
   MutexAutoLock hangReportMutex(sTelemetry->mHangReportsMutex);
 
   sTelemetry->mHangReports.AddHang(aStack, aDuration,
                                    aSystemUptime, aFirefoxUptime,
-                                   aAnnotations);
+                                   Move(aAnnotations));
 }
 #endif
 
 void
 TelemetryImpl::RecordThreadHangStats(Telemetry::ThreadHangStats& aStats)
 {
   if (!sTelemetry || !sTelemetry->mCanRecord)
     return;
@@ -3468,20 +3477,21 @@ void Init()
   MOZ_ASSERT(telemetryService);
 }
 
 #if defined(MOZ_ENABLE_PROFILER_SPS)
 void RecordChromeHang(uint32_t duration,
                       ProcessedStack &aStack,
                       int32_t aSystemUptime,
                       int32_t aFirefoxUptime,
-                      HangAnnotations* aAnnotations)
+                      UniquePtr<HangAnnotations> aAnnotations)
 {
   TelemetryImpl::RecordChromeHang(duration, aStack,
-                                  aSystemUptime, aFirefoxUptime, aAnnotations);
+                                  aSystemUptime, aFirefoxUptime,
+                                  Move(aAnnotations));
 }
 #endif
 
 void RecordThreadHangStats(ThreadHangStats& aStats)
 {
   TelemetryImpl::RecordThreadHangStats(aStats);
 }
 
--- a/toolkit/components/telemetry/Telemetry.h
+++ b/toolkit/components/telemetry/Telemetry.h
@@ -233,17 +233,18 @@ class ProcessedStack;
  * @param aFirefoxUptime - Firefox uptime at the time of the hang, in minutes
  * @param aAnnotations - Any annotations to be added to the report
  */
 #if defined(MOZ_ENABLE_PROFILER_SPS)
 void RecordChromeHang(uint32_t aDuration,
                       ProcessedStack &aStack,
                       int32_t aSystemUptime,
                       int32_t aFirefoxUptime,
-                      mozilla::HangMonitor::HangAnnotations* aAnnotations = nullptr);
+                      mozilla::UniquePtr<mozilla::HangMonitor::HangAnnotations>
+                              aAnnotations);
 #endif
 
 class ThreadHangStats;
 
 /**
  * Move a ThreadHangStats to Telemetry storage. Normally Telemetry queries
  * for active ThreadHangStats through BackgroundHangMonitor, but once a
  * thread exits, the thread's copy of ThreadHangStats needs to be moved to
--- a/xpcom/threads/HangMonitor.cpp
+++ b/xpcom/threads/HangMonitor.cpp
@@ -3,24 +3,24 @@
 /* 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/HangMonitor.h"
 
 #include <set>
 
+#include "mozilla/Atomics.h"
 #include "mozilla/BackgroundHangMonitor.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/ProcessedStack.h"
 #include "mozilla/Telemetry.h"
-#include "mozilla/ProcessedStack.h"
-#include "mozilla/Atomics.h"
 #include "mozilla/StaticPtr.h"
-#include "nsAutoPtr.h"
+#include "mozilla/UniquePtr.h"
 #include "nsReadableUtils.h"
 #include "nsStackWalk.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
@@ -358,17 +358,17 @@ ThreadMain(void*)
   // run twice to trigger hang protection.
   PRIntervalTime lastTimestamp = 0;
   int waitCount = 0;
 
 #ifdef REPORT_CHROME_HANGS
   Telemetry::ProcessedStack stack;
   int32_t systemUptime = -1;
   int32_t firefoxUptime = -1;
-  nsAutoPtr<ChromeHangAnnotations> annotations = new ChromeHangAnnotations();
+  auto annotations = MakeUnique<ChromeHangAnnotations>();
 #endif
 
   while (true) {
     if (gShutdown) {
       return; // Exit the thread
     }
 
     // avoid rereading the volatile value in this loop
@@ -405,20 +405,19 @@ ThreadMain(void*)
         }
       }
 #endif
     } else {
 #ifdef REPORT_CHROME_HANGS
       if (waitCount >= 2) {
         uint32_t hangDuration = PR_IntervalToSeconds(now - lastTimestamp);
         Telemetry::RecordChromeHang(hangDuration, stack, systemUptime,
-                                    firefoxUptime, annotations->IsEmpty() ?
-                                    nullptr : annotations.forget());
+                                    firefoxUptime, Move(annotations));
         stack.Clear();
-        annotations = new ChromeHangAnnotations();
+        annotations = MakeUnique<ChromeHangAnnotations>();
       }
 #endif
       lastTimestamp = timestamp;
       waitCount = 0;
     }
 
     PRIntervalTime timeout;
     if (gTimeout <= 0) {