[SCM] WebKit Debian packaging branch, webkit-1.3, updated. upstream/1.3.7-4207-g178b198

antti at apple.com antti at apple.com
Sun Feb 20 23:09:29 UTC 2011


The following commit has been merged in the webkit-1.3 branch:
commit 84c087a0201259dc98f873a80fd8a944ac972e46
Author: antti at apple.com <antti at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Jan 18 10:48:22 2011 +0000

    Source/WebCore:  2011-01-18  Antti Koivisto  <antti at apple.com>
    
    Reviewed by Dave Hyatt.
    
    https://bugs.webkit.org/show_bug.cgi?id=52370
    <rdar://problem/8856808>
    Style sharing optimization no longer works on major web sites
    
    The code in CSSStyleSelector::locateSharedStyle() that tries to share style information between element has been defeated
    by widespread use of certain CSS selectors (:first-child pseudo class and similar). The current implementation disables
    the sharing optimization for the whole page if one of these constructs is seen in any style sheet used by the page.
    
    This patch gets the style sharing back to 25-40% range on most web sites.
    
    * css/CSSMutableStyleDeclaration.h:
    (WebCore::CSSMutableStyleDeclaration::propertiesEqual):
    
        Needed to improve equality checking in NamedNodeMap::mappedMapsEquivalent.
    
    * css/CSSSelector.h:
    (WebCore::CSSSelector::isSiblingSelector):
    
        Test for selectors that are affected by the sibling elements.
    
    * css/CSSStyleSelector.cpp:
    (WebCore::elementCanUseSimpleDefaultStyle):
    (WebCore::collectSiblingRulesInDefaultStyle):
    (WebCore::assertNoSiblingRulesInDefaultStyle):
    
        Extract sibling rules from the MathML default stylesheet.
        Assert that no other default stylesheet has them.
    
    (WebCore::CSSStyleSelector::CSSStyleSelector):
    (WebCore::CSSStyleSelector::locateCousinList):
    (WebCore::CSSStyleSelector::matchesSiblingRules):
    (WebCore::CSSStyleSelector::canShareStyleWithElement):
    (WebCore::CSSStyleSelector::locateSharedStyle):
    (WebCore::CSSStyleSelector::styleForElement):
    (WebCore::collectIdsAndSiblingRulesFromList):
    (WebCore::CSSRuleSet::collectIdsAndSiblingRules):
    
        Track sibling rules and ids used in the stylesheets to allow much more fine-grained rejection of cases
        where style sharing can't be used.
    
    * css/CSSStyleSelector.h:
    * dom/NamedNodeMap.cpp:
    (WebCore::NamedNodeMap::mappedMapsEquivalent):
    
        Check also for CSSValue mutation from DOM.
    
    * mathml/MathMLMathElement.cpp:
    (WebCore::MathMLMathElement::insertedIntoDocument):
    * mathml/MathMLMathElement.h:
    
        MathML default style sheet has sibling rules which don't get noticed by the normal document
        stylesheet parsing.
    
    * rendering/style/RenderStyle.h:
    (WebCore::InheritedFlags::setFirstChildState):
    (WebCore::InheritedFlags::setLastChildState):
    (WebCore::InheritedFlags::setChildIndex):
    
        These all make style non-shareable (unique).
    
    LayoutTests: https://bugs.webkit.org/show_bug.cgi?id=52370
    Style sharing optimization no longer works on major web sites
    
    Reviewed by Dave Hyatt.
    
    These are progressions (with no noticable visual change).
    MathML code was improperly sharing style.
    
    * platform/mac/mathml/presentation/fractions-vertical-alignment-expected.txt:
    * platform/mac/mathml/presentation/subsup-expected.txt:
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76012 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 5edafc4..2082991 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,16 @@
+2011-01-18  Antti Koivisto  <antti at apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        https://bugs.webkit.org/show_bug.cgi?id=52370
+        Style sharing optimization no longer works on major web sites
+        
+        These are progressions (with no noticable visual change). 
+        MathML code was improperly sharing style.
+
+        * platform/mac/mathml/presentation/fractions-vertical-alignment-expected.txt:
+        * platform/mac/mathml/presentation/subsup-expected.txt:
+
 2011-01-18  Philippe Normand  <pnormand at igalia.com>
 
         Unreviewed, rolling out r76002.
