Bug 1183219 - Backed out last 5 changesets for bustage, r=me on a CLOSED TREE

This commit is contained in:
Victor Porof 2015-07-18 10:21:09 -04:00
parent 6609b1944f
commit 0267134d00
17 changed files with 290 additions and 410 deletions

View File

@ -2929,17 +2929,29 @@ nsDocShell::HistoryTransactionRemoved(int32_t aIndex)
return NS_OK;
}
unsigned long nsDocShell::gProfileTimelineRecordingsCount = 0;
mozilla::LinkedList<nsDocShell::ObservedDocShell>* nsDocShell::gObservedDocShells = nullptr;
NS_IMETHODIMP
nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
{
bool currentValue = nsIDocShell::GetRecordProfileTimelineMarkers();
if (currentValue != aValue) {
if (aValue) {
TimelineConsumers::AddConsumer(this);
++gProfileTimelineRecordingsCount;
UseEntryScriptProfiling();
MOZ_ASSERT(!mObserved);
mObserved.reset(new ObservedDocShell(this));
GetOrCreateObservedDocShells().insertFront(mObserved.get());
} else {
TimelineConsumers::RemoveConsumer(this);
--gProfileTimelineRecordingsCount;
UnuseEntryScriptProfiling();
mObserved.reset(nullptr);
ClearProfileTimelineMarkers();
}
}
@ -2955,13 +2967,124 @@ nsDocShell::GetRecordProfileTimelineMarkers(bool* aValue)
nsresult
nsDocShell::PopProfileTimelineMarkers(
JSContext* aCx,
JS::MutableHandle<JS::Value> aStore)
JSContext* aCx,
JS::MutableHandle<JS::Value> aProfileTimelineMarkers)
{
if (!mObserved->PopMarkers(aCx, aStore)) {
// Looping over all markers gathered so far at the docShell level, whenever a
// START marker is found, look for the corresponding END marker and build a
// {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;
SequenceRooter<mozilla::dom::ProfileTimelineMarker> rooter(
aCx, &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.
nsTArray<UniquePtr<TimelineMarker>> keptMarkers;
for (uint32_t i = 0; i < mProfileTimelineMarkers.Length(); ++i) {
UniquePtr<TimelineMarker>& startPayload = mProfileTimelineMarkers[i];
const char* startMarkerName = startPayload->GetName();
bool hasSeenPaintedLayer = false;
bool isPaint = strcmp(startMarkerName, "Paint") == 0;
// If we are processing a Paint marker, we append information from
// all the embedded Layer markers to this array.
dom::Sequence<dom::ProfileTimelineLayerRect> layerRectangles;
// If this is a TRACING_TIMESTAMP marker, there's no corresponding "end"
// marker, as it's a single unit of time, not a duration, create the final
// marker here.
if (startPayload->GetMetaData() == TRACING_TIMESTAMP) {
mozilla::dom::ProfileTimelineMarker* marker =
profileTimelineMarkers.AppendElement();
marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName());
marker->mStart = startPayload->GetTime();
marker->mEnd = startPayload->GetTime();
marker->mStack = startPayload->GetStack();
startPayload->AddDetails(aCx, *marker);
continue;
}
if (startPayload->GetMetaData() == TRACING_INTERVAL_START) {
bool hasSeenEnd = false;
// DOM events can be nested, so we must take care when searching
// for the matching end. It doesn't hurt to apply this logic to
// all event types.
uint32_t markerDepth = 0;
// 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) {
UniquePtr<TimelineMarker>& endPayload = mProfileTimelineMarkers[j];
const char* endMarkerName = endPayload->GetName();
// Look for Layer markers to stream out paint markers.
if (isPaint && strcmp(endMarkerName, "Layer") == 0) {
hasSeenPaintedLayer = true;
endPayload->AddLayerRectangles(layerRectangles);
}
if (!startPayload->Equals(*endPayload)) {
continue;
}
// Pair start and end markers.
if (endPayload->GetMetaData() == TRACING_INTERVAL_START) {
++markerDepth;
} else if (endPayload->GetMetaData() == TRACING_INTERVAL_END) {
if (markerDepth > 0) {
--markerDepth;
} else {
// But ignore paint start/end if no layer has been painted.
if (!isPaint || (isPaint && hasSeenPaintedLayer)) {
mozilla::dom::ProfileTimelineMarker* marker =
profileTimelineMarkers.AppendElement();
marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName());
marker->mStart = startPayload->GetTime();
marker->mEnd = endPayload->GetTime();
marker->mStack = startPayload->GetStack();
if (isPaint) {
marker->mRectangles.Construct(layerRectangles);
}
startPayload->AddDetails(aCx, *marker);
endPayload->AddDetails(aCx, *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(Move(mProfileTimelineMarkers[i]));
mProfileTimelineMarkers.RemoveElementAt(i);
--i;
}
}
}
mProfileTimelineMarkers.SwapElements(keptMarkers);
if (!ToJSValue(aCx, profileTimelineMarkers, aProfileTimelineMarkers)) {
JS_ClearPendingException(aCx);
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
@ -2974,6 +3097,24 @@ nsDocShell::Now(DOMHighResTimeStamp* aWhen)
return NS_OK;
}
void
nsDocShell::AddProfileTimelineMarker(const char* aName,
TracingMetadata aMetaData)
{
if (IsObserved()) {
TimelineMarker* marker = new TimelineMarker(this, aName, aMetaData);
mProfileTimelineMarkers.AppendElement(marker);
}
}
void
nsDocShell::AddProfileTimelineMarker(UniquePtr<TimelineMarker>&& aMarker)
{
if (IsObserved()) {
mProfileTimelineMarkers.AppendElement(Move(aMarker));
}
}
NS_IMETHODIMP
nsDocShell::SetWindowDraggingAllowed(bool aValue)
{
@ -3003,6 +3144,12 @@ nsDocShell::GetWindowDraggingAllowed(bool* aValue)
return NS_OK;
}
void
nsDocShell::ClearProfileTimelineMarkers()
{
mProfileTimelineMarkers.Clear();
}
nsIDOMStorageManager*
nsDocShell::TopSessionStorageManager()
{
@ -13840,7 +13987,7 @@ nsDocShell::NotifyJSRunToCompletionStart(const char* aReason,
MakeUnique<JavascriptTimelineMarker>(this, "Javascript", aReason,
aFunctionName, aFilename,
aLineNumber);
TimelineConsumers::AddMarkerForDocShell(this, Move(marker));
AddProfileTimelineMarker(Move(marker));
}
mJSRunToCompletionDepth++;
}
@ -13853,7 +14000,7 @@ nsDocShell::NotifyJSRunToCompletionStop()
// If last stop, mark interval end.
mJSRunToCompletionDepth--;
if (timelineOn && mJSRunToCompletionDepth == 0) {
TimelineConsumers::AddMarkerForDocShell(this, "Javascript", TRACING_INTERVAL_END);
AddProfileTimelineMarker("Javascript", TRACING_INTERVAL_END);
}
}

View File

@ -34,8 +34,6 @@
#include "nsThreadUtils.h"
#include "nsContentUtils.h"
#include "timeline/TimelineMarker.h"
#include "timeline/TimelineConsumers.h"
#include "timeline/ObservedDocShell.h"
// Threshold value in ms for META refresh based redirects
#define REFRESH_REDIRECT_TIMER 15000
@ -258,24 +256,53 @@ public:
// is no longer applied
void NotifyAsyncPanZoomStopped();
// Add new profile timeline markers to this docShell. This will only add
// markers if the docShell is currently recording profile timeline markers.
// See nsIDocShell::recordProfileTimelineMarkers
void AddProfileTimelineMarker(const char* aName, TracingMetadata aMetaData);
void AddProfileTimelineMarker(mozilla::UniquePtr<TimelineMarker>&& aMarker);
// Global counter for how many docShells are currently recording profile
// timeline markers
static unsigned long gProfileTimelineRecordingsCount;
class ObservedDocShell : public mozilla::LinkedListElement<ObservedDocShell>
{
public:
explicit ObservedDocShell(nsDocShell* aDocShell)
: mDocShell(aDocShell)
{ }
nsDocShell* operator*() const { return mDocShell.get(); }
private:
nsRefPtr<nsDocShell> mDocShell;
};
private:
// An observed docshell wrapper is created when recording markers is enabled.
mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
static mozilla::LinkedList<ObservedDocShell>* gObservedDocShells;
static mozilla::LinkedList<ObservedDocShell>& GetOrCreateObservedDocShells()
{
if (!gObservedDocShells) {
gObservedDocShells = new mozilla::LinkedList<ObservedDocShell>();
}
return *gObservedDocShells;
}
// Never null if timeline markers are being observed.
mozilla::UniquePtr<ObservedDocShell> mObserved;
// Return true if timeline markers are being observed for this docshell. False
// otherwise.
bool IsObserved() const { return !!mObserved; }
// It is necessary to allow adding a timeline marker wherever a docshell
// instance is available. This operation happens frequently and needs to
// be very fast, so instead of using a Map or having to search for some
// docshell-specific markers storage, a pointer to an `ObservedDocShell` is
// is stored on docshells directly.
friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell* aDocShell);
friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell* aDocShell);
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
nsDocShell* aDocShell, UniquePtr<TimelineMarker>&& aMarker);
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
nsDocShell* aDocShell, const char* aName, TracingMetadata aMetaData);
public:
static const mozilla::LinkedList<ObservedDocShell>& GetObservedDocShells()
{
return GetOrCreateObservedDocShells();
}
// Tell the favicon service that aNewURI has the same favicon as aOldURI.
static void CopyFavicon(nsIURI* aOldURI,
nsIURI* aNewURI,
@ -983,6 +1010,11 @@ private:
// has been called without a matching NotifyRunToCompletionStop.
uint32_t mJSRunToCompletionDepth;
nsTArray<mozilla::UniquePtr<TimelineMarker>> mProfileTimelineMarkers;
// Get rid of all the timeline markers accumulated so far
void ClearProfileTimelineMarkers();
// Separate function to do the actual name (i.e. not _top, _self etc.)
// searching for FindItemWithName.
nsresult DoFindItemWithName(const char16_t* aName,

View File

@ -6,32 +6,66 @@
#include "mozilla/AutoGlobalTimelineMarker.h"
#include "mozilla/TimelineConsumers.h"
#include "MainThreadUtils.h"
#include "nsDocShell.h"
namespace mozilla {
void
AutoGlobalTimelineMarker::PopulateDocShells()
{
const LinkedList<nsDocShell::ObservedDocShell>& docShells =
nsDocShell::GetObservedDocShells();
MOZ_ASSERT(!docShells.isEmpty());
for (const nsDocShell::ObservedDocShell* ds = docShells.getFirst();
ds;
ds = ds->getNext()) {
mOk = mDocShells.append(**ds);
if (!mOk) {
return;
}
}
}
AutoGlobalTimelineMarker::AutoGlobalTimelineMarker(const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: mName(aName)
: mOk(true)
, mDocShells()
, mName(aName)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(NS_IsMainThread());
if (TimelineConsumers::IsEmpty()) {
if (nsDocShell::gProfileTimelineRecordingsCount == 0) {
return;
}
TimelineConsumers::AddMarkerToAllObservedDocShells(mName, TRACING_INTERVAL_START);
PopulateDocShells();
if (!mOk) {
// If we don't successfully populate our vector with *all* docshells being
// observed, don't add markers to *any* of them.
return;
}
for (Vector<nsRefPtr<nsDocShell>>::Range range = mDocShells.all();
!range.empty();
range.popFront()) {
range.front()->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
}
}
AutoGlobalTimelineMarker::~AutoGlobalTimelineMarker()
{
if (TimelineConsumers::IsEmpty()) {
if (!mOk) {
return;
}
TimelineConsumers::AddMarkerToAllObservedDocShells(mName, TRACING_INTERVAL_END);
for (Vector<nsRefPtr<nsDocShell>>::Range range = mDocShells.all();
!range.empty();
range.popFront()) {
range.front()->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
}
}
} // namespace mozilla

View File

@ -8,6 +8,7 @@
#define mozilla_AutoGlobalTimelineMarker_h_
#include "mozilla/GuardObjects.h"
#include "mozilla/Vector.h"
#include "nsRefPtr.h"
class nsDocShell;
@ -33,12 +34,21 @@ class MOZ_STACK_CLASS AutoGlobalTimelineMarker
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
// True as long as no operation has failed, eg due to OOM.
bool mOk;
// The set of docshells that are being observed and will get markers.
mozilla::Vector<nsRefPtr<nsDocShell>> mDocShells;
// The name of the marker we are adding.
const char* mName;
void PopulateDocShells();
public:
explicit AutoGlobalTimelineMarker(const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
~AutoGlobalTimelineMarker();
AutoGlobalTimelineMarker(const AutoGlobalTimelineMarker& aOther) = delete;

View File

@ -6,36 +6,41 @@
#include "mozilla/AutoTimelineMarker.h"
#include "mozilla/TimelineConsumers.h"
#include "MainThreadUtils.h"
#include "nsDocShell.h"
namespace mozilla {
bool
AutoTimelineMarker::DocShellIsRecording(nsDocShell& aDocShell)
{
bool isRecording = false;
if (nsDocShell::gProfileTimelineRecordingsCount > 0) {
aDocShell.GetRecordProfileTimelineMarkers(&isRecording);
}
return isRecording;
}
AutoTimelineMarker::AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: mName(aName)
, mDocShell(nullptr)
: mDocShell(nullptr)
, mName(aName)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aDocShell);
if (TimelineConsumers::IsEmpty()) {
return;
nsDocShell* docShell = static_cast<nsDocShell*>(aDocShell);
if (docShell && DocShellIsRecording(*docShell)) {
mDocShell = docShell;
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
}
mDocShell = static_cast<nsDocShell*>(aDocShell);
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, TRACING_INTERVAL_START);
}
AutoTimelineMarker::~AutoTimelineMarker()
{
if (TimelineConsumers::IsEmpty()) {
return;
if (mDocShell) {
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
}
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, TRACING_INTERVAL_END);
}
} // namespace mozilla

View File

@ -32,11 +32,10 @@ class MOZ_STACK_CLASS AutoTimelineMarker
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
// The name of the marker we are adding.
nsRefPtr<nsDocShell> mDocShell;
const char* mName;
// The docshell that is associated with this marker.
nsRefPtr<nsDocShell> mDocShell;
bool DocShellIsRecording(nsDocShell& aDocShell);
public:
explicit AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName

View File

@ -1,144 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "ObservedDocShell.h"
#include "TimelineMarker.h"
#include "mozilla/Move.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ToJSValue.h"
namespace mozilla {
using dom::ProfileTimelineMarker;
using dom::ProfileTimelineLayerRect;
ObservedDocShell::ObservedDocShell(nsDocShell* aDocShell)
: mDocShell(aDocShell)
{}
void
ObservedDocShell::AddMarker(const char* aName, TracingMetadata aMetaData)
{
TimelineMarker* marker = new TimelineMarker(mDocShell, aName, aMetaData);
mTimelineMarkers.AppendElement(marker);
}
void
ObservedDocShell::AddMarker(UniquePtr<TimelineMarker>&& aMarker)
{
mTimelineMarkers.AppendElement(Move(aMarker));
}
void
ObservedDocShell::ClearMarkers()
{
mTimelineMarkers.Clear();
}
bool
ObservedDocShell::PopMarkers(JSContext* aCx,
JS::MutableHandle<JS::Value> aStore)
{
nsTArray<ProfileTimelineMarker> webidlStore;
dom::SequenceRooter<ProfileTimelineMarker> rooter(aCx, &webidlStore);
// If we see an unpaired START, we keep it around for the next call
// to ObservedDocShell::PopMarkers. We store the kept START objects here.
nsTArray<UniquePtr<TimelineMarker>> keptStartMarkers;
for (uint32_t i = 0; i < mTimelineMarkers.Length(); ++i) {
UniquePtr<TimelineMarker>& startPayload = mTimelineMarkers[i];
// If this is a TRACING_TIMESTAMP marker, there's no corresponding END
// as it's a single unit of time, not a duration.
if (startPayload->GetMetaData() == TRACING_TIMESTAMP) {
ProfileTimelineMarker* marker = webidlStore.AppendElement();
marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName());
marker->mStart = startPayload->GetTime();
marker->mEnd = startPayload->GetTime();
marker->mStack = startPayload->GetStack();
startPayload->AddDetails(aCx, *marker);
continue;
}
// Whenever a START marker is found, look for the corresponding END
// and build a {name,start,end} JS object.
if (startPayload->GetMetaData() == TRACING_INTERVAL_START) {
bool hasSeenEnd = false;
// "Paint" markers are different because painting is handled at root
// docshell level. The information that a paint was done is stored at
// sub-docshell level, but we can only be sure that a paint did actually
// happen in if a "Layer" marker was recorded too.
bool startIsPaintType = strcmp(startPayload->GetName(), "Paint") == 0;
bool hasSeenLayerType = false;
// If we are processing a "Paint" marker, we append information from
// all the embedded "Layer" markers to this array.
dom::Sequence<ProfileTimelineLayerRect> layerRectangles;
// DOM events can be nested, so we must take care when searching
// for the matching end. It doesn't hurt to apply this logic to
// all event types.
uint32_t markerDepth = 0;
// 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 < mTimelineMarkers.Length(); ++j) {
UniquePtr<TimelineMarker>& endPayload = mTimelineMarkers[j];
bool endIsLayerType = strcmp(endPayload->GetName(), "Layer") == 0;
// Look for "Layer" markers to stream out "Paint" markers.
if (startIsPaintType && endIsLayerType) {
hasSeenLayerType = true;
endPayload->AddLayerRectangles(layerRectangles);
}
if (!startPayload->Equals(*endPayload)) {
continue;
}
if (endPayload->GetMetaData() == TRACING_INTERVAL_START) {
++markerDepth;
continue;
}
if (endPayload->GetMetaData() == TRACING_INTERVAL_END) {
if (markerDepth > 0) {
--markerDepth;
continue;
}
if (!startIsPaintType || (startIsPaintType && hasSeenLayerType)) {
ProfileTimelineMarker* marker = webidlStore.AppendElement();
marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName());
marker->mStart = startPayload->GetTime();
marker->mEnd = endPayload->GetTime();
marker->mStack = startPayload->GetStack();
if (hasSeenLayerType) {
marker->mRectangles.Construct(layerRectangles);
}
startPayload->AddDetails(aCx, *marker);
endPayload->AddDetails(aCx, *marker);
}
hasSeenEnd = true;
break;
}
}
// If we did not see the corresponding END, keep the START.
if (!hasSeenEnd) {
keptStartMarkers.AppendElement(Move(mTimelineMarkers[i]));
mTimelineMarkers.RemoveElementAt(i);
--i;
}
}
}
mTimelineMarkers.SwapElements(keptStartMarkers);
return ToJSValue(aCx, webidlStore, aStore);
}
} // namespace mozilla

