Bug 1203766 - Part 6: Cache resolved style contexts on nsComputedDOMStyle to avoid re-resolving if styles haven't changed. r=bzbarsky

This commit is contained in:
Cameron McCormack 2015-09-17 12:08:20 +10:00
Родитель 88572918f6
Коммит c6d52eae0d
2 изменённых файлов: 67 добавлений и 11 удалений

Просмотреть файл

@ -222,7 +222,9 @@ nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement,
: mDocumentWeak(nullptr), mOuterFrame(nullptr),
mInnerFrame(nullptr), mPresShell(nullptr),
mStyleType(aStyleType),
mExposeVisitedStyle(false)
mStyleContextGeneration(0),
mExposeVisitedStyle(false),
mResolvedStyleContext(false)
{
MOZ_ASSERT(aElement && aPresShell);
@ -572,10 +574,10 @@ nsComputedDOMStyle::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv
void
nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
{
MOZ_ASSERT(!mStyleContext);
nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocumentWeak);
if (!document) {
mResolvedStyleContext = false;
mStyleContext = nullptr;
return;
}
@ -593,9 +595,24 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
mPresShell = document->GetShell();
if (!mPresShell || !mPresShell->GetPresContext()) {
mResolvedStyleContext = false;
mStyleContext = nullptr;
return;
}
uint64_t currentGeneration =
mPresShell->GetPresContext()->GetRestyleGeneration();
if (mStyleContext) {
if (mStyleContextGeneration == currentGeneration) {
// Our cached style context is still valid.
return;
}
// We've processed some restyles, so the cached style context might
// be out of date.
mStyleContext = nullptr;
}
// XXX the !mContent->IsHTMLElement(nsGkAtoms::area)
// check is needed due to bug 135040 (to avoid using
// mPrimaryFrame). Remove it once that's fixed.
@ -616,6 +633,7 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
}
mStyleContext = mInnerFrame->StyleContext();
mResolvedStyleContext = false;
NS_ASSERTION(mStyleContext, "Frame without style context?");
}
}
@ -649,9 +667,19 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
mPresShell,
mStyleType);
if (!mStyleContext) {
mResolvedStyleContext = false;
return;
}
// No need to re-get the generation, even though GetStyleContextForElement
// will flush, since we flushed style at the top of this function.
NS_ASSERTION(mPresShell &&
currentGeneration ==
mPresShell->GetPresContext()->GetRestyleGeneration(),
"why should we have flushed style again?");
mResolvedStyleContext = true;
mStyleContextGeneration = currentGeneration;
NS_ASSERTION(mPseudo || !mStyleContext->HasPseudoElementData(),
"should not have pseudo-element data");
}
@ -675,9 +703,12 @@ nsComputedDOMStyle::ClearCurrentStyleSources()
mInnerFrame = nullptr;
mPresShell = nullptr;
// Release the current style context for it should be re-resolved
// whenever a frame is not available.
mStyleContext = nullptr;
// Release the current style context if we got it off the frame.
// For a style context we resolved, keep it around so that we
// can re-use it next time this object is queried.
if (!mResolvedStyleContext) {
mStyleContext = nullptr;
}
}
already_AddRefed<CSSValue>

Просмотреть файл

@ -9,6 +9,8 @@
#define nsComputedDOMStyle_h__
#include "nsAutoPtr.h"
#include "mozilla/ArenaRefPtr.h"
#include "mozilla/ArenaRefPtrInlines.h"
#include "mozilla/Attributes.h"
#include "nsCOMPtr.h"
#include "nscore.h"
@ -595,12 +597,23 @@ private:
nsWeakPtr mDocumentWeak;
nsCOMPtr<nsIContent> mContent;
/*
* Strong reference to the style context while we're accessing the data from
* it. This can be either a style context we resolved ourselves or a style
* context we got from our frame.
/**
* Strong reference to the style context we access data from. This can be
* either a style context we resolved ourselves or a style context we got
* from our frame.
*
* If we got the style context from the frame, we clear out mStyleContext
* in ClearCurrentStyleSources. If we resolved one ourselves, then
* ClearCurrentStyleSources leaves it in mStyleContext for use the next
* time this nsComputedDOMStyle object is queried. UpdateCurrentStyleSources
* in this case will check that the style context is still valid to be used,
* by checking whether flush styles results in any restyles having been
* processed.
*
* Since an ArenaRefPtr is used to hold the style context, it will be cleared
* if the pres arena from which it was allocated goes away.
*/
nsRefPtr<nsStyleContext> mStyleContext;
mozilla::ArenaRefPtr<nsStyleContext> mStyleContext;
nsCOMPtr<nsIAtom> mPseudo;
/*
@ -626,8 +639,20 @@ private:
*/
StyleType mStyleType;
/**
* The nsComputedDOMStyle generation at the time we last resolved a style
* context and stored it in mStyleContext.
*/
uint64_t mStyleContextGeneration;
bool mExposeVisitedStyle;
/**
* Whether we resolved a style context last time we called
* UpdateCurrentStyleSources. Initially false.
*/
bool mResolvedStyleContext;
#ifdef DEBUG
bool mFlushedPendingReflows;
#endif