diff --git a/LayoutTests/platform/mac/mathml/presentation/fractions-vertical-alignment-expected.txt b/LayoutTests/platform/mac/mathml/presentation/fractions-vertical-alignment-expected.txt
index f41dc72..fc3d9ed 100644
--- a/LayoutTests/platform/mac/mathml/presentation/fractions-vertical-alignment-expected.txt
+++ b/LayoutTests/platform/mac/mathml/presentation/fractions-vertical-alignment-expected.txt
@@ -83,13 +83,13 @@ layer at (0,0) size 800x106
       RenderBlock {math:mo} at (0,0) size 9x16
         RenderText {math:mo} at (0,0) size 9x16
           text run at (0,0) width 9: "+"
-    RenderBlock {math:mfrac} at (164,36) size 71x70
-      RenderBlock {math:mfrac} at (0,0) size 53x16
+    RenderBlock {math:mfrac} at (164,36) size 73x70
+      RenderBlock {math:mfrac} at (0,0) size 55x16
         RenderInline {math:mi} at (0,0) size 10x16
-          RenderText {#text} at (21,0) size 10x16
-            text run at (21,0) width 10: "B"
-      RenderBlock {math:mfrac} at (0,16) size 53x54
-        RenderBlock {math:mrow} at (3,2) size 65x52
+          RenderText {#text} at (22,0) size 10x16
+            text run at (22,0) width 10: "B"
+      RenderBlock {math:mfrac} at (0,16) size 55x54
+        RenderBlock {math:mrow} at (4,2) size 66x52
           RenderInline {math:mi} at (0,0) size 11x16
             RenderText {#text} at (0,10) size 11x16
               text run at (0,10) width 11: "C"
@@ -97,13 +97,13 @@ layer at (0,0) size 800x106
             RenderBlock {math:mo} at (0,0) size 9x16
               RenderText {math:mo} at (0,0) size 9x16
                 text run at (0,0) width 9: "+"
-          RenderBlock {math:mfrac} at (21,0) size 44x52
-            RenderBlock {math:mfrac} at (0,0) size 35x16
+          RenderBlock {math:mfrac} at (21,0) size 45x52
+            RenderBlock {math:mfrac} at (0,0) size 36x16
               RenderInline {math:mi} at (0,0) size 12x16
-                RenderText {#text} at (11,0) size 12x16
-                  text run at (11,0) width 12: "D"
-            RenderBlock {math:mfrac} at (0,16) size 35x36
-              RenderBlock {math:mrow} at (3,2) size 38x34
+                RenderText {#text} at (12,0) size 12x16
+                  text run at (12,0) width 12: "D"
+            RenderBlock {math:mfrac} at (0,16) size 36x36
+              RenderBlock {math:mrow} at (4,2) size 38x34
                 RenderInline {math:mi} at (0,0) size 10x16
                   RenderText {#text} at (0,10) size 10x16
                     text run at (0,10) width 10: "E"
diff --git a/LayoutTests/platform/mac/mathml/presentation/subsup-expected.txt b/LayoutTests/platform/mac/mathml/presentation/subsup-expected.txt
index add47e2..3f2aecf 100644
--- a/LayoutTests/platform/mac/mathml/presentation/subsup-expected.txt
+++ b/LayoutTests/platform/mac/mathml/presentation/subsup-expected.txt
@@ -94,7 +94,7 @@ layer at (0,0) size 800x256
                   text run at (0,8) width 9: "Z"
             RenderBlock {msubsup} at (10,0) size 32x32
               RenderBlock {msubsup} at (0,0) size 18x16
-                RenderBlock {mrow} at (1,3) size 16x12
+                RenderBlock {mrow} at (0,3) size 16x12
                   RenderInline {mi} at (0,0) size 5x12
                     RenderText {#text} at (0,0) size 5x12
                       text run at (0,0) width 5: "k"
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 5c0c78b..91a1cc3 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,67 @@
+ 2011-01-18  Antti Koivisto  <antti at apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        https://bugs.webkit.org/show_bug.cgi?id=52370
+        <rdar://problem/8856808>
+        Style sharing optimization no longer works on major web sites
+        
+        The code in CSSStyleSelector::locateSharedStyle() that tries to share style information between element has been defeated 
+        by widespread use of certain CSS selectors (:first-child pseudo class and similar). The current implementation disables
+        the sharing optimization for the whole page if one of these constructs is seen in any style sheet used by the page.  
+        
+        This patch gets the style sharing back to 25-40% range on most web sites.
+
+        * css/CSSMutableStyleDeclaration.h:
+        (WebCore::CSSMutableStyleDeclaration::propertiesEqual):
+            
+            Needed to improve equality checking in NamedNodeMap::mappedMapsEquivalent.
+        
+        * css/CSSSelector.h:
+        (WebCore::CSSSelector::isSiblingSelector):
+        
+            Test for selectors that are affected by the sibling elements.
+        
+        * css/CSSStyleSelector.cpp:
+        (WebCore::elementCanUseSimpleDefaultStyle):
+        (WebCore::collectSiblingRulesInDefaultStyle):
+        (WebCore::assertNoSiblingRulesInDefaultStyle):
+            
+            Extract sibling rules from the MathML default stylesheet. 
+            Assert that no other default stylesheet has them.
+            
+        (WebCore::CSSStyleSelector::CSSStyleSelector):
+        (WebCore::CSSStyleSelector::locateCousinList):
+        (WebCore::CSSStyleSelector::matchesSiblingRules):
+        (WebCore::CSSStyleSelector::canShareStyleWithElement):
+        (WebCore::CSSStyleSelector::locateSharedStyle):
+        (WebCore::CSSStyleSelector::styleForElement):
+        (WebCore::collectIdsAndSiblingRulesFromList):
+        (WebCore::CSSRuleSet::collectIdsAndSiblingRules):
+
+            Track sibling rules and ids used in the stylesheets to allow much more fine-grained rejection of cases
+            where style sharing can't be used.
+
+        * css/CSSStyleSelector.h:
+        * dom/NamedNodeMap.cpp:
+        (WebCore::NamedNodeMap::mappedMapsEquivalent):
+            
+            Check also for CSSValue mutation from DOM. 
+            
+        * mathml/MathMLMathElement.cpp:
+        (WebCore::MathMLMathElement::insertedIntoDocument):
+        * mathml/MathMLMathElement.h:
+        
+            MathML default style sheet has sibling rules which don't get noticed by the normal document
+            stylesheet parsing.
+        
+        * rendering/style/RenderStyle.h:
+        (WebCore::InheritedFlags::setFirstChildState):
+        (WebCore::InheritedFlags::setLastChildState):
+        (WebCore::InheritedFlags::setChildIndex):
+        
+            These all make style non-shareable (unique).
+
 2011-01-18  MORITA Hajime  <morrita at google.com>
 
         Unreviewed crash fix on release builds.
diff --git a/Source/WebCore/css/CSSMutableStyleDeclaration.h b/Source/WebCore/css/CSSMutableStyleDeclaration.h
index f7d8ca9..35f1cc4 100644
--- a/Source/WebCore/css/CSSMutableStyleDeclaration.h
+++ b/Source/WebCore/css/CSSMutableStyleDeclaration.h
@@ -135,6 +135,8 @@ public:
     bool useStrictParsing() const { return m_strictParsing; }
 
     void addSubresourceStyleURLs(ListHashSet<KURL>&);
+    
+    bool propertiesEqual(const CSSMutableStyleDeclaration* o) const { return m_properties == o->m_properties; }
 
 protected:
     CSSMutableStyleDeclaration(CSSRule* parentRule);
diff --git a/Source/WebCore/css/CSSSelector.h b/Source/WebCore/css/CSSSelector.h
index 1101eed..5456be6 100644
--- a/Source/WebCore/css/CSSSelector.h
+++ b/Source/WebCore/css/CSSSelector.h
@@ -278,6 +278,7 @@ namespace WebCore {
             return m_match == PseudoElement;
         }
         bool isUnknownPseudoElement() const;
+        bool isSiblingSelector() const;
 
         Relation relation() const { return static_cast<Relation>(m_relation); }
 
@@ -350,6 +351,24 @@ inline bool CSSSelector::isUnknownPseudoElement() const
     return m_match == PseudoElement && m_pseudoType == PseudoUnknown;
 }
 
+inline bool CSSSelector::isSiblingSelector() const
+{
+    PseudoType type = pseudoType();
+    return m_relation == DirectAdjacent
+        || m_relation == IndirectAdjacent
+        || type == PseudoEmpty
+        || type == PseudoFirstChild
+        || type == PseudoFirstOfType
+        || type == PseudoLastChild
+        || type == PseudoLastOfType
+        || type == PseudoOnlyChild
+        || type == PseudoOnlyOfType
+        || type == PseudoNthChild
+        || type == PseudoNthOfType
+        || type == PseudoNthLastChild
+        || type == PseudoNthLastOfType;
+}
+
 } // namespace WebCore
 
 #endif // CSSSelector_h
diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp
index 583df56..fc0722a 100644
--- a/Source/WebCore/css/CSSStyleSelector.cpp
+++ b/Source/WebCore/css/CSSStyleSelector.cpp
@@ -400,8 +400,8 @@ public:
         }
     }
 
-    CSSRuleData* first() { return m_first; }
-    CSSRuleData* last() { return m_last; }
+    CSSRuleData* first() const { return m_first; }
+    CSSRuleData* last() const { return m_last; }
 
     void append(unsigned pos, CSSStyleRule* rule, CSSSelector* sel) { m_last = new CSSRuleData(pos, rule, sel, m_last); }
 
@@ -425,6 +425,8 @@ public:
     void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
                       CSSStyleRule* rule, CSSSelector* sel);
     
+    void collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<CSSRuleSet>& siblingRules) const;
+    
     CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
     CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
     CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
@@ -448,6 +450,8 @@ static CSSRuleSet* defaultQuirksStyle;
 static CSSRuleSet* defaultPrintStyle;
 static CSSRuleSet* defaultViewSourceStyle;
 static CSSStyleSheet* simpleDefaultStyleSheet;
+    
+static CSSRuleSet* siblingRulesInDefaultStyle;
 
 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
 
@@ -459,11 +463,31 @@ static void loadSimpleDefaultStyle();
 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
 static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}";
 