View File

@ -1,41 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef ObservedDocShell_h_
#define ObservedDocShell_h_
#include "GeckoProfiler.h"
#include "nsTArray.h"
#include "nsRefPtr.h"
class nsDocShell;
class TimelineMarker;
namespace mozilla {
// # ObservedDocShell
//
// A wrapper around a docshell for which docshell-specific markers are
// allowed to exist. See TimelineConsumers for register/unregister logic.
class ObservedDocShell : public LinkedListElement<ObservedDocShell>
{
private:
nsRefPtr<nsDocShell> mDocShell;
nsTArray<UniquePtr<TimelineMarker>> mTimelineMarkers;
public:
explicit ObservedDocShell(nsDocShell* aDocShell);
nsDocShell* operator*() const { return mDocShell.get(); }
void AddMarker(const char* aName, TracingMetadata aMetaData);
void AddMarker(UniquePtr<TimelineMarker>&& aMarker);
void ClearMarkers();
bool PopMarkers(JSContext* aCx, JS::MutableHandle<JS::Value> aStore);
};
} // namespace mozilla
#endif /* ObservedDocShell_h_ */

View File

@ -1,110 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/TimelineConsumers.h"
namespace mozilla {
unsigned long TimelineConsumers::sActiveConsumers = 0;
LinkedList<ObservedDocShell>* TimelineConsumers::sObservedDocShells = nullptr;
LinkedList<ObservedDocShell>&
TimelineConsumers::GetOrCreateObservedDocShellsList()
{
if (!sObservedDocShells) {
sObservedDocShells = new LinkedList<ObservedDocShell>();
}
return *sObservedDocShells;
}
void
TimelineConsumers::AddConsumer(nsDocShell* aDocShell)
{
UniquePtr<ObservedDocShell>& observed = aDocShell->mObserved;
MOZ_ASSERT(!observed);
sActiveConsumers++;
observed.reset(new ObservedDocShell(aDocShell));
GetOrCreateObservedDocShellsList().insertFront(observed.get());
}
void
TimelineConsumers::RemoveConsumer(nsDocShell* aDocShell)
{
UniquePtr<ObservedDocShell>& observed = aDocShell->mObserved;
MOZ_ASSERT(observed);
sActiveConsumers--;
observed.get()->ClearMarkers();
observed.get()->remove();
observed.reset(nullptr);
}
bool
TimelineConsumers::IsEmpty()
{
return sActiveConsumers == 0;
}
bool
TimelineConsumers::GetKnownDocShells(Vector<nsRefPtr<nsDocShell>>& aStore)
{
const LinkedList<ObservedDocShell>& docShells = GetOrCreateObservedDocShellsList();
for (const ObservedDocShell* rds = docShells.getFirst();
rds != nullptr;
rds = rds->getNext()) {
if (!aStore.append(**rds)) {
return false;
}
}
return true;
}
void
TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
UniquePtr<TimelineMarker>&& aMarker)
{
if (aDocShell->IsObserved()) {
aDocShell->mObserved->AddMarker(Move(aMarker));
}
}
void
TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
const char* aName, TracingMetadata aMetaData)
{
if (aDocShell->IsObserved()) {
aDocShell->mObserved->AddMarker(aName, aMetaData);
}
}
void
TimelineConsumers::AddMarkerToDocShellsList(Vector<nsRefPtr<nsDocShell>>& aDocShells,
const char* aName, TracingMetadata aMetaData)
{
for (Vector<nsRefPtr<nsDocShell>>::Range range = aDocShells.all();
!range.empty();
range.popFront()) {
AddMarkerForDocShell(range.front(), aName, aMetaData);
}
}
void
TimelineConsumers::AddMarkerToAllObservedDocShells(const char* aName, TracingMetadata aMetaData)
{
Vector<nsRefPtr<nsDocShell>> docShells;
if (!GetKnownDocShells(docShells)) {
// If we don't successfully populate our vector with *all* docshells being
// observed, don't add the marker to *any* of them.
return;
}
AddMarkerToDocShellsList(docShells, aName, aMetaData);
}
} // namespace mozilla

