StyleResolver: Optimize sharing candidate evaluation for elements with shared attribu...
authorakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Nov 2012 17:54:27 +0000 (17:54 +0000)
committerakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Nov 2012 17:54:27 +0000 (17:54 +0000)
<http://webkit.org/b/102507>

Reviewed by Antti Koivisto.

When evaluating two elements as potential style sharing candidate, we have a whole bunch of code
comparing the various attributes that would prevent sharing.

If the two elements both share the same ElementAttributeData, we can skip all those checks
since they are guaranteed to have equal attributes.

Cuts the time spent in canShareStyleWithElement() by 25% on the HTML5 spec at <http://whatwg.org/c>.

* css/StyleResolver.cpp:
(WebCore::haveIdenticalStyleAffectingAttributes):
(WebCore::StyleResolver::canShareStyleWithElement):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@134962 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/css/StyleResolver.cpp

index c825f51..a515392 100644 (file)
@@ -1,3 +1,22 @@
+2012-11-16  Andreas Kling  <akling@apple.com>
+
+        StyleResolver: Optimize sharing candidate evaluation for elements with shared attribute data.
+        <http://webkit.org/b/102507>
+
+        Reviewed by Antti Koivisto.
+
+        When evaluating two elements as potential style sharing candidate, we have a whole bunch of code
+        comparing the various attributes that would prevent sharing.
+
+        If the two elements both share the same ElementAttributeData, we can skip all those checks
+        since they are guaranteed to have equal attributes.
+
+        Cuts the time spent in canShareStyleWithElement() by 25% on the HTML5 spec at <http://whatwg.org/c>.
+
+        * css/StyleResolver.cpp:
+        (WebCore::haveIdenticalStyleAffectingAttributes):
+        (WebCore::StyleResolver::canShareStyleWithElement):
+
 2012-11-16  Byungwoo Lee  <bw80.lee@samsung.com>
 
         [EFL][GTK] Build fix after r134955
index fb5eaef..cdaf599 100644 (file)
@@ -1152,6 +1152,44 @@ static inline bool elementHasDirectionAuto(Element* element)
     return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto();
 }
 
+static inline bool haveIdenticalStyleAffectingAttributes(StyledElement* a, StyledElement* b)
+{
+    if (a->attributeData() == b->attributeData())
+        return true;
+    if (a->fastGetAttribute(XMLNames::langAttr) != b->fastGetAttribute(XMLNames::langAttr))
+        return false;
+    if (a->fastGetAttribute(langAttr) != b->fastGetAttribute(langAttr))
+        return false;
+    if (a->fastGetAttribute(readonlyAttr) != b->fastGetAttribute(readonlyAttr))
+        return false;
+    // FIXME: This is probably not necessary.
+    if (a->fastGetAttribute(cellpaddingAttr) != b->fastGetAttribute(cellpaddingAttr))
+        return false;
+    if (a->hasClass()) {
+#if ENABLE(SVG)
+        // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
+        if (a->isSVGElement()) {
+            if (a->getAttribute(classAttr) != b->getAttribute(classAttr))
+                return false;
+        } else
+#endif
+        if (a->fastGetAttribute(classAttr) != b->fastGetAttribute(classAttr))
+            return false;
+    }
+
+    if (a->presentationAttributeStyle() && !attributeStylesEqual(a->presentationAttributeStyle(), b->presentationAttributeStyle()))
+        return false;
+
+#if ENABLE(PROGRESS_ELEMENT)
+    if (a->hasTagName(progressTag)) {
+        if (static_cast<HTMLProgressElement*>(a)->isDeterminate() != static_cast<HTMLProgressElement*>(b)->isDeterminate())
+            return false;
+    }
+#endif
+
+    return true;
+}
+
 bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
 {
     RenderStyle* style = element->renderStyle();
@@ -1192,29 +1230,15 @@ bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
         return false;
     if (element == element->document()->cssTarget())
         return false;
-    if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
-        return false;
-    if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
-        return false;
-    if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
-        return false;
-    if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
+
+    if (!haveIdenticalStyleAffectingAttributes(element, m_styledElement))
         return false;
+
     if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
         return false;
     if (element->hasScopedHTMLStyleChild())
         return false;
 
-#if ENABLE(PROGRESS_ELEMENT)
-    if (element->hasTagName(progressTag)) {
-        ASSERT(m_element->hasTagName(progressTag));
-        HTMLProgressElement* thisProgressElement = static_cast<HTMLProgressElement*>(element);
-        HTMLProgressElement* otherProgressElement = static_cast<HTMLProgressElement*>(m_element);
-        if (thisProgressElement->isDeterminate() != otherProgressElement->isDeterminate())
-            return false;
-    }
-#endif
-
     // FIXME: We should share style for option and optgroup whenever possible.
     // Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems
     // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405
@@ -1247,21 +1271,6 @@ bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
     if (elementHasDirectionAuto(element))
         return false;
 
-    if (element->hasClass()) {
-#if ENABLE(SVG)
-        // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
-        if (element->isSVGElement()) {
-            if (element->getAttribute(classAttr) != m_element->getAttribute(classAttr))
-                return false;
-        } else
-#endif
-        if (element->fastGetAttribute(classAttr) != m_element->fastGetAttribute(classAttr))
-            return false;
-    }
-
-    if (element->presentationAttributeStyle() && !attributeStylesEqual(element->presentationAttributeStyle(), m_styledElement->presentationAttributeStyle()))
-        return false;
-
     if (additionalPresentationAttributeStyleA && !attributeStylesEqual(additionalPresentationAttributeStyleA, additionalPresentationAttributeStyleB))
         return false;