-static bool elementCanUseSimpleDefaultStyle(Element* e)
+static inline bool elementCanUseSimpleDefaultStyle(Element* e)
 {
     return e->hasTagName(htmlTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
 }
 
+static inline void collectSiblingRulesInDefaultStyle()
+{
+    OwnPtr<CSSRuleSet> siblingRules;
+    HashSet<AtomicStringImpl*> ids;
+    defaultStyle->collectIdsAndSiblingRules(ids, siblingRules);
+    ASSERT(ids.isEmpty());
+    delete siblingRulesInDefaultStyle;
+    siblingRulesInDefaultStyle = siblingRules.leakPtr();
+}
+
+static inline void assertNoSiblingRulesInDefaultStyle()
+{
+#ifndef NDEBUG
+    if (siblingRulesInDefaultStyle)
+        return;
+    collectSiblingRulesInDefaultStyle();
+    ASSERT(!siblingRulesInDefaultStyle);
+#endif
+}
+    
 static const MediaQueryEvaluator& screenEval()
 {
     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
@@ -549,6 +573,16 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee
         if (sheet->isCSSStyleSheet() && !sheet->disabled())
             m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
     }
+    
+    // Collect all ids and rules using sibling selectors (:first-child and similar)
+    // in the current set of stylesheets. Style sharing code uses this information to reject
+    // sharing candidates.
+    // Usually there are no sibling rules in the default style but the MathML sheet has some.
+    if (siblingRulesInDefaultStyle)
+        siblingRulesInDefaultStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules);
+    m_authorStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules);
+    if (m_userStyle)
+        m_userStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules);
 
     if (document->renderer() && document->renderer()->style())
         document->renderer()->style()->font().update(fontSelector());
