Optimize style invalidations for attribute selectors
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 Feb 2016 08:20:58 +0000 (08:20 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 16 Feb 2016 08:20:58 +0000 (08:20 +0000)
commit26168ef51e4cd23f4b3823cae625c11d32052827
tree9710cffdb5fcaf3be8dbc66a3158d551929117c6
parentbb8778d50194249a7a4f46694b7225ca96e49480
Optimize style invalidations for attribute selectors
https://bugs.webkit.org/show_bug.cgi?id=154242

Reviewed by Andreas Kling.

Source/WebCore:

Currently we invalidate the whole element subtree if there are any attribute selectors for the changed attribute.
This is slow as generally few if any elements are really affected. Using attribute selectors for dynamic styling
should be performant.

This patch implements optimization strategy for attributes similar to what we already have for classes:

- Collect a map of all rules that contains descendant-affecting attribute selectors for a given attribute.
- When an attribute value changes check if there are any such rules for it.
- Check if the value change affects the results of any of the attribute selectors.
- Only if it does invalidate the exact descendant elements affected by the rules.

Test: fast/css/style-invalidation-attribute-change-descendants.html

* WebCore.xcodeproj/project.pbxproj:
* css/DocumentRuleSets.cpp:
(WebCore::DocumentRuleSets::ancestorClassRules):
(WebCore::DocumentRuleSets::ancestorAttributeRulesForHTML):

    Create optimization RuleSets when needed.

* css/DocumentRuleSets.h:
(WebCore::DocumentRuleSets::uncommonAttribute):
(WebCore::DocumentRuleSets::features):
* css/RuleFeature.cpp:
(WebCore::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
(WebCore::makeAttributeSelectorKey):
(WebCore::RuleFeatureSet::collectFeatures):

    Collect rules with descendant affecting attribute selectors.

(WebCore::RuleFeatureSet::add):
(WebCore::RuleFeatureSet::clear):
(WebCore::RuleFeatureSet::shrinkToFit):
* css/RuleFeature.h:
* css/SelectorChecker.cpp:
(WebCore::anyAttributeMatches):
(WebCore::SelectorChecker::attributeSelectorMatches):

    Expose function for matching single attribute selectors.

(WebCore::canMatchHoverOrActiveInQuirksMode):
* css/SelectorChecker.h:
* dom/Attr.cpp:
(WebCore::Attr::setValue):
(WebCore::Attr::childrenChanged):
* dom/Element.cpp:
(WebCore::Element::setAttributeInternal):
(WebCore::makeIdForStyleResolution):
(WebCore::Element::attributeChanged):
(WebCore::Element::removeAttributeInternal):
(WebCore::Element::addAttributeInternal):
(WebCore::Element::removeAttribute):

    Add AttributeChangeInvalidation where needed.

(WebCore::Element::needsStyleInvalidation):

    Move to Element from ClassChangeInvalidation.

(WebCore::Element::willModifyAttribute):

    No more full style invalidation on attribute change.

* style/AttributeChangeInvalidation.cpp: Added.
(WebCore::Style::AttributeChangeInvalidation::invalidateStyle):

    Invalidate local style.
    Check if we need to invalidate descendants by looking into ancestorAttributeRules.

(WebCore::Style::AttributeChangeInvalidation::invalidateDescendants):

    Use StyleInvalidationAnalysis to invalidate the subtree for the relevant rules.

* style/AttributeChangeInvalidation.h: Added.
(WebCore::Style::AttributeChangeInvalidation::needsInvalidation):
(WebCore::Style::AttributeChangeInvalidation::AttributeChangeInvalidation):
(WebCore::Style::AttributeChangeInvalidation::~AttributeChangeInvalidation):

    If needed, invalidate descendants before and after attribute change to catch rules that start and stop applying.

LayoutTests:

* fast/css/style-invalidation-attribute-change-descendants-expected.txt: Added.
* fast/css/style-invalidation-attribute-change-descendants.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@196629 268f45cc-cd09-0410-ab3c-d52691b4dbfc
19 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css/style-invalidation-attribute-change-descendants-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/style-invalidation-attribute-change-descendants.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/DocumentRuleSets.cpp
Source/WebCore/css/DocumentRuleSets.h
Source/WebCore/css/RuleFeature.cpp
Source/WebCore/css/RuleFeature.h
Source/WebCore/css/SelectorChecker.cpp
Source/WebCore/css/SelectorChecker.h
Source/WebCore/dom/Attr.cpp
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/style/AttributeChangeInvalidation.cpp [new file with mode: 0644]
Source/WebCore/style/AttributeChangeInvalidation.h [new file with mode: 0644]
Source/WebCore/style/ClassChangeInvalidation.h