Bug 1071056 - preserve unpaired START markers until next pop. r=bgirard
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2853,24 +2853,31 @@ nsDocShell::PopProfileTimelineMarkers(JS
// {name,start,end} JS object.
// Paint markers are different because paint is handled at root docShell level
// in the information that a paint was done is then stored at each sub
// docShell level but we can only be sure that a paint did happen in a
// docShell if an Layer marker type was recorded too.
nsTArray<mozilla::dom::ProfileTimelineMarker> profileTimelineMarkers;
+ // If we see an unpaired START, we keep it around for the next call
+ // to PopProfileTimelineMarkers. We store the kept START objects in
+ // this array.
+ decltype(mProfileTimelineMarkers) keptMarkers;
+
for (uint32_t i = 0; i < mProfileTimelineMarkers.Length(); ++i) {
ProfilerMarkerTracing* startPayload = static_cast<ProfilerMarkerTracing*>(
mProfileTimelineMarkers[i]->mPayload);
const char* startMarkerName = mProfileTimelineMarkers[i]->mName;
bool hasSeenPaintedLayer = false;
if (startPayload->GetMetaData() == TRACING_INTERVAL_START) {
+ bool hasSeenEnd = false;
+
// The assumption is that the devtools timeline flushes markers frequently
// enough for the amount of markers to always be small enough that the
// nested for loop isn't going to be a performance problem.
for (uint32_t j = i + 1; j < mProfileTimelineMarkers.Length(); ++j) {
ProfilerMarkerTracing* endPayload = static_cast<ProfilerMarkerTracing*>(
mProfileTimelineMarkers[j]->mPayload);
const char* endMarkerName = mProfileTimelineMarkers[j]->mName;
@@ -2888,25 +2895,36 @@ nsDocShell::PopProfileTimelineMarkers(JS
if (!isPaint || (isPaint && hasSeenPaintedLayer)) {
mozilla::dom::ProfileTimelineMarker marker;
marker.mName = NS_ConvertUTF8toUTF16(startMarkerName);
marker.mStart = mProfileTimelineMarkers[i]->mTime;
marker.mEnd = mProfileTimelineMarkers[j]->mTime;
profileTimelineMarkers.AppendElement(marker);
}
+ // We want the start to be dropped either way.
+ hasSeenEnd = true;
+
break;
}
}
+
+ // If we did not see the corresponding END, keep the START.
+ if (!hasSeenEnd) {
+ keptMarkers.AppendElement(mProfileTimelineMarkers[i]);
+ mProfileTimelineMarkers.RemoveElementAt(i);
+ --i;
+ }
}
}
ToJSValue(aCx, profileTimelineMarkers, aProfileTimelineMarkers);
ClearProfileTimelineMarkers();
+ mProfileTimelineMarkers.SwapElements(keptMarkers);
return NS_OK;
#else
return NS_ERROR_FAILURE;
#endif
}
float
@@ -2947,18 +2965,17 @@ nsDocShell::AddProfileTimelineMarker(con
#endif
}
void
nsDocShell::ClearProfileTimelineMarkers()
{
#ifdef MOZ_ENABLE_PROFILER_SPS
for (uint32_t i = 0; i < mProfileTimelineMarkers.Length(); ++i) {
- delete mProfileTimelineMarkers[i]->mPayload;
- mProfileTimelineMarkers[i]->mPayload = nullptr;
+ delete mProfileTimelineMarkers[i];
}
mProfileTimelineMarkers.Clear();
#endif
}
nsIDOMStorageManager*
nsDocShell::TopSessionStorageManager()
{
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -16,16 +16,17 @@
#include "nsIScrollable.h"
#include "nsITextScroll.h"
#include "nsIContentViewerContainer.h"
#include "nsIDOMStorageManager.h"
#include "nsDocLoader.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/TimeStamp.h"
#include "GeckoProfiler.h"
+#include "ProfilerMarkers.h"
// Helper Classes
#include "nsCOMPtr.h"
#include "nsPoint.h" // mCurrent/mDefaultScrollbarPreferences
#include "nsString.h"
#include "nsAutoPtr.h"
#include "nsThreadUtils.h"
@@ -954,21 +955,27 @@ private:
{
InternalProfileTimelineMarker(const char* aName,
ProfilerMarkerTracing* aPayload,
float aTime)
: mName(aName)
, mPayload(aPayload)
, mTime(aTime)
{}
+
+ ~InternalProfileTimelineMarker()
+ {
+ delete mPayload;
+ }
+
const char* mName;
ProfilerMarkerTracing* mPayload;
float mTime;
};
- nsTArray<nsAutoPtr<InternalProfileTimelineMarker>> mProfileTimelineMarkers;
+ nsTArray<InternalProfileTimelineMarker*> mProfileTimelineMarkers;
// Get the elapsed time (in millis) since the profile timeline recording
// started
float GetProfileTimelineDelta();
// Get rid of all the timeline markers accumulated so far
void ClearProfileTimelineMarkers();