@@ -944,40 +978,52 @@ static const unsigned cStyleSearchThreshold = 10;
 
 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth) const
 {
-    if (parent && parent->isStyledElement()) {
-        StyledElement* p = static_cast<StyledElement*>(parent);
-        if (!p->inlineStyleDecl() && !p->hasID()) {
-            Node* r = p->previousSibling();
-            unsigned subcount = 0;
-            RenderStyle* st = p->renderStyle();
-            while (r) {
-                if (r->renderStyle() == st)
-                    return r->lastChild();
-                if (subcount++ == cStyleSearchThreshold)
-                    return 0;
-                r = r->previousSibling();
-            }
-            if (!r && depth < cStyleSearchThreshold)
-                r = locateCousinList(parent->parentElement(), depth + 1);
-            while (r) {
-                if (r->renderStyle() == st)
-                    return r->lastChild();
-                if (subcount++ == cStyleSearchThreshold)
-                    return 0;
-                r = r->previousSibling();
-            }
-        }
+    if (!parent || !parent->isStyledElement())
+        return 0;
+    StyledElement* p = static_cast<StyledElement*>(parent);
+    if (p->inlineStyleDecl())
+        return 0;
+    if (p->hasID() && m_idsInRules.contains(p->idForStyleResolution().impl()))
+        return 0;
+    Node* r = p->previousSibling();
+    unsigned subcount = 0;
+    RenderStyle* st = p->renderStyle();
+    while (r) {
+        if (r->renderStyle() == st)
+            return r->lastChild();
+        if (subcount++ == cStyleSearchThreshold)
+            return 0;
+        r = r->previousSibling();
+    }
+    if (!r && depth < cStyleSearchThreshold)
+        r = locateCousinList(parent->parentElement(), depth + 1);
+    while (r) {
+        if (r->renderStyle() == st)
+            return r->lastChild();
+        if (subcount++ == cStyleSearchThreshold)
+            return 0;
+        r = r->previousSibling();
     }
     return 0;
 }
 
+bool CSSStyleSelector::matchesSiblingRules()
+{
+    int firstSiblingRule = -1, lastSiblingRule = -1;
+    matchRules(m_siblingRules.get(), firstSiblingRule, lastSiblingRule, false);
+    if (m_matchedDecls.isEmpty())
+        return false;
+    m_matchedDecls.clear();
+    return true;
+}
+
 bool CSSStyleSelector::canShareStyleWithElement(Node* n) const
 {
     if (n->isStyledElement()) {
         StyledElement* s = static_cast<StyledElement*>(n);
         RenderStyle* style = s->renderStyle();
         if (style && !style->unique() &&
-            (s->tagQName() == m_element->tagQName()) && !s->hasID() &&
+            (s->tagQName() == m_element->tagQName()) &&
             (s->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() &&
             (s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) &&
             (s->isLink() == m_element->isLink()) && 
@@ -992,6 +1038,10 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n) const
             (s->fastGetAttribute(langAttr) == m_element->fastGetAttribute(langAttr)) &&
             (s->fastGetAttribute(readonlyAttr) == m_element->fastGetAttribute(readonlyAttr)) &&
             (s->fastGetAttribute(cellpaddingAttr) == m_element->fastGetAttribute(cellpaddingAttr))) {
+            
+            if (s->hasID() && m_idsInRules.contains(s->idForStyleResolution().impl()))
+                return 0;
+            
             bool isControl = s->isFormControlElement();
             if (isControl != m_element->isFormControlElement())
                 return false;
@@ -1062,32 +1112,46 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n) const
     }
     return false;
 }
-
-ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle() const
+    
+inline Node* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const
 {
-    if (m_styledElement && !m_styledElement->inlineStyleDecl() && !m_styledElement->hasID() && !m_styledElement->document()->usesSiblingRules()) {
-        // Check previous siblings.
-        unsigned count = 0;
-        Node* n;
-        for (n = m_element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
-        while (n) {
-            if (canShareStyleWithElement(n))
-                return n->renderStyle();
-            if (count++ == cStyleSearchThreshold)
-                return 0;
-            for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
-        }
-        if (!n) 
-            n = locateCousinList(m_element->parentElement());
-        while (n) {
-            if (canShareStyleWithElement(n))
-                return n->renderStyle();
-            if (count++ == cStyleSearchThreshold)
-                return 0;
-            for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
-        }        
+    for (; node; node = node->previousSibling()) {
+        if (!node->isElementNode())
+            continue;
+        if (canShareStyleWithElement(node))
+            break;
+        if (count++ == cStyleSearchThreshold)
+            return 0;
     }
-    return 0;
+    return node;
+}
+
+ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
+{
+    if (!m_styledElement || !m_parentStyle)
+        return 0;
+    // If the element has inline style it is probably unique.
+    if (m_styledElement->inlineStyleDecl())
+        return 0;
+    // Ids stop style sharing if they show up in the stylesheets.
+    if (m_styledElement->hasID() && m_idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
+        return 0;
+    // Check previous siblings.
+    unsigned count = 0;
+    Node* shareNode = findSiblingForStyleSharing(m_styledElement->previousSibling(), count);
+    if (!shareNode) {
+        Node* cousinList = locateCousinList(m_styledElement->parentElement());
+        shareNode = findSiblingForStyleSharing(cousinList, count); 
+        if (!shareNode)
+            return 0;
+    }
+    // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
+    if (matchesSiblingRules())
+        return 0;
+    // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
+    if (m_parentStyle->childrenAffectedByPositionalRules())
+        return 0;
+    return shareNode->renderStyle();
 }
 
 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
@@ -1180,12 +1244,12 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
     }
 
     initElement(e);
+    initForStyleResolve(e, defaultParent);
     if (allowSharing) {
         RenderStyle* sharedStyle = locateSharedStyle();
         if (sharedStyle)
             return sharedStyle;
     }
-    initForStyleResolve(e, defaultParent);
 
     // Compute our style allowing :visited to match first.
     RefPtr<RenderStyle> visitedStyle;
@@ -1227,6 +1291,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
 #if ENABLE(FULLSCREEN_API)
         loadFullScreenRulesIfNeeded(e->document());
 #endif
+        assertNoSiblingRulesInDefaultStyle();
     }
 
 #if ENABLE(SVG)
@@ -1237,6 +1302,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
         CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
         defaultStyle->addRulesFromSheet(svgSheet, screenEval());
         defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
+        assertNoSiblingRulesInDefaultStyle();
     }
 #endif
 
@@ -1248,6 +1314,8 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
         CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
         defaultStyle->addRulesFromSheet(mathMLSheet, screenEval());
         defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval());
