Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: Source/core/css/resolver/StyleResolver.cpp

Issue 15871005: Avoid N^2 walk placing renderers when building the render tree (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Again, updating to ToT. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/)
9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 } 560 }
561 561
562 // Now check SMIL animation override style. 562 // Now check SMIL animation override style.
563 if (includeSMILProperties && matchAuthorAndUserStyles && m_state.styledEleme nt() && m_state.styledElement()->isSVGElement()) 563 if (includeSMILProperties && matchAuthorAndUserStyles && m_state.styledEleme nt() && m_state.styledElement()->isSVGElement())
564 collector.addElementStyleProperties(toSVGElement(m_state.styledElement() )->animatedSMILStyleProperties(), false /* isCacheable */); 564 collector.addElementStyleProperties(toSVGElement(m_state.styledElement() )->animatedSMILStyleProperties(), false /* isCacheable */);
565 565
566 if (m_state.styledElement() && m_state.styledElement()->hasActiveAnimations( )) 566 if (m_state.styledElement() && m_state.styledElement()->hasActiveAnimations( ))
567 collector.matchedResult().isCacheable = false; 567 collector.matchedResult().isCacheable = false;
568 } 568 }
569 569
570 inline void StyleResolver::initElement(Element* e) 570 inline void StyleResolver::initElement(Element* e, int childIndex)
571 { 571 {
572 if (m_state.element() != e) { 572 if (m_state.element() != e) {
573 m_state.initElement(e); 573 m_state.initElement(e, childIndex);
574 if (e && e == e->document()->documentElement()) { 574 if (e && e == e->document()->documentElement()) {
575 e->document()->setDirectionSetOnDocumentElement(false); 575 e->document()->setDirectionSetOnDocumentElement(false);
576 e->document()->setWritingModeSetOnDocumentElement(false); 576 e->document()->setWritingModeSetOnDocumentElement(false);
577 } 577 }
578 } 578 }
579 } 579 }
580 580
581 static const unsigned cStyleSearchThreshold = 10; 581 static const unsigned cStyleSearchThreshold = 10;
582 static const unsigned cStyleSearchLevelThreshold = 10; 582 static const unsigned cStyleSearchLevelThreshold = 10;
583 583
(...skipping 16 matching lines...) Expand all
600 if (p->inlineStyle()) 600 if (p->inlineStyle())
601 return 0; 601 return 0;
602 if (p->isSVGElement() && toSVGElement(p)->animatedSMILStyleProperties()) 602 if (p->isSVGElement() && toSVGElement(p)->animatedSMILStyleProperties())
603 return 0; 603 return 0;
604 if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().i mpl())) 604 if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().i mpl()))
605 return 0; 605 return 0;
606 606
607 RenderStyle* parentStyle = p->renderStyle(); 607 RenderStyle* parentStyle = p->renderStyle();
608 unsigned subcount = 0; 608 unsigned subcount = 0;
609 Node* thisCousin = p; 609 Node* thisCousin = p;
610 Node* currentNode = p->previousSibling(); 610 Node* currentNode = p->nextSibling();
611 611
612 // Reserve the tries for this level. This effectively makes sure that the al gorithm 612 // Reserve the tries for this level. This effectively makes sure that the al gorithm
613 // will never go deeper than cStyleSearchLevelThreshold levels into recursio n. 613 // will never go deeper than cStyleSearchLevelThreshold levels into recursio n.
614 visitedNodeCount += cStyleSearchThreshold; 614 visitedNodeCount += cStyleSearchThreshold;
615 static int iterationCount = 0;
ojan 2013/06/03 23:03:29 Leftover debugging code?
615 while (thisCousin) { 616 while (thisCousin) {
616 while (currentNode) { 617 while (currentNode) {
617 ++subcount; 618 ++subcount;
618 if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderSt yle() == parentStyle && currentNode->lastChild() 619 if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderSt yle() == parentStyle && currentNode->lastChild()
619 && currentNode->isElementNode() && !parentElementPreventsSharing (toElement(currentNode)) 620 && currentNode->isElementNode() && !parentElementPreventsSharing (toElement(currentNode))
620 && !toElement(currentNode)->shadow() 621 && !toElement(currentNode)->shadow()
621 ) { 622 ) {
622 // Adjust for unused reserved tries. 623 // Adjust for unused reserved tries.
623 visitedNodeCount -= cStyleSearchThreshold - subcount; 624 visitedNodeCount -= cStyleSearchThreshold - subcount;
624 return currentNode->lastChild(); 625 return currentNode->lastChild();
625 } 626 }
626 if (subcount >= cStyleSearchThreshold) 627 if (subcount >= cStyleSearchThreshold)
627 return 0; 628 return 0;
628 currentNode = currentNode->previousSibling(); 629 currentNode = currentNode->nextSibling();
629 } 630 }
630 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC ount); 631 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC ount);
631 thisCousin = currentNode; 632 thisCousin = currentNode;
632 } 633 }
633 634
634 return 0; 635 return 0;
635 } 636 }
636 637
637 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet) 638 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
638 { 639 {
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWe bVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNo de()) 815 if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWe bVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNo de())
815 return false; 816 return false;
816 817
817 if (element == element->document()->webkitCurrentFullScreenElement() || stat e.element() == state.document()->webkitCurrentFullScreenElement()) 818 if (element == element->document()->webkitCurrentFullScreenElement() || stat e.element() == state.document()->webkitCurrentFullScreenElement())
818 return false; 819 return false;
819 return true; 820 return true;
820 } 821 }
821 822
822 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsi gned& count) const 823 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsi gned& count) const
823 { 824 {
824 for (; node; node = node->previousSibling()) { 825 for (; node; node = node->nextSibling()) {
825 if (!node->isStyledElement()) 826 if (!node->isStyledElement())
826 continue; 827 continue;
827 if (canShareStyleWithElement(static_cast<StyledElement*>(node))) 828 if (canShareStyleWithElement(static_cast<StyledElement*>(node)))
828 break; 829 break;
829 if (count++ == cStyleSearchThreshold) 830 if (count++ == cStyleSearchThreshold)
830 return 0; 831 return 0;
831 } 832 }
832 return static_cast<StyledElement*>(node); 833 return static_cast<StyledElement*>(node);
833 } 834 }
834 835
(...skipping 19 matching lines...) Expand all
854 return 0; 855 return 0;
855 if (elementHasDirectionAuto(state.element())) 856 if (elementHasDirectionAuto(state.element()))
856 return 0; 857 return 0;
857 if (state.element()->hasActiveAnimations()) 858 if (state.element()->hasActiveAnimations())
858 return 0; 859 return 0;
859 860
860 // Cache whether state.element is affected by any known class selectors. 861 // Cache whether state.element is affected by any known class selectors.
861 // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver. 862 // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver.
862 state.setElementAffectedByClassRules(state.element() && state.element()->has Class() && classNamesAffectedByRules(state.element()->classNames())); 863 state.setElementAffectedByClassRules(state.element() && state.element()->has Class() && classNamesAffectedByRules(state.element()->classNames()));
863 864
864 // Check previous siblings and their cousins. 865 // Check next siblings and their cousins.
865 unsigned count = 0; 866 unsigned count = 0;
866 unsigned visitedNodeCount = 0; 867 unsigned visitedNodeCount = 0;
867 StyledElement* shareElement = 0; 868 StyledElement* shareElement = 0;
868 Node* cousinList = state.styledElement()->previousSibling(); 869 Node* cousinList = state.styledElement()->nextSibling();
869 while (cousinList) { 870 while (cousinList) {
870 shareElement = findSiblingForStyleSharing(cousinList, count); 871 shareElement = findSiblingForStyleSharing(cousinList, count);
871 if (shareElement) 872 if (shareElement)
872 break; 873 break;
873 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo unt); 874 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo unt);
874 } 875 }
875 876
876 // If we have exhausted all our budget or our cousins. 877 // If we have exhausted all our budget or our cousins.
877 if (!shareElement) 878 if (!shareElement)
878 return 0; 879 return 0;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 } 1074 }
1074 1075
1075 static inline bool isAtShadowBoundary(const Element* element) 1076 static inline bool isAtShadowBoundary(const Element* element)
1076 { 1077 {
1077 if (!element) 1078 if (!element)
1078 return false; 1079 return false;
1079 ContainerNode* parentNode = element->parentNode(); 1080 ContainerNode* parentNode = element->parentNode();
1080 return parentNode && parentNode->isShadowRoot(); 1081 return parentNode && parentNode->isShadowRoot();
1081 } 1082 }
1082 1083
1083 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS tyle* defaultParent, 1084 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS tyle* defaultParent, StyleSharingBehavior sharingBehavior,
1084 StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling) 1085 RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling, int c hildIndex)
1085 { 1086 {
1086 // Once an element has a renderer, we don't try to destroy it, since otherwi se the renderer 1087 // Once an element has a renderer, we don't try to destroy it, since otherwi se the renderer
1087 // will vanish if a style recalc happens during loading. 1088 // will vanish if a style recalc happens during loading.
1088 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStyles heetsLoaded() && !element->renderer()) { 1089 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStyles heetsLoaded() && !element->renderer()) {
1089 if (!s_styleNotYetAvailable) { 1090 if (!s_styleNotYetAvailable) {
1090 s_styleNotYetAvailable = RenderStyle::create().leakRef(); 1091 s_styleNotYetAvailable = RenderStyle::create().leakRef();
1091 s_styleNotYetAvailable->setDisplay(NONE); 1092 s_styleNotYetAvailable->setDisplay(NONE);
1092 s_styleNotYetAvailable->font().update(m_fontSelector); 1093 s_styleNotYetAvailable->font().update(m_fontSelector);
1093 } 1094 }
1094 element->document()->setHasNodesWithPlaceholderStyle(); 1095 element->document()->setHasNodesWithPlaceholderStyle();
1095 return s_styleNotYetAvailable; 1096 return s_styleNotYetAvailable;
1096 } 1097 }
1097 1098
1098 StyleResolverState& state = m_state; 1099 StyleResolverState& state = m_state;
1099 initElement(element); 1100 initElement(element, childIndex);
1100 state.initForStyleResolve(document(), element, defaultParent, regionForStyli ng); 1101 state.initForStyleResolve(document(), element, defaultParent, regionForStyli ng);
1101 if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoi nt()) { 1102 if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoi nt()) {
1102 RenderStyle* sharedStyle = locateSharedStyle(); 1103 RenderStyle* sharedStyle = locateSharedStyle();
1103 if (sharedStyle) { 1104 if (sharedStyle) {
1104 state.clear(); 1105 state.clear();
1105 return sharedStyle; 1106 return sharedStyle;
1106 } 1107 }
1107 } 1108 }
1108 1109
1109 if (state.parentStyle()) { 1110 if (state.parentStyle()) {
(...skipping 2618 matching lines...) Expand 10 before | Expand all | Expand 10 after
3728 info.addMember(m_state, "state"); 3729 info.addMember(m_state, "state");
3729 3730
3730 // FIXME: move this to a place where it would be called only once? 3731 // FIXME: move this to a place where it would be called only once?
3731 info.addMember(CSSDefaultStyleSheets::defaultStyle, "defaultStyle"); 3732 info.addMember(CSSDefaultStyleSheets::defaultStyle, "defaultStyle");
3732 info.addMember(CSSDefaultStyleSheets::defaultQuirksStyle, "defaultQuirksStyl e"); 3733 info.addMember(CSSDefaultStyleSheets::defaultQuirksStyle, "defaultQuirksStyl e");
3733 info.addMember(CSSDefaultStyleSheets::defaultPrintStyle, "defaultPrintStyle" ); 3734 info.addMember(CSSDefaultStyleSheets::defaultPrintStyle, "defaultPrintStyle" );
3734 info.addMember(CSSDefaultStyleSheets::defaultViewSourceStyle, "defaultViewSo urceStyle"); 3735 info.addMember(CSSDefaultStyleSheets::defaultViewSourceStyle, "defaultViewSo urceStyle");
3735 } 3736 }
3736 3737
3737 } // namespace WebCore 3738 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698