Bug 1324941 - Add a profiler label and a profiler marker for DOMEvent dispatch. r?smaug
MozReview-Commit-ID: 9nyftWPKRVe
--- 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,