+        // There are some sibling rules here.
+        collectSiblingRulesInDefaultStyle();
     }
 #endif
 
@@ -1259,6 +1327,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
         CSSStyleSheet* wmlSheet = parseUASheet(wmlUserAgentStyleSheet, sizeof(wmlUserAgentStyleSheet));
         defaultStyle->addRulesFromSheet(wmlSheet, screenEval());
         defaultPrintStyle->addRulesFromSheet(wmlSheet, printEval());
+        assertNoSiblingRulesInDefaultStyle();
     }
 #endif
 
@@ -1270,6 +1339,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
         CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
         defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
         defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
+        assertNoSiblingRulesInDefaultStyle();
     }
 #endif
 
@@ -2927,6 +2997,47 @@ void CSSRuleSet::addStyleRule(CSSStyleRule* rule)
     }
 }
 
+static void collectIdsAndSiblingRulesFromList(HashSet<AtomicStringImpl*>& ids, OwnPtr<CSSRuleSet>& siblingRules, const CSSRuleDataList* rules)
+{
+    for (CSSRuleData* data = rules->first(); data; data = data->next()) {
+        bool foundSiblingSelector = false;
+        for (CSSSelector* selector = data->selector(); selector; selector = selector->tagHistory()) {
+            if (selector->m_match == CSSSelector::Id && !selector->m_value.isEmpty())
+                ids.add(selector->m_value.impl());
+            if (CSSSelector* simpleSelector = selector->simpleSelector()) {
+                ASSERT(!simpleSelector->simpleSelector());
+                if (simpleSelector->m_match == CSSSelector::Id && !simpleSelector->m_value.isEmpty())
+                    ids.add(simpleSelector->m_value.impl());
+            }
+            if (selector->isSiblingSelector())
+                foundSiblingSelector = true;
+        }
+        if (foundSiblingSelector) {
+            if (!siblingRules)
+                siblingRules = adoptPtr(new CSSRuleSet);
+            siblingRules->addRule(data->rule(), data->selector());   
+        }
+    }
+}
+
+void CSSRuleSet::collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<CSSRuleSet>& siblingRules) const
+{
+    AtomRuleMap::const_iterator end = m_idRules.end();
+    for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it)
+        collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
+    end = m_classRules.end();
+    for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it)
+        collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
+    end = m_tagRules.end();
+    for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it)
+        collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
+    end = m_pseudoRules.end();
+    for (AtomRuleMap::const_iterator it = m_pseudoRules.begin(); it != end; ++it)
+        collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
+    if (m_universalRules)
+        collectIdsAndSiblingRulesFromList(ids, siblingRules, m_universalRules.get());
+}
+
 // -------------------------------------------------------------------------------------
 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
 