View File

@ -1,47 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_TimelineConsumers_h_
#define mozilla_TimelineConsumers_h_
#include "mozilla/UniquePtr.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Vector.h"
#include "timeline/ObservedDocShell.h"
class nsDocShell;
namespace mozilla {
class TimelineConsumers
{
private:
// Counter for how many timelines are currently interested in markers.
static unsigned long sActiveConsumers;
static LinkedList<ObservedDocShell>* sObservedDocShells;
static LinkedList<ObservedDocShell>& GetOrCreateObservedDocShellsList();
public:
static void AddConsumer(nsDocShell* aDocShell);
static void RemoveConsumer(nsDocShell* aDocShell);
static bool IsEmpty();
static bool GetKnownDocShells(Vector<nsRefPtr<nsDocShell>>& aStore);
// Methods for adding markers to appropriate docshells. These will only add
// markers if the docshell is currently being observed by a timeline.
// See nsIDocShell::recordProfileTimelineMarkers
static void AddMarkerForDocShell(nsDocShell* aDocShell,
UniquePtr<TimelineMarker>&& aMarker);
static void AddMarkerForDocShell(nsDocShell* aDocShell,
const char* aName, TracingMetadata aMetaData);
static void AddMarkerToDocShellsList(Vector<nsRefPtr<nsDocShell>>& aDocShells,
const char* aName, TracingMetadata aMetaData);
static void AddMarkerToAllObservedDocShells(const char* aName, TracingMetadata aMetaData);
};
} // namespace mozilla
#endif /* mozilla_TimelineConsumers_h_ */

