Bug 1403078: Lazily tweak the traversal root to account for sibling invalidations. r=heycam

MozReview-Commit-ID: Ij3nMOKu5FO
This commit is contained in:
Emilio Cobos Álvarez 2017-09-26 07:25:06 +02:00
Родитель a35d42324c
Коммит 1ae8fc2d3a
3 изменённых файлов: 30 добавлений и 30 удалений

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

@ -1046,25 +1046,7 @@ ServoRestyleManager::SnapshotFor(Element* aElement)
aElement->SetFlags(ELEMENT_HAS_SNAPSHOT);
// Now that we have a snapshot, make sure a restyle is triggered.
//
// If we have any later siblings, we need to flag the restyle on the parent,
// so that a traversal from the restyle root is guaranteed to reach those
// siblings (since the snapshot may generate hints for later siblings).
if (aElement->GetNextElementSibling()) {
Element* parent = aElement->GetFlattenedTreeParentElementForStyle();
MOZ_ASSERT(parent);
// The parent will only be outside of the composed doc if we're mid-unbind.
//
// FIXME(emilio): Make the traversal lazily mark the parent as dirty if
// needed to avoid this problem altogether, plus being better perf-wise.
if (parent->IsInComposedDoc()) {
parent->NoteDirtyForServo();
parent->SetHasDirtyDescendantsForServo();
}
} else {
aElement->NoteDirtyForServo();
}
aElement->NoteDirtyForServo();
return *snapshot;
}

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

@ -969,14 +969,30 @@ ServoStyleSet::StyleDocument(ServoTraversalFlags aFlags)
// Do the first traversal.
DocumentStyleRootIterator iter(doc->GetServoRestyleRoot());
while (Element* root = iter.GetNextStyleRoot()) {
MOZ_ASSERT(MayTraverseFrom(const_cast<Element*>(root)));
MOZ_ASSERT(MayTraverseFrom(root));
// If there were text nodes inserted into the document (but not elements),
// there may be lazy frame construction to do even if no styling is required.
postTraversalRequired |= root->HasFlag(NODE_DESCENDANTS_NEED_FRAMES);
Element* parent = root->GetFlattenedTreeParentElementForStyle();
MOZ_ASSERT_IF(parent,
!parent->HasAnyOfFlags(Element::kAllServoDescendantBits));
bool required = Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, aFlags);
postTraversalRequired |= required;
postTraversalRequired |=
Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, aFlags);
postTraversalRequired |=
root->HasAnyOfFlags(Element::kAllServoDescendantBits | NODE_NEEDS_FRAME);
if (parent) {
MOZ_ASSERT(root == doc->GetServoRestyleRoot());
if (parent->HasDirtyDescendantsForServo()) {
// If any style invalidation was triggered in our siblings, then we may
// need to post-traverse them, even if the root wasn't restyled after
// all.
doc->SetServoRestyleRoot(
parent,
doc->GetServoRestyleRootDirtyBits() |
ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
postTraversalRequired = true;
}
}
}
// If there are still animation restyles needed, trigger a second traversal to
@ -995,8 +1011,10 @@ ServoStyleSet::StyleDocument(ServoTraversalFlags aFlags)
nsINode* styleRoot = doc->GetServoRestyleRoot();
Element* root = styleRoot->IsElement() ? styleRoot->AsElement() : rootElement;
bool required = Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, aFlags);
postTraversalRequired |= required;
postTraversalRequired |=
Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, aFlags);
postTraversalRequired |=
root->HasAnyOfFlags(Element::kAllServoDescendantBits | NODE_NEEDS_FRAME);
}
return postTraversalRequired;
@ -1430,8 +1448,8 @@ ServoStyleSet::MaybeGCRuleTree()
Servo_MaybeGCRuleTree(mRawSet.get());
}
bool
ServoStyleSet::MayTraverseFrom(Element* aElement)
/* static */ bool
ServoStyleSet::MayTraverseFrom(const Element* aElement)
{
MOZ_ASSERT(aElement->IsInComposedDoc());
Element* parent = aElement->GetFlattenedTreeParentElementForStyle();

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

@ -333,7 +333,7 @@ public:
*
* Most traversal callsites don't need to check this, but some do.
*/
bool MayTraverseFrom(dom::Element* aElement);
static bool MayTraverseFrom(const dom::Element* aElement);
#ifdef DEBUG
void AssertTreeIsClean();