diff --git a/Source/WebCore/css/CSSStyleSelector.h b/Source/WebCore/css/CSSStyleSelector.h
index b57ba13..eeace57 100644
--- a/Source/WebCore/css/CSSStyleSelector.h
+++ b/Source/WebCore/css/CSSStyleSelector.h
@@ -108,8 +108,10 @@ public:
     private:
         void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, PseudoId = NOPSEUDO);
         void initElement(Element*);
-        ALWAYS_INLINE RenderStyle* locateSharedStyle() const;
+        RenderStyle* locateSharedStyle();
+        bool matchesSiblingRules();
         Node* locateCousinList(Element* parent, unsigned depth = 1) const;
+        Node* findSiblingForStyleSharing(Node*, unsigned& count) const;
         bool canShareStyleWithElement(Node*) const;
 
         RenderStyle* style() const { return m_style.get(); }
@@ -197,6 +199,9 @@ public:
         
         OwnPtr<CSSRuleSet> m_authorStyle;
         OwnPtr<CSSRuleSet> m_userStyle;
+        
+        OwnPtr<CSSRuleSet> m_siblingRules;
+        HashSet<AtomicStringImpl*> m_idsInRules;
 
         bool m_hasUAAppearance;
         BorderData m_borderData;
diff --git a/Source/WebCore/dom/NamedNodeMap.cpp b/Source/WebCore/dom/NamedNodeMap.cpp
index bc56f7e..0e2861e 100644
--- a/Source/WebCore/dom/NamedNodeMap.cpp
+++ b/Source/WebCore/dom/NamedNodeMap.cpp
@@ -359,6 +359,8 @@ bool NamedNodeMap::mappedMapsEquivalent(const NamedNodeMap* otherMap) const
             Attribute* otherAttr = otherMap->getAttributeItem(attr->name());
             if (!otherAttr || attr->value() != otherAttr->value())
                 return false;
