From ae03d0a33778539b58a451f9acb6fb69e032336f Mon Sep 17 00:00:00 2001 From: "kling@webkit.org" Date: Thu, 9 Feb 2012 04:41:19 +0000 Subject: [PATCH] Increased style sharing for elements with presentation attributes. Reviewed by Antti Koivisto. When determining whether two elements can share style, we can do a lot better. Instead of comparing the attribute maps for exact equality, do a property-by-property comparison of the attributeStyle() and the additionalAttributeStyle() (if any.) This increases our style sharing hit rate and shaves 100ms off of each cycle on Chromium's "Moz" page cycler test on my machine. The function that compares attribute styles has O(n^2) runtime in the worst case, where n is the number of properties in the styles. However, given the low number of properties found in attribute styles, this should be fine, and it doesn't seem to heat up in profiles. * css/CSSStyleSelector.cpp: (WebCore::attributeStylesEqual): (WebCore::CSSStyleSelector::canShareStyleWithElement): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@107173 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/WebCore/ChangeLog | 23 ++++++++++++++++++++++ Source/WebCore/css/CSSStyleSelector.cpp | 35 ++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index 2f58add..6ec5a25 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,26 @@ +2012-02-08 Andreas Kling + + Increased style sharing for elements with presentation attributes. + + + Reviewed by Antti Koivisto. + + When determining whether two elements can share style, we can do a lot better. + Instead of comparing the attribute maps for exact equality, do a property-by-property + comparison of the attributeStyle() and the additionalAttributeStyle() (if any.) + + This increases our style sharing hit rate and shaves 100ms off of each cycle on + Chromium's "Moz" page cycler test on my machine. + + The function that compares attribute styles has O(n^2) runtime in the worst case, + where n is the number of properties in the styles. However, given the low number of + properties found in attribute styles, this should be fine, and it doesn't seem to + heat up in profiles. + + * css/CSSStyleSelector.cpp: + (WebCore::attributeStylesEqual): + (WebCore::CSSStyleSelector::canShareStyleWithElement): + 2012-02-08 Raymond Liu Fix the caculation of preDelayFrames in DynamicsCompressorKernel diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp index 54cdd93..7f158f6 100644 --- a/Source/WebCore/css/CSSStyleSelector.cpp +++ b/Source/WebCore/css/CSSStyleSelector.cpp @@ -1194,6 +1194,32 @@ bool CSSStyleSelector::canShareStyleWithControl(StyledElement* element) const return true; } +// This function makes some assumptions that only make sense for attribute styles (we only compare CSSProperty::id() and CSSProperty::value().) +static inline bool attributeStylesEqual(StylePropertySet* a, StylePropertySet* b) +{ + if (a == b) + return true; + if (a->propertyCount() != b->propertyCount()) + return false; + unsigned propertyCount = a->propertyCount(); + for (unsigned i = 0; i < propertyCount; ++i) { + const CSSProperty& aProperty = a->propertyAt(i); + unsigned j; + for (j = 0; j < propertyCount; ++j) { + const CSSProperty& bProperty = b->propertyAt(j); + if (aProperty.id() != bProperty.id()) + continue; + // We could get a few more hits by comparing cssText() here, but that gets expensive quickly. + if (aProperty.value() != bProperty.value()) + return false; + break; + } + if (j == propertyCount) + return false; + } + return true; +} + bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const { RenderStyle* style = element->renderStyle(); @@ -1210,6 +1236,10 @@ bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const return false; if (!!element->attributeStyle() != !!m_styledElement->attributeStyle()) return false; + StylePropertySet* additionalAttributeStyleA = element->additionalAttributeStyle().get(); + StylePropertySet* additionalAttributeStyleB = m_styledElement->additionalAttributeStyle().get(); + if (!additionalAttributeStyleA != !additionalAttributeStyleB) + return false; if (element->isLink() != m_element->isLink()) return false; if (style->affectedByUncommonAttributeSelectors()) @@ -1274,7 +1304,10 @@ bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const if (element->hasClass() && m_element->getAttribute(classAttr) != element->getAttribute(classAttr)) return false; - if (element->attributeStyle() && !element->attributeMap()->mapsEquivalent(m_styledElement->attributeMap())) + if (element->attributeStyle() && !attributeStylesEqual(element->attributeStyle(), m_styledElement->attributeStyle())) + return false; + + if (additionalAttributeStyleA && !attributeStylesEqual(additionalAttributeStyleA, additionalAttributeStyleB)) return false; if (element->isLink() && m_elementLinkState != style->insideLink()) -- 2.7.4