Changeset 30667 in webkit
- Timestamp:
- Feb 29, 2008 10:58:06 AM (16 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r30665 r30667 1 2008-02-29 David Hyatt <hyatt@apple.com> 2 3 <rdar://problem/5755916> REGRESSION: Loading HTML5 spec is 5x slower on TOT than in 3.0.4 4 5 Improve the performance of dynamic sibling and CSS3 selectors so that there is no slowdown any more. 6 Be more precise in terms of what nodes we mark dirty. 7 8 Reviewed by Beth 9 10 * css/CSSStyleSelector.cpp: 11 (WebCore::CSSStyleSelector::checkSelector): 12 * dom/Element.cpp: 13 (WebCore::Element::recalcStyle): 14 (WebCore::checkForSiblingStyleChanges): 15 (WebCore::Element::childrenChanged): 16 (WebCore::Element::finishParsingChildren): 17 * rendering/RenderStyle.cpp: 18 (WebCore::RenderStyle::RenderStyle): 19 * rendering/RenderStyle.h: 20 (WebCore::RenderStyle::childrenAffectedByPositionalRules): 21 (WebCore::RenderStyle::childrenAffectedByDirectAdjacentRules): 22 (WebCore::RenderStyle::setChildrenAffectedByDirectAdjacentRules): 23 1 24 2008-02-29 Alexey Proskuryakov <ap@webkit.org> 2 25 -
trunk/WebCore/css/CSSStyleSelector.cpp
r30593 r30667 1430 1430 RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); 1431 1431 if (parentStyle) 1432 parentStyle->setChildrenAffectedBy ForwardPositionalRules();1432 parentStyle->setChildrenAffectedByDirectAdjacentRules(); 1433 1433 } 1434 1434 Node* n = e->previousSibling(); -
trunk/WebCore/dom/Element.cpp
r30633 r30667 707 707 RenderStyle* currentStyle = renderStyle(); 708 708 bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false; 709 bool hasPositionalChildren = currentStyle && (currentStyle->childrenAffectedByFirstChildRules() || currentStyle->childrenAffectedByLastChildRules() || 710 currentStyle->childrenAffectedByForwardPositionalRules() || currentStyle->childrenAffectedByBackwardPositionalRules()); 709 bool hasPositionalRules = changed() && currentStyle && currentStyle->childrenAffectedByPositionalRules(); 711 710 712 711 #if ENABLE(SVG) … … 751 750 if (currentStyle->childrenAffectedByLastChildRules()) 752 751 newStyle->setChildrenAffectedByLastChildRules(); 752 if (currentStyle->childrenAffectedByDirectAdjacentRules()) 753 newStyle->setChildrenAffectedByDirectAdjacentRules(); 753 754 } 754 755 … … 769 770 770 771 if (change != Force) { 771 if ((document()->usesDescendantRules() || hasPositional Children) && styleChangeType() == FullStyleChange)772 if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() == FullStyleChange) 772 773 change = Force; 773 774 else … … 801 802 } 802 803 803 static void checkFirstChildRules(Element* e, RenderStyle* style) 804 { 805 if (style->childrenAffectedByFirstChildRules()) { 806 // Check our first two children. They need to be true and false respectively. 807 bool checkingFirstChild = true; 808 for (Node* n = e->firstChild(); n; n = n->nextSibling()) { 809 if (n->isElementNode()) { 810 if (checkingFirstChild) { 811 if (n->attached() && n->renderStyle() && !n->renderStyle()->firstChildState()) 812 n->setChanged(); 813 checkingFirstChild = false; 814 } else { 815 if (n->attached() && n->renderStyle() && n->renderStyle()->firstChildState()) 816 n->setChanged(); 817 break; 818 } 819 } 820 } 821 } 822 } 823 824 static void checkLastChildRules(Element* e, RenderStyle* style) 825 { 826 if (style->childrenAffectedByLastChildRules()) { 827 // Check our last two children. They need to be true and false respectively. 828 bool checkingLastChild = true; 829 for (Node* n = e->lastChild(); n; n = n->previousSibling()) { 830 if (n->isElementNode()) { 831 if (checkingLastChild) { 832 if (n->attached() && n->renderStyle() && !n->renderStyle()->lastChildState()) 833 n->setChanged(); 834 checkingLastChild = false; 835 } else { 836 if (n->attached() && n->renderStyle() && n->renderStyle()->lastChildState()) 837 n->setChanged(); 838 break; 839 } 840 } 841 } 842 } 843 } 844 845 static bool checkEmptyRules(Element* e, RenderStyle* style) 846 { 847 return style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes()); 848 } 849 850 static void checkStyleRules(Element* e, RenderStyle* style, bool changedByParser) 851 { 852 if (e->changed() || !style) 853 return; 854 855 if (style->childrenAffectedByBackwardPositionalRules() || 856 (!changedByParser && style->childrenAffectedByForwardPositionalRules()) || 857 checkEmptyRules(e, style)) { 804 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback, 805 Node* beforeChange, Node* afterChange, int childCountDelta) 806 { 807 if (!style || (e->changed() && style->childrenAffectedByPositionalRules())) 808 return; 809 810 // :first-child. In the parser callback case, we don't have to check anything, since we were right the first time. 811 // In the DOM case, we only need to do something if |afterChange| is not 0. 812 // |afterChange| is 0 in the parser case, so it works out that we'll skip this block. 813 if (style->childrenAffectedByFirstChildRules() && afterChange) { 814 // Find our new first child. 815 Node* newFirstChild = 0; 816 for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {}; 817 818 // Find the first element node following |afterChange| 819 Node* firstElementAfterInsertion = 0; 820 for (firstElementAfterInsertion = afterChange; 821 firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode(); 822 firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {}; 823 824 // This is the insert/append case. 825 if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() && 826 firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState()) 827 firstElementAfterInsertion->setChanged(); 828 829 // We also have to handle node removal. 830 if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && newFirstChild->renderStyle() && !newFirstChild->renderStyle()->firstChildState()) 831 newFirstChild->setChanged(); 832 } 833 834 // :last-child. In the parser callback case, we don't have to check anything, since we were right the first time. 835 // In the DOM case, we only need to do something if |afterChange| is not 0. 836 if (style->childrenAffectedByLastChildRules() && beforeChange) { 837 // Find our new last child. 838 Node* newLastChild = 0; 839 for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {}; 840 841 // Find the last element node going backwards from |beforeChange| 842 Node* lastElementBeforeInsertion = 0; 843 for (lastElementBeforeInsertion = beforeChange; 844 lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode(); 845 lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {}; 846 847 if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() && 848 lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState()) 849 lastElementBeforeInsertion->setChanged(); 850 851 // We also have to handle node removal. The parser callback case is similar to node removal as well in that we need to change the last child 852 // to match now. 853 if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState()) 854 newLastChild->setChanged(); 855 } 856 857 // The + selector. We need to invalidate the first element following the insertion point. It is the only possible element 858 // that could be affected by this DOM change. 859 if (style->childrenAffectedByDirectAdjacentRules() && afterChange) { 860 Node* firstElementAfterInsertion = 0; 861 for (firstElementAfterInsertion = afterChange; 862 firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode(); 863 firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {}; 864 if (firstElementAfterInsertion && firstElementAfterInsertion->attached()) 865 firstElementAfterInsertion->setChanged(); 866 } 867 868 // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type. 869 // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type. 870 // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the 871 // backward case. 872 // |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to. 873 // For performance reasons we just mark the parent node as changed, since we don't want to make childrenChanged O(n^2) by crawling all our kids 874 // here. recalcStyle will then force a walk of the children when it sees that this has happened. 875 if ((style->childrenAffectedByForwardPositionalRules() && afterChange) || 876 (style->childrenAffectedByBackwardPositionalRules() && beforeChange)) 858 877 e->setChanged(); 859 return; 860 } 861 862 checkFirstChildRules(e, style); 863 checkLastChildRules(e, style); 878 879 // :empty selector. 880 if (style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes())) 881 e->setChanged(); 864 882 } 865 883 … … 868 886 ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 869 887 if (!changedByParser) 870 check StyleRules(this, renderStyle(), false);888 checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta); 871 889 } 872 890 … … 875 893 ContainerNode::finishParsingChildren(); 876 894 m_parsingChildrenFinished = true; 877 check StyleRules(this, renderStyle(), true);895 checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0); 878 896 } 879 897 -
trunk/WebCore/rendering/RenderStyle.cpp
r30573 r30667 951 951 , m_childrenAffectedByFirstChildRules(false) 952 952 , m_childrenAffectedByLastChildRules(false) 953 , m_childrenAffectedByDirectAdjacentRules(false) 953 954 , m_childrenAffectedByForwardPositionalRules(false) 954 955 , m_childrenAffectedByBackwardPositionalRules(false) … … 973 974 , m_childrenAffectedByFirstChildRules(false) 974 975 , m_childrenAffectedByLastChildRules(false) 976 , m_childrenAffectedByDirectAdjacentRules(false) 975 977 , m_childrenAffectedByForwardPositionalRules(false) 976 978 , m_childrenAffectedByBackwardPositionalRules(false) … … 1017 1019 , m_childrenAffectedByFirstChildRules(false) 1018 1020 , m_childrenAffectedByLastChildRules(false) 1021 , m_childrenAffectedByDirectAdjacentRules(false) 1019 1022 , m_childrenAffectedByForwardPositionalRules(false) 1020 1023 , m_childrenAffectedByBackwardPositionalRules(false) -
trunk/WebCore/rendering/RenderStyle.h
r30577 r30667 1515 1515 bool m_childrenAffectedByFirstChildRules : 1; 1516 1516 bool m_childrenAffectedByLastChildRules : 1; 1517 bool m_childrenAffectedByDirectAdjacentRules : 1; 1517 1518 bool m_childrenAffectedByForwardPositionalRules : 1; 1518 1519 bool m_childrenAffectedByBackwardPositionalRules : 1; 1519 1520 bool m_firstChildState : 1; 1520 1521 bool m_lastChildState : 1; 1521 unsigned m_childIndex : 1 9; // Plenty of bits to cache an index.1522 unsigned m_childIndex : 18; // Plenty of bits to cache an index. 1522 1523 1523 1524 int m_ref; … … 2166 2167 bool emptyState() const { return m_emptyState; } 2167 2168 void setEmptyState(bool b) { m_affectedByEmpty = true; m_unique = true; m_emptyState = b; } 2169 bool childrenAffectedByPositionalRules() const { return childrenAffectedByForwardPositionalRules() || childrenAffectedByBackwardPositionalRules(); } 2168 2170 bool childrenAffectedByFirstChildRules() const { return m_childrenAffectedByFirstChildRules; } 2169 2171 void setChildrenAffectedByFirstChildRules() { m_childrenAffectedByFirstChildRules = true; } 2170 2172 bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; } 2171 2173 void setChildrenAffectedByLastChildRules() { m_childrenAffectedByLastChildRules = true; } 2174 bool childrenAffectedByDirectAdjacentRules() const { return m_childrenAffectedByDirectAdjacentRules; } 2175 void setChildrenAffectedByDirectAdjacentRules() { m_childrenAffectedByDirectAdjacentRules = true; } 2172 2176 bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; } 2173 2177 void setChildrenAffectedByForwardPositionalRules() { m_childrenAffectedByForwardPositionalRules = true; }
Note: See TracChangeset
for help on using the changeset viewer.