View File

@ -7,14 +7,11 @@
EXPORTS.mozilla += [
'AutoGlobalTimelineMarker.h',
'AutoTimelineMarker.h',
'TimelineConsumers.h',
]
UNIFIED_SOURCES += [
'AutoGlobalTimelineMarker.cpp',
'AutoTimelineMarker.cpp',
'ObservedDocShell.cpp',
'TimelineConsumers.cpp',
'TimelineMarker.cpp',
]

View File

@ -1185,7 +1185,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
mozilla::UniquePtr<TimelineMarker> marker =
MakeUnique<TimestampTimelineMarker>(docShell, TRACING_TIMESTAMP, key);
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
docShell->AddProfileTimelineMarker(Move(marker));
}
// For `console.time(foo)` and `console.timeEnd(foo)`
else if (isTimelineRecording && aData.Length() == 1) {
@ -1198,7 +1198,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
MakeUnique<ConsoleTimelineMarker>(docShell,
aMethodName == MethodTime ? TRACING_INTERVAL_START : TRACING_INTERVAL_END,
key);
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
docShell->AddProfileTimelineMarker(Move(marker));
}
}
}

View File

@ -23,7 +23,6 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h"
#include "mozilla/TimelineConsumers.h"
#include "EventListenerService.h"
#include "nsCOMArray.h"
@ -1123,7 +1122,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
nsCOMPtr<nsIDocShell> docShell;
bool isTimelineRecording = false;
if (mIsMainThreadELM &&
!TimelineConsumers::IsEmpty() &&
nsDocShell::gProfileTimelineRecordingsCount > 0 &&
listener->mListenerType != Listener::eNativeListener) {
docShell = GetDocShellForTarget();
if (docShell) {
@ -1138,7 +1137,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
mozilla::UniquePtr<TimelineMarker> marker =
MakeUnique<EventTimelineMarker>(ds, TRACING_INTERVAL_START,
phase, typeStr);
TimelineConsumers::AddMarkerForDocShell(ds, Move(marker));
ds->AddProfileTimelineMarker(Move(marker));
}
}
@ -1149,7 +1148,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
if (isTimelineRecording) {
nsDocShell* ds = static_cast<nsDocShell*>(docShell.get());
TimelineConsumers::AddMarkerForDocShell(ds, "DOMEvent", TRACING_INTERVAL_END);
ds->AddProfileTimelineMarker("DOMEvent", TRACING_INTERVAL_END);
}
}
}