+            if (!attr->decl()->propertiesEqual(otherAttr->decl()))
+                return false;
         }
     }
     return true;
diff --git a/Source/WebCore/mathml/MathMLMathElement.cpp b/Source/WebCore/mathml/MathMLMathElement.cpp
index 6c5c3c6..ae74b52 100644
--- a/Source/WebCore/mathml/MathMLMathElement.cpp
+++ b/Source/WebCore/mathml/MathMLMathElement.cpp
@@ -44,6 +44,14 @@ PassRefPtr<MathMLMathElement> MathMLMathElement::create(const QualifiedName& tag
     return adoptRef(new MathMLMathElement(tagName, document));
 }
 
+void MathMLMathElement::insertedIntoDocument()
+{
+    // There are sibling rules in the MathML default style.
+    document()->setUsesSiblingRules(true);
+    
+    MathMLInlineContainerElement::insertedIntoDocument();
+}
+
 RenderObject* MathMLMathElement::createRenderer(RenderArena* arena, RenderStyle*)
 {
     return new (arena) RenderMathMLMath(this);
diff --git a/Source/WebCore/mathml/MathMLMathElement.h b/Source/WebCore/mathml/MathMLMathElement.h
index d31d548..81f161b 100644
--- a/Source/WebCore/mathml/MathMLMathElement.h
+++ b/Source/WebCore/mathml/MathMLMathElement.h
@@ -39,6 +39,7 @@ public:
 private:
     MathMLMathElement(const QualifiedName& tagName, Document*);
 
+    virtual void insertedIntoDocument();
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
 };
     
diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h
index 1ef981a..75ba048 100644
--- a/Source/WebCore/rendering/style/RenderStyle.h
+++ b/Source/WebCore/rendering/style/RenderStyle.h
@@ -1176,11 +1176,11 @@ public:
     bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; }
     void setChildrenAffectedByBackwardPositionalRules() { m_childrenAffectedByBackwardPositionalRules = true; }
     bool firstChildState() const { return m_firstChildState; }
-    void setFirstChildState() { m_firstChildState = true; }
+    void setFirstChildState() { m_unique = true; m_firstChildState = true; }
     bool lastChildState() const { return m_lastChildState; }
-    void setLastChildState() { m_lastChildState = true; }
+    void setLastChildState() { m_unique = true; m_lastChildState = true; }
     unsigned childIndex() const { return m_childIndex; }
-    void setChildIndex(unsigned index) { m_childIndex = index; }
+    void setChildIndex(unsigned index) { m_unique = true; m_childIndex = index; }
 
     const Color visitedDependentColor(int colorProperty) const;
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list