Bug 1356141 - Don't traverse any elements that needed only for animation-only restyles in normal traversal. r?heycam
Before this patch, we were setting the dirty descendants bit in animation-only
restyles and it triggered unnecessary traversal for elements that does not need
the traversal (i.e no need selector matching).
MozReview-Commit-ID: 6pmF3ojVzgb
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -482,16 +482,26 @@ public:
void UnsetHasDirtyDescendantsForServo() {
MOZ_ASSERT(IsStyledByServo());
UnsetFlags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
}
inline void NoteDirtyDescendantsForServo();
+ bool HasAnimationOnlyDirtyDescendantsForServo() const {
+ MOZ_ASSERT(IsStyledByServo());
+ return HasFlag(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
+ }
+
+ void UnsetHasAnimationOnlyDirtyDescendantsForServo() {
+ MOZ_ASSERT(IsStyledByServo());
+ UnsetFlags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
+ }
+
#ifdef DEBUG
inline bool DirtyDescendantsBitIsPropagatedForServo();
#endif
bool HasServoData() const {
return !!mServoData.Get();
}
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -129,45 +129,48 @@ ServoRestyleManager::PostRebuildAllStyle
// if we do, we need to re-selector-match them here.
}
/* static */ void
ServoRestyleManager::ClearServoDataFromSubtree(Element* aElement)
{
if (!aElement->HasServoData()) {
MOZ_ASSERT(!aElement->HasDirtyDescendantsForServo());
+ MOZ_ASSERT(!aElement->HasAnimationOnlyDirtyDescendantsForServo());
return;
}
StyleChildrenIterator it(aElement);
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
if (n->IsElement()) {
ClearServoDataFromSubtree(n->AsElement());
}
}
aElement->ClearServoData();
aElement->UnsetHasDirtyDescendantsForServo();
+ aElement->UnsetHasAnimationOnlyDirtyDescendantsForServo();
}
-
/* static */ void
ServoRestyleManager::ClearRestyleStateFromSubtree(Element* aElement)
{
- if (aElement->HasDirtyDescendantsForServo()) {
+ if (aElement->HasDirtyDescendantsForServo() ||
+ aElement->HasAnimationOnlyDirtyDescendantsForServo()) {
StyleChildrenIterator it(aElement);
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
if (n->IsElement()) {
ClearRestyleStateFromSubtree(n->AsElement());
}
}
}
Unused << Servo_TakeChangeHint(aElement);
aElement->UnsetHasDirtyDescendantsForServo();
+ aElement->UnsetHasAnimationOnlyDirtyDescendantsForServo();
aElement->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
}
/**
* This struct takes care of encapsulating some common state that text nodes may
* need to track during the post-traversal.
*
* This is currently used to properly compute change hints when the parent
@@ -439,17 +442,19 @@ ServoRestyleManager::ProcessPostTraversa
// style or not, we need to call it *after* setting |newContext| to
// |styleFrame| to ensure the animated transform has been removed first.
AddLayerChangesForAnimation(styleFrame, aElement, aChangeList);
}
const bool descendantsNeedFrames =
aElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES);
const bool traverseElementChildren =
- aElement->HasDirtyDescendantsForServo() || descendantsNeedFrames;
+ aElement->HasDirtyDescendantsForServo() ||
+ aElement->HasAnimationOnlyDirtyDescendantsForServo() ||
+ descendantsNeedFrames;
const bool traverseTextChildren = recreateContext || descendantsNeedFrames;
bool recreatedAnyContext = recreateContext;
if (traverseElementChildren || traverseTextChildren) {
nsStyleContext* upToDateContext =
recreateContext ? newContext : oldStyleContext;
StyleChildrenIterator it(aElement);
TextPostTraversalState textState(
@@ -465,16 +470,17 @@ ServoRestyleManager::ProcessPostTraversa
} else if (traverseTextChildren && n->IsNodeOfType(nsINode::eTEXT)) {
recreatedAnyContext |=
ProcessPostTraversalForText(n, aChangeList, textState);
}
}
}
aElement->UnsetHasDirtyDescendantsForServo();
+ aElement->UnsetHasAnimationOnlyDirtyDescendantsForServo();
aElement->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
return recreatedAnyContext;
}
bool
ServoRestyleManager::ProcessPostTraversalForText(
nsIContent* aTextNode,
nsStyleChangeList& aChangeList,