View File

@ -3075,7 +3075,7 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
data->mLayer->SetEventRegions(EventRegions());
}
}
if (!layer) {
// We couldn't optimize to an image layer or a color layer above.
layer = data->mLayer;
@ -5657,7 +5657,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer,
if (isRecording) {
mozilla::UniquePtr<TimelineMarker> marker =
MakeUnique<LayerTimelineMarker>(docShell, aRegionToDraw);
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
docShell->AddProfileTimelineMarker(Move(marker));
}
}

View File

@ -358,7 +358,7 @@ RestyleTracker::DoProcessRestyles()
MakeUnique<RestyleTimelineMarker>(docShell,
TRACING_INTERVAL_START,
data->mRestyleHint);
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
docShell->AddProfileTimelineMarker(Move(marker));
}
#if defined(MOZ_ENABLE_PROFILER_SPS) && !defined(MOZILLA_XPCOMRT_API)
@ -375,7 +375,7 @@ RestyleTracker::DoProcessRestyles()
MakeUnique<RestyleTimelineMarker>(docShell,
TRACING_INTERVAL_END,
data->mRestyleHint);
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
docShell->AddProfileTimelineMarker(Move(marker));
}
}
@ -422,7 +422,7 @@ RestyleTracker::DoProcessRestyles()
MakeUnique<RestyleTimelineMarker>(docShell,
TRACING_INTERVAL_START,
currentRestyle->mRestyleHint);
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
docShell->AddProfileTimelineMarker(Move(marker));
}
ProcessOneRestyle(currentRestyle->mElement,
@ -434,7 +434,7 @@ RestyleTracker::DoProcessRestyles()
MakeUnique<RestyleTimelineMarker>(docShell,
TRACING_INTERVAL_END,
currentRestyle->mRestyleHint);
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
docShell->AddProfileTimelineMarker(Move(marker));
}
}
}

