| Index: Source/core/css/invalidation/StyleInvalidator.cpp
|
| diff --git a/Source/core/css/invalidation/StyleInvalidator.cpp b/Source/core/css/invalidation/StyleInvalidator.cpp
|
| index ddc28c70b6e8607355a4e9245bac2d1f5bca3d2d..d116bf5867fb7d1dd91ca06d4cea8e991d2248e6 100644
|
| --- a/Source/core/css/invalidation/StyleInvalidator.cpp
|
| +++ b/Source/core/css/invalidation/StyleInvalidator.cpp
|
| @@ -33,36 +33,40 @@ static const unsigned char* s_tracingEnabled = nullptr;
|
| void StyleInvalidator::invalidate(Document& document)
|
| {
|
| RecursionData recursionData;
|
| + SiblingData siblingData;
|
| if (Element* documentElement = document.documentElement())
|
| - invalidate(*documentElement, recursionData);
|
| + invalidate(*documentElement, recursionData, siblingData);
|
| document.clearChildNeedsStyleInvalidation();
|
| document.clearNeedsStyleInvalidation();
|
| clearPendingInvalidations();
|
| }
|
|
|
| -void StyleInvalidator::scheduleInvalidation(PassRefPtrWillBeRawPtr<DescendantInvalidationSet> invalidationSet, Element& element)
|
| +void StyleInvalidator::scheduleInvalidation(PassRefPtrWillBeRawPtr<DescendantInvalidationSet> invalidationSet, Element& element, InvalidateType type)
|
| {
|
| ASSERT(element.inActiveDocument());
|
| - if (element.styleChangeType() >= SubtreeStyleChange)
|
| - return;
|
| - if (invalidationSet->wholeSubtreeInvalid()) {
|
| - element.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
|
| - clearInvalidation(element);
|
| - return;
|
| - }
|
| - if (invalidationSet->isEmpty()) {
|
| - element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
|
| - return;
|
| + if (type == InvalidateDescendants) {
|
| + if (element.styleChangeType() >= SubtreeStyleChange)
|
| + return;
|
| + if (invalidationSet->wholeSubtreeInvalid()) {
|
| + element.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
|
| + clearInvalidation(element);
|
| + return;
|
| + }
|
| + if (invalidationSet->isEmpty()) {
|
| + element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
|
| + return;
|
| + }
|
| + element.setNeedsStyleInvalidation();
|
| + } else {
|
| + element.markAncestorsWithChildNeedsStyleInvalidation();
|
| }
|
| -
|
| - InvalidationList& list = ensurePendingInvalidationList(element);
|
| + InvalidationList& list = ensurePendingInvalidationList(element, type);
|
| list.append(invalidationSet);
|
| - element.setNeedsStyleInvalidation();
|
| }
|
|
|
| -StyleInvalidator::InvalidationList& StyleInvalidator::ensurePendingInvalidationList(Element& element)
|
| +StyleInvalidator::InvalidationList& StyleInvalidator::ensurePendingInvalidationList(Element& element, InvalidateType type)
|
| {
|
| - PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(&element, nullptr);
|
| + PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap[type].add(&element, nullptr);
|
| if (addResult.isNewEntry)
|
| addResult.storedValue->value = adoptPtrWillBeNoop(new InvalidationList);
|
| return *addResult.storedValue->value;
|
| @@ -72,13 +76,15 @@ void StyleInvalidator::clearInvalidation(Element& element)
|
| {
|
| if (!element.needsStyleInvalidation())
|
| return;
|
| - m_pendingInvalidationMap.remove(&element);
|
| + m_pendingInvalidationMap[InvalidateDescendants].remove(&element);
|
| + m_pendingInvalidationMap[InvalidateSiblings].remove(&element);
|
| element.clearNeedsStyleInvalidation();
|
| }
|
|
|
| void StyleInvalidator::clearPendingInvalidations()
|
| {
|
| - m_pendingInvalidationMap.clear();
|
| + m_pendingInvalidationMap[InvalidateDescendants].clear();
|
| + m_pendingInvalidationMap[InvalidateSiblings].clear();
|
| }
|
|
|
| StyleInvalidator::StyleInvalidator()
|
| @@ -104,7 +110,7 @@ void StyleInvalidator::RecursionData::pushInvalidationSet(const DescendantInvali
|
| m_invalidateCustomPseudo = invalidationSet.customPseudoInvalid();
|
| }
|
|
|
| -ALWAYS_INLINE bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSets(Element& element)
|
| +ALWAYS_INLINE bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSets(Element& element) const
|
| {
|
| if (m_invalidateCustomPseudo && element.shadowPseudoId() != nullAtom) {
|
| TRACE_STYLE_INVALIDATOR_INVALIDATION_IF_ENABLED(element, InvalidateCustomPseudo);
|
| @@ -122,6 +128,30 @@ ALWAYS_INLINE bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSe
|
| return false;
|
| }
|
|
|
| +void StyleInvalidator::SiblingData::pushInvalidationSet(const DescendantInvalidationSet& invalidationSet)
|
| +{
|
| + m_invalidationSets.append(&invalidationSet);
|
| + if (invalidationSet.maxDirectAdjacentSelectors() == std::numeric_limits<unsigned>::max())
|
| + m_invalidationLimits.append(std::numeric_limits<unsigned>::max());
|
| + else
|
| + m_invalidationLimits.append(m_elementIndex + invalidationSet.maxDirectAdjacentSelectors());
|
| +}
|
| +
|
| +ALWAYS_INLINE bool StyleInvalidator::SiblingData::matchesCurrentInvalidationSets(Element& element)
|
| +{
|
| + m_elementIndex++;
|
| +
|
| + for (unsigned index = 0; index < m_invalidationLimits.size(); ++index) {
|
| + if (m_elementIndex > m_invalidationLimits[index])
|
| + continue;
|
| +
|
| + if (m_invalidationSets[index]->wholeSubtreeInvalid() || m_invalidationSets[index]->invalidatesElement(element))
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| ALWAYS_INLINE bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element& element, StyleInvalidator::RecursionData& recursionData)
|
| {
|
| if (element.styleChangeType() >= SubtreeStyleChange || recursionData.wholeSubtreeInvalid()) {
|
| @@ -129,7 +159,7 @@ ALWAYS_INLINE bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element
|
| return false;
|
| }
|
| if (element.needsStyleInvalidation()) {
|
| - if (InvalidationList* invalidationList = m_pendingInvalidationMap.get(&element)) {
|
| + if (InvalidationList* invalidationList = m_pendingInvalidationMap[InvalidateDescendants].get(&element)) {
|
| for (const auto& invalidationSet : *invalidationList)
|
| recursionData.pushInvalidationSet(*invalidationSet);
|
| if (UNLIKELY(*s_tracingEnabled)) {
|
| @@ -147,28 +177,34 @@ ALWAYS_INLINE bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element
|
|
|
| bool StyleInvalidator::invalidateChildren(Element& element, StyleInvalidator::RecursionData& recursionData)
|
| {
|
| + SiblingData siblingData;
|
| +
|
| bool someChildrenNeedStyleRecalc = false;
|
| for (ShadowRoot* root = element.youngestShadowRoot(); root; root = root->olderShadowRoot()) {
|
| if (!recursionData.treeBoundaryCrossing() && !root->childNeedsStyleInvalidation() && !root->needsStyleInvalidation())
|
| continue;
|
| for (Element* child = ElementTraversal::firstChild(*root); child; child = ElementTraversal::nextSibling(*child)) {
|
| - bool childRecalced = invalidate(*child, recursionData);
|
| + bool childRecalced = invalidate(*child, recursionData, siblingData);
|
| someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced;
|
| }
|
| root->clearChildNeedsStyleInvalidation();
|
| root->clearNeedsStyleInvalidation();
|
| }
|
| for (Element* child = ElementTraversal::firstChild(element); child; child = ElementTraversal::nextSibling(*child)) {
|
| - bool childRecalced = invalidate(*child, recursionData);
|
| + bool childRecalced = invalidate(*child, recursionData, siblingData);
|
| someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced;
|
| }
|
| return someChildrenNeedStyleRecalc;
|
| }
|
|
|
| -bool StyleInvalidator::invalidate(Element& element, StyleInvalidator::RecursionData& recursionData)
|
| +bool StyleInvalidator::invalidate(Element& element, StyleInvalidator::RecursionData& recursionData, SiblingData& siblingData)
|
| {
|
| RecursionCheckpoint checkpoint(&recursionData);
|
|
|
| + if (siblingData.matchesCurrentInvalidationSets(element)) {
|
| + element.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
|
| + }
|
| +
|
| bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(element, recursionData);
|
|
|
| bool someChildrenNeedStyleRecalc = false;
|
| @@ -194,13 +230,20 @@ bool StyleInvalidator::invalidate(Element& element, StyleInvalidator::RecursionD
|
| element.clearChildNeedsStyleInvalidation();
|
| element.clearNeedsStyleInvalidation();
|
|
|
| + if (InvalidationList* invalidationList = m_pendingInvalidationMap[InvalidateSiblings].get(&element)) {
|
| + for (const auto& invalidationSet : *invalidationList) {
|
| + siblingData.pushInvalidationSet(*invalidationSet);
|
| + }
|
| + }
|
| +
|
| return thisElementNeedsStyleRecalc;
|
| }
|
|
|
| DEFINE_TRACE(StyleInvalidator)
|
| {
|
| #if ENABLE(OILPAN)
|
| - visitor->trace(m_pendingInvalidationMap);
|
| + visitor->trace(m_pendingInvalidationMap[InvalidateDescendants]);
|
| + visitor->trace(m_pendingInvalidationMap[InvalidateSiblings]);
|
| #endif
|
| }
|
|
|
|
|