Bug 1350930 - Move profiler markers for reflow and style flushes from the refresh driver into the PresShell. r?bzbarsky
MozReview-Commit-ID: FQs2zsIU2zO
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -4205,30 +4205,41 @@ PresShell::DoFlushPendingNotifications(m
// events. At the same time, we still need up-to-date style data.
// In particular, reflow depends on style being completely up to
// date. If it's not, then style context reparenting, which can
// happen during reflow, might suddenly pick up the new rules and
// we'll end up with frames whose style doesn't match the frame
// type.
if (!mIsDestroying) {
nsAutoScriptBlocker scriptBlocker;
+#ifdef MOZ_GECKO_PROFILER
+ AutoProfilerTracing tracingStyleFlush("Paint", "Styles",
+ Move(mStyleCause));
+ mStyleCause = nullptr;
+#endif
+
mPresContext->RestyleManager()->ProcessPendingRestyles();
}
didStyleFlush = true;
// There might be more pending constructors now, but we're not going to
// worry about them. They can't be triggered during reflow, so we should
// be good.
if (flushType >= (SuppressInterruptibleReflows()
? FlushType::Layout
: FlushType::InterruptibleLayout) &&
!mIsDestroying) {
+#ifdef MOZ_GECKO_PROFILER
+ AutoProfilerTracing tracingLayoutFlush("Paint", "Reflow",
+ Move(mReflowCause));
+ mReflowCause = nullptr;
+#endif
didLayoutFlush = true;
mFrameConstructor->RecalcQuotesAndCounters();
viewManager->FlushDelayedResize(true);
if (ProcessReflowCommands(flushType < FlushType::Layout) &&
mContentToScrollTo) {
// We didn't get interrupted. Go ahead and scroll to our content
DoScrollContentIntoView();
if (mContentToScrollTo) {
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -12,16 +12,17 @@
#include "mozilla/ArenaObjectID.h"
#include "mozilla/EventForwards.h"
#include "mozilla/FlushType.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/WeakPtr.h"
+#include "GeckoProfiler.h"
#include "gfxPoint.h"
#include "nsTHashtable.h"
#include "nsHashKeys.h"
#include "nsISupports.h"
#include "nsIContent.h"
#include "nsISelectionController.h"
#include "nsQueryFrame.h"
#include "nsStringFwd.h"
@@ -1692,16 +1693,24 @@ protected:
nsSize mScrollPositionClampingScrollPortSize;
// A list of stack weak frames. This is a pointer to the last item in the list.
AutoWeakFrame* mAutoWeakFrames;
// A hash table of heap allocated weak frames.
nsTHashtable<nsPtrHashKey<WeakFrame>> mWeakFrames;
+#ifdef MOZ_GECKO_PROFILER
+ // These two fields capture call stacks of any changes that require a restyle
+ // or a reflow. Only the first change per restyle / reflow is recorded (the
+ // one that caused a call to SetNeedStyleFlush() / SetNeedLayoutFlush()).
+ UniqueProfilerBacktrace mStyleCause;
+ UniqueProfilerBacktrace mReflowCause;
+#endif
+
// Most recent canvas background color.
nscolor mCanvasBackgroundColor;
// Used to force allocation and rendering of proportionally more or
// less pixels in both dimensions.
mozilla::Maybe<float> mResolution;
int16_t mSelectionFlags;
--- a/layout/base/nsIPresShellInlines.h
+++ b/layout/base/nsIPresShellInlines.h
@@ -13,27 +13,39 @@ void
nsIPresShell::SetNeedLayoutFlush()
{
mNeedLayoutFlush = true;
if (nsIDocument* doc = mDocument->GetDisplayDocument()) {
if (nsIPresShell* shell = doc->GetShell()) {
shell->mNeedLayoutFlush = true;
}
}
+
+#ifdef MOZ_GECKO_PROFILER
+ if (!mReflowCause) {
+ mReflowCause = profiler_get_backtrace();
+ }
+#endif
}
void
nsIPresShell::SetNeedStyleFlush()
{
mNeedStyleFlush = true;
if (nsIDocument* doc = mDocument->GetDisplayDocument()) {
if (nsIPresShell* shell = doc->GetShell()) {
shell->mNeedStyleFlush = true;
}
}
+
+#ifdef MOZ_GECKO_PROFILER
+ if (!mStyleCause) {
+ mStyleCause = profiler_get_backtrace();
+ }
+#endif
}
void
nsIPresShell::EnsureStyleFlush()
{
SetNeedStyleFlush();
ObserveStyleFlushes();
}
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1852,71 +1852,51 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
// This is the FlushType::Style case.
DispatchAnimationEvents();
DispatchPendingEvents();
RunFrameRequestCallbacks(aNowTime);
DispatchScrollEvents();
if (mPresContext && mPresContext->GetPresShell()) {
-#ifdef MOZ_GECKO_PROFILER
- Maybe<AutoProfilerTracing> tracingStyleFlush;
-#endif
AutoTArray<nsIPresShell*, 16> observers;
observers.AppendElements(mStyleFlushObservers);
for (uint32_t j = observers.Length();
j && mPresContext && mPresContext->GetPresShell(); --j) {
// Make sure to not process observers which might have been removed
// during previous iterations.
nsIPresShell* shell = observers[j - 1];
if (!mStyleFlushObservers.RemoveElement(shell))
continue;
-#ifdef MOZ_GECKO_PROFILER
- if (!tracingStyleFlush) {
- tracingStyleFlush.emplace("Paint", "Styles", Move(mStyleCause));
- mStyleCause = nullptr;
- }
-#endif
-
nsCOMPtr<nsIPresShell> shellKungFuDeathGrip(shell);
shell->mObservingStyleFlushes = false;
shell->FlushPendingNotifications(ChangesToFlush(FlushType::Style, false));
// Inform the FontFaceSet that we ticked, so that it can resolve its
// ready promise if it needs to (though it might still be waiting on
// a layout flush).
nsPresContext* presContext = shell->GetPresContext();
if (presContext) {
presContext->NotifyFontFaceSetOnRefresh();
}
mNeedToRecomputeVisibility = true;
}
}
} else if (i == 2) {
// This is the FlushType::Layout case.
-#ifdef MOZ_GECKO_PROFILER
- Maybe<AutoProfilerTracing> tracingLayoutFlush;
-#endif
AutoTArray<nsIPresShell*, 16> observers;
observers.AppendElements(mLayoutFlushObservers);
for (uint32_t j = observers.Length();
j && mPresContext && mPresContext->GetPresShell(); --j) {
// Make sure to not process observers which might have been removed
// during previous iterations.
nsIPresShell* shell = observers[j - 1];
if (!mLayoutFlushObservers.RemoveElement(shell))
continue;
-#ifdef MOZ_GECKO_PROFILER
- if (!tracingLayoutFlush) {
- tracingLayoutFlush.emplace("Paint", "Reflow", Move(mReflowCause));
- mReflowCause = nullptr;
- }
-#endif
-
nsCOMPtr<nsIPresShell> shellKungFuDeathGrip(shell);
shell->mObservingLayoutFlushes = false;
shell->mWasLastReflowInterrupted = false;
FlushType flushType = HasPendingAnimations(shell)
? FlushType::Layout
: FlushType::InterruptibleLayout;
shell->FlushPendingNotifications(ChangesToFlush(flushType, false));
// Inform the FontFaceSet that we ticked, so that it can resolve its
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -19,17 +19,16 @@
#include "nsTObserverArray.h"
#include "nsTArray.h"
#include "nsTHashtable.h"
#include "nsTObserverArray.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
-#include "GeckoProfiler.h"
#include "mozilla/layers/TransactionIdAllocator.h"
class nsPresContext;
class nsIPresShell;
class nsIDocument;
class imgIRequest;
class nsIDOMEvent;
class nsINode;
@@ -155,45 +154,27 @@ public:
void RemoveImageRequest(imgIRequest* aRequest);
/**
* Add / remove presshells that we should flush style and layout on
*/
bool AddStyleFlushObserver(nsIPresShell* aShell) {
NS_ASSERTION(!mStyleFlushObservers.Contains(aShell),
"Double-adding style flush observer");
- // We only get the cause for the first observer each frame because capturing
- // a stack is expensive. This is still useful if (1) you're trying to remove
- // all flushes for a particial frame or (2) the costly flush is triggered
- // near the call site where the first observer is triggered.
-#ifdef MOZ_GECKO_PROFILER
- if (!mStyleCause) {
- mStyleCause = profiler_get_backtrace();
- }
-#endif
bool appended = mStyleFlushObservers.AppendElement(aShell) != nullptr;
EnsureTimerStarted();
return appended;
}
void RemoveStyleFlushObserver(nsIPresShell* aShell) {
mStyleFlushObservers.RemoveElement(aShell);
}
bool AddLayoutFlushObserver(nsIPresShell* aShell) {
NS_ASSERTION(!IsLayoutFlushObserver(aShell),
"Double-adding layout flush observer");
-#ifdef MOZ_GECKO_PROFILER
- // We only get the cause for the first observer each frame because capturing
- // a stack is expensive. This is still useful if (1) you're trying to remove
- // all flushes for a particial frame or (2) the costly flush is triggered
- // near the call site where the first observer is triggered.
- if (!mReflowCause) {
- mReflowCause = profiler_get_backtrace();
- }
-#endif
bool appended = mLayoutFlushObservers.AppendElement(aShell) != nullptr;
EnsureTimerStarted();
return appended;
}
void RemoveLayoutFlushObserver(nsIPresShell* aShell) {
mLayoutFlushObservers.RemoveElement(aShell);
}
bool IsLayoutFlushObserver(nsIPresShell* aShell) {
@@ -415,21 +396,16 @@ private:
return mFrameRequestCallbackDocs.Length() != 0;
}
void FinishedWaitingForTransaction();
mozilla::RefreshDriverTimer* ChooseTimer() const;
mozilla::RefreshDriverTimer* mActiveTimer;
-#ifdef MOZ_GECKO_PROFILER
- UniqueProfilerBacktrace mReflowCause;
- UniqueProfilerBacktrace mStyleCause;
-#endif
-
// nsPresContext passed in constructor and unset in Disconnect.
mozilla::WeakPtr<nsPresContext> mPresContext;
RefPtr<nsRefreshDriver> mRootRefresh;
// The most recently allocated transaction id.
uint64_t mPendingTransaction;
// The most recently completed transaction id.