View File

@ -8923,7 +8923,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
nsDocShell* docShell = static_cast<nsDocShell*>(GetPresContext()->GetDocShell());
if (docShell) {
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", TRACING_INTERVAL_START);
docShell->AddProfileTimelineMarker("Reflow", TRACING_INTERVAL_START);
}
if (mReflowContinueTimer) {
@ -9100,7 +9100,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
}
if (docShell) {
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", TRACING_INTERVAL_END);
docShell->AddProfileTimelineMarker("Reflow", TRACING_INTERVAL_END);
}
return !interrupted;
}

View File

@ -64,7 +64,6 @@
#include "mozilla/VsyncDispatcher.h"
#include "nsThreadUtils.h"
#include "mozilla/unused.h"
#include "mozilla/TimelineConsumers.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
@ -994,7 +993,7 @@ RefreshDriverTimer*
nsRefreshDriver::ChooseTimer() const
{
if (mThrottled) {
if (!sThrottledRateTimer)
if (!sThrottledRateTimer)
sThrottledRateTimer = new InactiveRefreshDriverTimer(GetThrottledTimerInterval(),
DEFAULT_INACTIVE_TIMER_DISABLE_SECONDS * 1000.0);
return sThrottledRateTimer;
@ -1052,7 +1051,7 @@ nsRefreshDriver::~nsRefreshDriver()
MOZ_ASSERT(ObserverCount() == 0,
"observers should have unregistered");
MOZ_ASSERT(!mActiveTimer, "timer should be gone");
if (mRootRefresh) {
mRootRefresh->RemoveRefreshObserver(this, Flush_Style);
mRootRefresh = nullptr;
@ -1437,7 +1436,7 @@ HasPendingAnimations(nsIPresShell* aShell)
static void GetProfileTimelineSubDocShells(nsDocShell* aRootDocShell,
nsTArray<nsDocShell*>& aShells)
{
if (!aRootDocShell || TimelineConsumers::IsEmpty()) {
if (!aRootDocShell || nsDocShell::gProfileTimelineRecordingsCount == 0) {
return;
}
@ -1819,7 +1818,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
for (nsDocShell* docShell : profilingDocShells) {
// For the sake of the profile timeline's simplicity, this is flagged as
// paint even if it includes creating display lists
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", TRACING_INTERVAL_START);
docShell->AddProfileTimelineMarker("Paint", TRACING_INTERVAL_START);
}
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
@ -1836,7 +1835,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
}
#endif
for (nsDocShell* docShell : profilingDocShells) {
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", TRACING_INTERVAL_END);
docShell->AddProfileTimelineMarker("Paint", TRACING_INTERVAL_END);
}
if (nsContentUtils::XPConnect()) {