Bug 1339289 - Give names to a lot of common timers (r=ehsan)
authorBill McCloskey <billm@mozilla.com>
Mon, 13 Feb 2017 15:45:23 -0800
changeset 343187 c64f0271649030394d2a29872513c9ec36521fa0
parent 343186 6ea3593a23e443f50f877ece94e14e9b3f6ffdf2
child 343188 daa7da2c260e302602d6f79cd35964fb02221399
push id31372
push usercbook@mozilla.com
push dateThu, 16 Feb 2017 12:16:10 +0000
treeherdermozilla-central@2737f66ad6ac [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1339289
milestone54.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 1339289 - Give names to a lot of common timers (r=ehsan) MozReview-Commit-ID: IMsv5bkyjBL
dom/base/nsContentSink.cpp
dom/base/nsContentSink.h
dom/base/nsWindowMemoryReporter.cpp
dom/events/EventStateManager.cpp
dom/html/nsHTMLDNSPrefetch.cpp
dom/media/DecoderDoctorDiagnostics.cpp
dom/storage/StorageCache.cpp
dom/xhr/XMLHttpRequestMainThread.cpp
layout/base/nsCaret.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
startupcache/StartupCache.cpp
toolkit/components/perfmonitoring/nsPerformanceStats.cpp
toolkit/components/telemetry/TelemetryIPCAccumulator.cpp
xpcom/threads/nsTimerImpl.cpp
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -60,16 +60,17 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsConten
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentSink)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsContentSink)
   NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
+  NS_INTERFACE_MAP_ENTRY(nsINamed)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocumentObserver)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsContentSink)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsContentSink)
   if (tmp->mDocument) {
     tmp->mDocument->RemoveObserver(tmp);
@@ -1622,8 +1623,21 @@ nsContentSink::NotifyDocElementCreated(n
       NotifyObservers(domDoc, "document-element-inserted",
                       EmptyString().get());
   }
 
   nsContentUtils::DispatchChromeEvent(aDoc, aDoc,
                                       NS_LITERAL_STRING("DOMDocElementInserted"),
                                       true, false);
 }
+
+NS_IMETHODIMP
+nsContentSink::GetName(nsACString& aName)
+{
+  aName.AssignASCII("nsContentSink_timer");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsContentSink::SetName(const char* aName)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
--- a/dom/base/nsContentSink.h
+++ b/dom/base/nsContentSink.h
@@ -71,24 +71,27 @@ extern mozilla::LazyLogModule gContentSi
 //----------------------------------------------------------------------
 
 // 1/2 second fudge factor for window creation
 #define NS_DELAY_FOR_WINDOW_CREATION  500000
 
 class nsContentSink : public nsICSSLoaderObserver,
                       public nsSupportsWeakReference,
                       public nsStubDocumentObserver,
-                      public nsITimerCallback
+                      public nsITimerCallback,
+                      public nsINamed
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsContentSink,
                                            nsICSSLoaderObserver)
     // nsITimerCallback
   NS_DECL_NSITIMERCALLBACK
 
