Bug 1398119 - Rearrange NoteDirtyElement for faster bailouts on the same restyle root. r=emilio

This eliminates ~90% of the time spent in NoteDirtyElement on this testcase.

MozReview-Commit-ID: Lm5hf7QRiOK
This commit is contained in:
Bobby Holley 2018-01-11 13:34:30 -08:00
Родитель 1ce8eb2531
Коммит f458d41b8e
3 изменённых файлов: 27 добавлений и 9 удалений

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

@ -4592,6 +4592,15 @@ NoteDirtyElement(Element* aElement, uint32_t aBits)
MOZ_ASSERT(aElement->IsInComposedDoc());
MOZ_ASSERT(aElement->IsStyledByServo());
// Check the existing root early on, since it may allow us to short-circuit
// before examining the parent chain.
nsIDocument* doc = aElement->GetComposedDoc();
nsINode* existingRoot = doc->GetServoRestyleRoot();
if (existingRoot == aElement) {
doc->SetServoRestyleRootDirtyBits(doc->GetServoRestyleRootDirtyBits() | aBits);
return;
}
nsINode* parent = aElement->GetFlattenedTreeParentNodeForStyle();
if (!parent) {
// The element is not in the flattened tree, bail.
@ -4630,24 +4639,20 @@ NoteDirtyElement(Element* aElement, uint32_t aBits)
}
}
nsIDocument* doc = aElement->GetComposedDoc();
if (nsIPresShell* shell = doc->GetShell()) {
shell->EnsureStyleFlush();
}
MOZ_ASSERT(parent->IsElement() || parent == doc);
nsINode* existingRoot = doc->GetServoRestyleRoot();
uint32_t existingBits = existingRoot ? doc->GetServoRestyleRootDirtyBits() : 0;
// The bit checks below rely on this to arrive to useful conclusions about the
// shape of the tree.
AssertNoBitsPropagatedFrom(existingRoot);
// If there's no existing restyle root, or if the root is already aElement,
// just note the root+bits and return.
if (!existingRoot || existingRoot == aElement) {
doc->SetServoRestyleRoot(aElement, existingBits | aBits);
if (!existingRoot) {
doc->SetServoRestyleRoot(aElement, aBits);
return;
}
@ -4657,6 +4662,7 @@ NoteDirtyElement(Element* aElement, uint32_t aBits)
!parent->IsElement() ||
!PropagateBits(parent->AsElement(), aBits, existingRoot);
uint32_t existingBits = existingRoot ? doc->GetServoRestyleRootDirtyBits() : 0;
if (!reachedDocRoot || existingRoot == doc) {
// We're a descendant of the existing root. All that's left to do is to
// make sure the bit we propagated is also registered on the root.

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

@ -3149,6 +3149,7 @@ public:
}
inline void SetServoRestyleRoot(nsINode* aRoot, uint32_t aDirtyBits);
inline void SetServoRestyleRootDirtyBits(uint32_t aDirtyBits);
bool ShouldThrowOnDynamicMarkupInsertion()
{

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

@ -62,9 +62,6 @@ inline void
nsIDocument::SetServoRestyleRoot(nsINode* aRoot, uint32_t aDirtyBits)
{
MOZ_ASSERT(aRoot);
MOZ_ASSERT(aDirtyBits);
MOZ_ASSERT((aDirtyBits & ~Element::kAllServoDescendantBits) == 0);
MOZ_ASSERT((aDirtyBits & mServoRestyleRootDirtyBits) == mServoRestyleRootDirtyBits);
// NOTE(emilio): The !aRoot->IsElement() check allows us to handle cases where
// we change the restyle root during unbinding of a subtree where the root is
@ -90,7 +87,21 @@ nsIDocument::SetServoRestyleRoot(nsINode* aRoot, uint32_t aDirtyBits)
nsContentUtils::ContentIsFlattenedTreeDescendantOfForStyle(mServoRestyleRoot, aRoot));
MOZ_ASSERT(aRoot == aRoot->OwnerDocAsNode() || aRoot->IsElement());
mServoRestyleRoot = aRoot;
SetServoRestyleRootDirtyBits(aDirtyBits);
}
// Note: we break this out of SetServoRestyleRoot so that callers can add
// bits without doing a no-op assignment to the restyle root, which would
// involve cycle-collected refcount traffic.
inline void
nsIDocument::SetServoRestyleRootDirtyBits(uint32_t aDirtyBits)
{
MOZ_ASSERT(aDirtyBits);
MOZ_ASSERT((aDirtyBits & ~Element::kAllServoDescendantBits) == 0);
MOZ_ASSERT((aDirtyBits & mServoRestyleRootDirtyBits) == mServoRestyleRootDirtyBits);
MOZ_ASSERT(mServoRestyleRoot);
mServoRestyleRootDirtyBits = aDirtyBits;
}
#endif // nsIDocumentInlines_h