Bug 1324941 - Add a profiler label and a profiler marker for DOMEvent dispatch. r?smaug draft
authorMarkus Stange <mstange@themasta.com>
Fri, 23 Dec 2016 12:44:35 +0100
changeset 454517 e4cc4a3c015fa40e756b0c579a5630f6fa468b58
parent 454516 4de3e445d12a69226cb7fb52ce3cb053a323ac2e
child 540729 17e710881e5e2c0b1baa17b4ebc503bd57fe9466
push id39954
push userbmo:mstange@themasta.com
push dateThu, 29 Dec 2016 16:16:37 +0000
reviewerssmaug
bugs1324941
milestone53.0a1
Bug 1324941 - Add a profiler label and a profiler marker for DOMEvent dispatch. r?smaug MozReview-Commit-ID: 9nyftWPKRVe
dom/events/EventListenerManager.cpp
tools/profiler/core/ProfilerMarkers.cpp
tools/profiler/public/ProfilerMarkers.h
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -24,18 +24,21 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/EventTargetBinding.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/TimelineConsumers.h"
 #include "mozilla/EventTimelineMarker.h"
+#include "mozilla/TimeStamp.h"
 
 #include "EventListenerService.h"
+#include "GeckoProfiler.h"
+#include "ProfilerMarkers.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsDOMCID.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsHtml5Atoms.h"
 #include "nsIContent.h"
@@ -1276,17 +1279,45 @@ EventListenerManager::HandleEventInterna
             if (listener->mFlags.mOnce) {
               // Move the listener to the stack before handling the event.
               // The order is important, otherwise the listener could be
               // called again inside the listener.
               listenerHolder.emplace(Move(*listener));
               listener = listenerHolder.ptr();
               hasRemovedListener = true;
             }
-            if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent, aCurrentTarget))) {
+
+            nsresult rv = NS_OK;
+            if (profiler_is_active()) {
+              // Add a profiler label and a profiler marker for the actual
+              // dispatch of the event.
+              // This is a very hot code path, so we need to make sure not to
+              // do this extra work when we're not profiling.
+              nsAutoString typeStr;
+              (*aDOMEvent)->GetType(typeStr);
+              PROFILER_LABEL_PRINTF("EventListenerManager", "HandleEventInternal",
+                                    js::ProfileEntry::Category::EVENTS,
+                                    "%s",
+                                    NS_LossyConvertUTF16toASCII(typeStr).get());
+              TimeStamp startTime = TimeStamp::Now();
+
+              rv = HandleEventSubType(listener, *aDOMEvent, aCurrentTarget);
+
+              TimeStamp endTime = TimeStamp::Now();
+              uint16_t phase;
+              (*aDOMEvent)->GetEventPhase(&phase);
+              PROFILER_MARKER_PAYLOAD("DOMEvent",
+                                      new DOMEventMarkerPayload(typeStr, phase,
+                                                                startTime,
+                                                                endTime));
+            } else {
+              rv = HandleEventSubType(listener, *aDOMEvent, aCurrentTarget);
+            }
+
+            if (NS_FAILED(rv)) {
               aEvent->mFlags.mExceptionWasRaised = true;
             }
             aEvent->mFlags.mInPassiveListener = false;
 
             if (needsEndEventMarker) {
               timelines->AddMarkerForDocShell(
                 docShell, "DOMEvent", MarkerTracingType::END);
             }
--- a/tools/profiler/core/ProfilerMarkers.cpp
+++ b/tools/profiler/core/ProfilerMarkers.cpp
@@ -149,16 +149,37 @@ IOMarkerPayload::StreamPayload(Spliceabl
 {
   streamCommonProps("io", aWriter, aUniqueStacks);
   aWriter.StringProperty("source", mSource);
   if (mFilename != nullptr) {
     aWriter.StringProperty("filename", mFilename);
   }
 }
 
+DOMEventMarkerPayload::DOMEventMarkerPayload(const nsAString& aType, uint16_t aPhase,
+                                             const mozilla::TimeStamp& aStartTime,
+                                             const mozilla::TimeStamp& aEndTime)
+  : ProfilerMarkerPayload(aStartTime, aEndTime, nullptr)
+  , mType(aType)
+  , mPhase(aPhase)
+{
+}
+
+DOMEventMarkerPayload::~DOMEventMarkerPayload()
+{
+}
+
+void
+DOMEventMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks)
+{
+  streamCommonProps("DOMEvent", aWriter, aUniqueStacks);
+  aWriter.StringProperty("type", NS_ConvertUTF16toUTF8(mType).get());
+  aWriter.IntProperty("phase", mPhase);
+}
+
 void
 ProfilerJSEventMarker(const char *event)
 {
     PROFILER_MARKER(event);
 }
 
 LayerTranslationPayload::LayerTranslationPayload(mozilla::layers::Layer* aLayer,
                                                  mozilla::gfx::Point aPoint)
--- a/tools/profiler/public/ProfilerMarkers.h
+++ b/tools/profiler/public/ProfilerMarkers.h
@@ -112,16 +112,32 @@ public:
   virtual void StreamPayload(SpliceableJSONWriter& aWriter,
                              UniqueStacks& aUniqueStacks) override;
 
 private:
   const char* mSource;
   char* mFilename;
 };
 
+class DOMEventMarkerPayload : public ProfilerMarkerPayload
+{
+public:
+  DOMEventMarkerPayload(const nsAString& aType, uint16_t aPhase,
+                        const mozilla::TimeStamp& aStartTime,
+                        const mozilla::TimeStamp& aEndTime);
+  ~DOMEventMarkerPayload();
+
+  virtual void StreamPayload(SpliceableJSONWriter& aWriter,
+                             UniqueStacks& aUniqueStacks) override;
+
+private:
+  nsString mType;
+  uint16_t mPhase;
+};
+
 /**
  * Contains the translation applied to a 2d layer so we can
  * track the layer position at each frame.
  */
 class LayerTranslationPayload : public ProfilerMarkerPayload
 {
 public:
   LayerTranslationPayload(mozilla::layers::Layer* aLayer,