+  NS_DECL_NSINAMED
+
   // nsICSSLoaderObserver
   NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet,
                               bool aWasAlternate,
                               nsresult aStatus) override;
 
   virtual nsresult ProcessMETATag(nsIContent* aContent);
 
   // nsIContentSink implementation helpers
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -651,18 +651,19 @@ nsWindowMemoryReporter::AsyncCheckForGho
   // prevents the timer from being completely starved if it is repeatedly killed
   // and restarted.
   int32_t timeSinceLastCheck = (TimeStamp::NowLoRes() - mLastCheckForGhostWindows).ToSeconds();
   int32_t timerDelay = (kTimeBetweenChecks - std::min(timeSinceLastCheck, kTimeBetweenChecks)) * PR_MSEC_PER_SEC;
 
   mCheckTimer = do_CreateInstance("@mozilla.org/timer;1");
 
   if (mCheckTimer) {
-    mCheckTimer->InitWithFuncCallback(CheckTimerFired, nullptr,
-                                      timerDelay, nsITimer::TYPE_ONE_SHOT);
+    mCheckTimer->InitWithNamedFuncCallback(CheckTimerFired, nullptr,
+                                           timerDelay, nsITimer::TYPE_ONE_SHOT,
+                                           "nsWindowMemoryReporter::AsyncCheckForGhostWindows_timer");
   }
 }
 
 void
 nsWindowMemoryReporter::ObserveAfterMinimizeMemoryUsage()
 {
   // Someone claims they've done enough GC/CCs so that all eligible windows
   // have been free'd.  So we deem that any windows which satisfy ghost
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -191,28 +191,31 @@ PrintDocTreeAll(nsIDocShellTreeItem* aIt
 #define NS_MODIFIER_ALT      4
 #define NS_MODIFIER_META     8
 #define NS_MODIFIER_OS       16
 
 /******************************************************************/
 /* mozilla::UITimerCallback                                       */
 /******************************************************************/
 
-class UITimerCallback final : public nsITimerCallback
+class UITimerCallback final :
+    public nsITimerCallback,
+    public nsINamed
 {
 public:
   UITimerCallback() : mPreviousCount(0) {}
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
+  NS_DECL_NSINAMED
 private:
   ~UITimerCallback() = default;
   uint32_t mPreviousCount;
 };
 
-NS_IMPL_ISUPPORTS(UITimerCallback, nsITimerCallback)
+NS_IMPL_ISUPPORTS(UITimerCallback, nsITimerCallback, nsINamed)
 
 // If aTimer is nullptr, this method always sends "user-interaction-inactive"
 // notification.
 NS_IMETHODIMP
 UITimerCallback::Notify(nsITimer* aTimer)
 {
   nsCOMPtr<nsIObserverService> obs =
     mozilla::services::GetObserverService();
@@ -228,16 +231,29 @@ UITimerCallback::Notify(nsITimer* aTimer
   } else {
     obs->NotifyObservers(nullptr, "user-interaction-active", nullptr);
     EventStateManager::UpdateUserActivityTimer();
   }
   mPreviousCount = gMouseOrKeyboardEventCounter;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+UITimerCallback::GetName(nsACString& aName)
+{
+  aName.AssignASCII("UITimerCallback_timer");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UITimerCallback::SetName(const char* aName)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 /******************************************************************/
 /* mozilla::OverOutElementsWrapper                                */
 /******************************************************************/
 
 OverOutElementsWrapper::OverOutElementsWrapper()
   : mLastOverFrame(nullptr)
 {
 }
--- a/dom/html/nsHTMLDNSPrefetch.cpp
+++ b/dom/html/nsHTMLDNSPrefetch.cpp
@@ -290,17 +290,18 @@ nsHTMLDNSPrefetch::nsDeferrals::Add(uint
     return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
     
   mEntries[mHead].mFlags = flags;
   mEntries[mHead].mElement = do_GetWeakReference(aElement);
   mHead = (mHead + 1) & sMaxDeferredMask;
 
   if (!mActiveLoaderCount && !mTimerArmed && mTimer) {
     mTimerArmed = true;
-    mTimer->InitWithFuncCallback(Tick, this, 2000, nsITimer::TYPE_ONE_SHOT);
+    mTimer->InitWithNamedFuncCallback(Tick, this, 2000, nsITimer::TYPE_ONE_SHOT,
+                                      "nsHTMLDNSPrefetch::nsDeferrals::Tick");
   }
   
   return NS_OK;
 }
 
 void
 nsHTMLDNSPrefetch::nsDeferrals::SubmitQueue()
 {
--- a/dom/media/DecoderDoctorDiagnostics.cpp
+++ b/dom/media/DecoderDoctorDiagnostics.cpp
@@ -44,24 +44,25 @@ struct NotificationAndReportStringId
 // small period of time, in order to provide a synthesized analysis.
 //
 // Referenced by the document through a nsINode property, mTimer, and
 // inter-task captures.
 // When notified that the document is dead, or when the timer expires but
 // nothing new happened, StopWatching() will remove the document property and
 // timer (if present), so no more work will happen and the watcher will be
 // destroyed once all references are gone.
-class DecoderDoctorDocumentWatcher : public nsITimerCallback
+class DecoderDoctorDocumentWatcher : public nsITimerCallback, public nsINamed
 {
 public:
   static already_AddRefed<DecoderDoctorDocumentWatcher>
   RetrieveOrCreate(nsIDocument* aDocument);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
+  NS_DECL_NSINAMED
 
   void AddDiagnostics(DecoderDoctorDiagnostics&& aDiagnostics,
                       const char* aCallSite);
 
 private:
   explicit DecoderDoctorDocumentWatcher(nsIDocument* aDocument);
   virtual ~DecoderDoctorDocumentWatcher();
 
@@ -113,17 +114,17 @@ private:
   typedef nsTArray<Diagnostics> DiagnosticsSequence;
   DiagnosticsSequence mDiagnosticsSequence;
 
   nsCOMPtr<nsITimer> mTimer; // Keep timer alive until we run.
   DiagnosticsSequence::size_type mDiagnosticsHandled = 0;
 };
 
 
-NS_IMPL_ISUPPORTS(DecoderDoctorDocumentWatcher, nsITimerCallback)
+NS_IMPL_ISUPPORTS(DecoderDoctorDocumentWatcher, nsITimerCallback, nsINamed)
 
 // static
 already_AddRefed<DecoderDoctorDocumentWatcher>
 DecoderDoctorDocumentWatcher::RetrieveOrCreate(nsIDocument* aDocument)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aDocument);
   RefPtr<DecoderDoctorDocumentWatcher> watcher =
@@ -639,16 +640,28 @@ DecoderDoctorDocumentWatcher::Notify(nsI
     // If more diagnostics come in, we'll treat them as another burst, separately.
     // 'true' to remove the property from the document.
     StopWatching(true);
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+DecoderDoctorDocumentWatcher::GetName(nsACString& aName)
+{
+  aName.AssignASCII("DecoderDoctorDocumentWatcher_timer");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DecoderDoctorDocumentWatcher::SetName(const char* aName)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
 
 void
 DecoderDoctorDiagnostics::StoreFormatDiagnostics(nsIDocument* aDocument,
                                                  const nsAString& aFormat,
                                                  bool aCanPlay,
                                                  const char* aCallSite)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/storage/StorageCache.cpp
+++ b/dom/storage/StorageCache.cpp
@@ -243,36 +243,49 @@ StorageCache::Preload()
 
   sDatabase->AsyncPreload(this);
 }
 
 namespace {
 
 // This class is passed to timer as a tick observer.  It refers the cache
 // and keeps it alive for a time.
-class StorageCacheHolder : public nsITimerCallback
+class StorageCacheHolder : public nsITimerCallback, public nsINamed
 {
   virtual ~StorageCacheHolder() {}
 
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD
   Notify(nsITimer* aTimer) override
   {
     mCache = nullptr;
     return NS_OK;
   }
 
+  NS_IMETHOD
+  GetName(nsACString& aName) override
+  {
+    aName.AssignASCII("StorageCacheHolder_timer");
+    return NS_OK;
+  }
+
+  NS_IMETHOD
+  SetName(const char* aName) override
+  {
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
   RefPtr<StorageCache> mCache;
 
 public:
   explicit StorageCacheHolder(StorageCache* aCache) : mCache(aCache) {}
 };
 
-NS_IMPL_ISUPPORTS(StorageCacheHolder, nsITimerCallback)
+NS_IMPL_ISUPPORTS(StorageCacheHolder, nsITimerCallback, nsINamed)
 
 } // namespace
 
 void
 StorageCache::KeepAlive()
 {
   // Missing reference back to the manager means the cache is not responsible
   // for its lifetime.  Used for keeping sessionStorage live forever.
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -376,16 +376,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY(nsIJSXMLHttpRequest)
   NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
   NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
   NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
+  NS_INTERFACE_MAP_ENTRY(nsINamed)
   NS_INTERFACE_MAP_ENTRY(nsISizeOfEventTarget)
 NS_INTERFACE_MAP_END_INHERITING(XMLHttpRequestEventTarget)
 
 NS_IMPL_ADDREF_INHERITED(XMLHttpRequestMainThread, XMLHttpRequestEventTarget)
 NS_IMPL_RELEASE_INHERITED(XMLHttpRequestMainThread, XMLHttpRequestEventTarget)
 
 NS_IMPL_EVENT_HANDLER(XMLHttpRequestMainThread, readystatechange)
 
@@ -3774,24 +3775,24 @@ XMLHttpRequestMainThread::BlobStoreCompl
   MOZ_ASSERT(mState != State::done);
 
   mResponseBlob = aBlob;
   mBlobStorage = nullptr;
 
   ChangeStateToDone();
 }
 
-nsresult
+NS_IMETHODIMP
 XMLHttpRequestMainThread::GetName(nsACString& aName)
 {
   aName.AssignLiteral("XMLHttpRequest");
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 XMLHttpRequestMainThread::SetName(const char* aName)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 // nsXMLHttpRequestXPCOMifier implementation
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLHttpRequestXPCOMifier)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -610,18 +610,19 @@ void nsCaret::ResetBlinking()
     if (NS_FAILED(err))
       return;
   }
 
   uint32_t blinkRate = static_cast<uint32_t>(
     LookAndFeel::GetInt(LookAndFeel::eIntID_CaretBlinkTime, 500));
   if (blinkRate > 0) {
     mBlinkCount = Preferences::GetInt("ui.caretBlinkCount", -1);
-    mBlinkTimer->InitWithFuncCallback(CaretBlinkCallback, this, blinkRate,
-                                      nsITimer::TYPE_REPEATING_SLACK);
+    mBlinkTimer->InitWithNamedFuncCallback(CaretBlinkCallback, this, blinkRate,
+                                           nsITimer::TYPE_REPEATING_SLACK,
+                                           "nsCaret::CaretBlinkCallback_timer");
   }
 }
 
 void nsCaret::StopBlinking()
 {
   if (mBlinkTimer)
   {
     mBlinkTimer->Cancel();
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -757,17 +757,18 @@ nsPresContext::PreferenceChanged(const c
   if (!mPrefChangedTimer)
   {
     // We will end up calling InvalidatePreferenceSheets one from each pres
     // context, but all it's doing is clearing its cached sheet pointers,
     // so it won't be wastefully recreating the sheet multiple times.
     // The first pres context that has its mPrefChangedTimer called will
     // be the one to cause the reconstruction of the pref style sheet.
     nsLayoutStylesheetCache::InvalidatePreferenceSheets();
-    mPrefChangedTimer = CreateTimer(PrefChangedUpdateTimerCallback, 0);
+    mPrefChangedTimer = CreateTimer(PrefChangedUpdateTimerCallback,
+                                    "PrefChangedUpdateTimerCallback", 0);
     if (!mPrefChangedTimer) {
       return;
     }
   }
   if (prefName.EqualsLiteral("nglayout.debug.paint_flashing") ||
       prefName.EqualsLiteral("nglayout.debug.paint_flashing_chrome")) {
     mPaintFlashingInitialized = false;
     return;
@@ -1516,17 +1517,18 @@ void
 nsPresContext::SetContainer(nsIDocShell* aDocShell)
 {
   if (aDocShell) {
     NS_ASSERTION(!(mContainer && mNeedsPrefUpdate),
                  "Should only need pref update if mContainer is null.");
     mContainer = static_cast<nsDocShell*>(aDocShell);
     if (mNeedsPrefUpdate) {
       if (!mPrefChangedTimer) {
-        mPrefChangedTimer = CreateTimer(PrefChangedUpdateTimerCallback, 0);
+        mPrefChangedTimer = CreateTimer(PrefChangedUpdateTimerCallback,
+                                        "PrefChangedUpdateTimerCallback", 0);
       }
       mNeedsPrefUpdate = false;
     }
   } else {
     mContainer = WeakPtr<nsDocShell>();
   }
   UpdateIsChrome();
   if (mContainer) {
@@ -2671,22 +2673,24 @@ nsPresContext::HasCachedStyleData()
     return mShell->DidInitialize();
   }
 
   return styleSet->HasCachedStyleData();
 }
 
 already_AddRefed<nsITimer>
 nsPresContext::CreateTimer(nsTimerCallbackFunc aCallback,
+                           const char* aName,
                            uint32_t aDelay)
 {
   nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
   if (timer) {
-    nsresult rv = timer->InitWithFuncCallback(aCallback, this, aDelay,
-                                              nsITimer::TYPE_ONE_SHOT);
+    nsresult rv = timer->InitWithNamedFuncCallback(aCallback, this, aDelay,
+                                                   nsITimer::TYPE_ONE_SHOT,
+                                                   aName);
     if (NS_SUCCEEDED(rv)) {
       return timer.forget();
     }
   }
 
   return nullptr;
 }
 
@@ -3092,16 +3096,17 @@ nsRootPresContext::InitApplyPluginGeomet
   // We'll apply the plugin geometry updates during the next compositing paint in this
   // presContext (either from nsPresShell::WillPaintWindow or from
   // nsPresShell::DidPaintWindow, depending on the platform).  But paints might
   // get optimized away if the old plugin geometry covers the invalid region,
   // so set a backup timer to do this too.  We want to make sure this
   // won't fire before our normal paint notifications, if those would
   // update the geometry, so set it for double the refresh driver interval.
   mApplyPluginGeometryTimer = CreateTimer(ApplyPluginGeometryUpdatesCallback,
+                                          "ApplyPluginGeometryUpdatesCallback",
                                           nsRefreshDriver::DefaultInterval() * 2);
 }
 
 void
 nsRootPresContext::CancelApplyPluginGeometryTimer()
 {
   if (mApplyPluginGeometryTimer) {
     mApplyPluginGeometryTimer->Cancel();
@@ -3271,17 +3276,19 @@ NotifyDidPaintForSubtreeCallback(nsITime
 }
 
 void
 nsRootPresContext::EnsureEventualDidPaintEvent()
 {
   if (mNotifyDidPaintTimer)
     return;
 
-  mNotifyDidPaintTimer = CreateTimer(NotifyDidPaintForSubtreeCallback, 100);
+  mNotifyDidPaintTimer = CreateTimer(NotifyDidPaintForSubtreeCallback,
+                                     "NotifyDidPaintForSubtreeCallback",
+                                     100);
 }
 
 void
 nsRootPresContext::AddWillPaintObserver(nsIRunnable* aRunnable)
 {
   if (!mWillPaintFallbackEvent.IsPending()) {
     mWillPaintFallbackEvent = new RunWillPaintObservers(this);
     NS_DispatchToMainThread(mWillPaintFallbackEvent.get());
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -1237,16 +1237,17 @@ protected:
   bool HavePendingInputEvent();
 
   // Can't be inline because we can't include nsStyleSet.h.
   bool HasCachedStyleData();
 
   // Creates a one-shot timer with the given aCallback & aDelay.
   // Returns a refcounted pointer to the timer (or nullptr on failure).
   already_AddRefed<nsITimer> CreateTimer(nsTimerCallbackFunc aCallback,
+                                         const char* aName,
                                          uint32_t aDelay);
 
   // IMPORTANT: The ownership implicit in the following member variables
   // has been explicitly checked.  If you add any members to this class,
   // please make the ownership explicit (pinkerton, scc).
 
   nsPresContextType     mType;
   // the nsPresShell owns a strong reference to the nsPresContext, and is responsible
--- a/startupcache/StartupCache.cpp
+++ b/startupcache/StartupCache.cpp
@@ -584,18 +584,19 @@ StartupCache::ResetStartupWriteTimer()
   mStartupWriteInitiated = false;
   nsresult rv;
   if (!mTimer)
     mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
   else
     rv = mTimer->Cancel();
   NS_ENSURE_SUCCESS(rv, rv);
   // Wait for 10 seconds, then write out the cache.
-  mTimer->InitWithFuncCallback(StartupCache::WriteTimeout, this, 60000,
-                               nsITimer::TYPE_ONE_SHOT);
+  mTimer->InitWithNamedFuncCallback(StartupCache::WriteTimeout, this, 60000,
+                                    nsITimer::TYPE_ONE_SHOT,
+                                    "StartupCache::WriteTimeout");
   return NS_OK;
 }
 
 bool
 StartupCache::StartupWriteComplete()
 {
   WaitOnWriteThread();
   return mStartupWriteInitiated && mTable.Count() == 0;
--- a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
+++ b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
@@ -560,20 +560,24 @@ PerformanceAlert::GetReason(uint32_t* re
  * class PendingAlertsCollector
  *
  */
 
 /**
  * A timer callback in charge of collecting the groups in
  * `mPendingAlerts` and triggering dispatch of performance alerts.
  */
-class PendingAlertsCollector final: public nsITimerCallback {
+class PendingAlertsCollector final :
+  public nsITimerCallback,
+  public nsINamed
+{
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
+  NS_DECL_NSINAMED
 
   explicit PendingAlertsCollector(nsPerformanceStatsService* service)
     : mService(service)
     , mPending(false)
   { }
 
   nsresult Start(uint32_t timerDelayMS);
   nsresult Dispose();
@@ -584,25 +588,38 @@ private:
   RefPtr<nsPerformanceStatsService> mService;
   bool mPending;
 
   nsCOMPtr<nsITimer> mTimer;
 
   mozilla::Vector<uint64_t> mJankLevels;
 };
 
-NS_IMPL_ISUPPORTS(PendingAlertsCollector, nsITimerCallback);
+NS_IMPL_ISUPPORTS(PendingAlertsCollector, nsITimerCallback, nsINamed);
 
 NS_IMETHODIMP
 PendingAlertsCollector::Notify(nsITimer*) {
   mPending = false;
   mService->NotifyJankObservers(mJankLevels);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+PendingAlertsCollector::GetName(nsACString& aName)
+{
+  aName.AssignASCII("PendingAlertsCollector_timer");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PendingAlertsCollector::SetName(const char* aName)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 nsresult
 PendingAlertsCollector::Start(uint32_t timerDelayMS) {
   if (mPending) {
     // Collector is already started.
     return NS_OK;
   }
 
   if (!mTimer) {
--- a/toolkit/components/telemetry/TelemetryIPCAccumulator.cpp
+++ b/toolkit/components/telemetry/TelemetryIPCAccumulator.cpp
@@ -66,33 +66,36 @@ void DoArmIPCTimerMainThread(const Stati
   gIPCTimerArming = false;
   if (gIPCTimerArmed) {
     return;
   }
   if (!gIPCTimer) {
     CallCreateInstance(NS_TIMER_CONTRACTID, &gIPCTimer);
   }
   if (gIPCTimer) {
-    gIPCTimer->InitWithFuncCallback(TelemetryIPCAccumulator::IPCTimerFired,
-                                    nullptr, kBatchTimeoutMs,
-                                    nsITimer::TYPE_ONE_SHOT);
+    gIPCTimer->InitWithNamedFuncCallback(TelemetryIPCAccumulator::IPCTimerFired,
+                                         nullptr, kBatchTimeoutMs,
+                                         nsITimer::TYPE_ONE_SHOT,
+                                         "TelemetryIPCAccumulator::IPCTimerFired");
     gIPCTimerArmed = true;
   }
 }
 
 void ArmIPCTimer(const StaticMutexAutoLock& lock)
 {
   if (gIPCTimerArmed || gIPCTimerArming) {
     return;
   }
   gIPCTimerArming = true;
   if (NS_IsMainThread()) {
     DoArmIPCTimerMainThread(lock);
   } else {
-    TelemetryIPCAccumulator::DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
+    TelemetryIPCAccumulator::DispatchToMainThread(NS_NewRunnableFunction(
+                                                    "TelemetryIPCAccumulator::ArmIPCTimer",
+                                                    []() -> void {
       StaticMutexAutoLock locker(gTelemetryIPCAccumulatorMutex);
       DoArmIPCTimerMainThread(locker);
     }));
   }
 }
 
 } // anonymous namespace
 
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -640,38 +640,38 @@ nsTimerImpl::GetName(nsACString& aName)
       } else if (cb.mName.is<Callback::NameFunc>()) {
         static const size_t buflen = 1024;
         char buf[buflen];
         cb.mName.as<Callback::NameFunc>()(
             mITimer, /* aAnonymize = */ true, cb.mClosure, buf, buflen);
         aName.Assign(buf);
       } else {
         MOZ_ASSERT(cb.mName.is<Callback::NameNothing>());
-        aName.AssignLiteral("Anonymous callback timer");
+        aName.AssignLiteral("Anonymous_callback_timer");
       }
       break;
 
     case Callback::Type::Interface:
       if (nsCOMPtr<nsINamed> named = do_QueryInterface(cb.mCallback.i)) {
         named->GetName(aName);
       } else {
-        aName.AssignLiteral("Anonymous interface timer");
+        aName.AssignLiteral("Anonymous_interface_timer");
       }
       break;
 
     case Callback::Type::Observer:
       if (nsCOMPtr<nsINamed> named = do_QueryInterface(cb.mCallback.o)) {
         named->GetName(aName);
       } else {
-        aName.AssignLiteral("Anonymous observer timer");
+        aName.AssignLiteral("Anonymous_observer_timer");
       }
       break;
 
     case Callback::Type::Unknown:
-      aName.AssignLiteral("Anonymous timer");
+      aName.AssignLiteral("Canceled_timer");
       break;
   }
 }
 
 nsTimer::~nsTimer()
 {
 }