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

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: Merging 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 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 } 559 }
560 560
561 // Now check SMIL animation override style. 561 // Now check SMIL animation override style.
562 if (includeSMILProperties && matchAuthorAndUserStyles && m_state.styledEleme nt() && m_state.styledElement()->isSVGElement()) 562 if (includeSMILProperties && matchAuthorAndUserStyles && m_state.styledEleme nt() && m_state.styledElement()->isSVGElement())
563 collector.addElementStyleProperties(toSVGElement(m_state.styledElement() )->animatedSMILStyleProperties(), false /* isCacheable */); 563 collector.addElementStyleProperties(toSVGElement(m_state.styledElement() )->animatedSMILStyleProperties(), false /* isCacheable */);
564 564
565 if (m_state.styledElement() && m_state.styledElement()->hasActiveAnimations( )) 565 if (m_state.styledElement() && m_state.styledElement()->hasActiveAnimations( ))
566 collector.matchedResult().isCacheable = false; 566 collector.matchedResult().isCacheable = false;
567 } 567 }
568 568
569 inline void StyleResolver::initElement(Element* e) 569 inline void StyleResolver::initElement(Element* e, int childIndex)
570 { 570 {
571 if (m_state.element() != e) { 571 if (m_state.element() != e) {
572 m_state.initElement(e); 572 m_state.initElement(e, childIndex);
573 if (e && e == e->document()->documentElement()) { 573 if (e && e == e->document()->documentElement()) {
574 e->document()->setDirectionSetOnDocumentElement(false); 574 e->document()->setDirectionSetOnDocumentElement(false);
575 e->document()->setWritingModeSetOnDocumentElement(false); 575 e->document()->setWritingModeSetOnDocumentElement(false);
576 } 576 }
577 } 577 }
578 } 578 }
579 579
580 static const unsigned cStyleSearchThreshold = 10; 580 static const unsigned cStyleSearchThreshold = 10;
581 static const unsigned cStyleSearchLevelThreshold = 10; 581 static const unsigned cStyleSearchLevelThreshold = 10;
582 582
(...skipping 16 matching lines...) Expand all
599 if (p->inlineStyle()) 599 if (p->inlineStyle())
600 return 0; 600 return 0;
601 if (p->isSVGElement() && toSVGElement(p)->animatedSMILStyleProperties()) 601 if (p->isSVGElement() && toSVGElement(p)->animatedSMILStyleProperties())
602 return 0; 602 return 0;
603 if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().i mpl())) 603 if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().i mpl()))
604 return 0; 604 return 0;
605 605
606 RenderStyle* parentStyle = p->renderStyle(); 606 RenderStyle* parentStyle = p->renderStyle();
607 unsigned subcount = 0; 607 unsigned subcount = 0;
608 Node* thisCousin = p; 608 Node* thisCousin = p;
609 Node* currentNode = p->previousSibling(); 609 Node* currentNode = p->nextSibling();
610 610
611 // Reserve the tries for this level. This effectively makes sure that the al gorithm 611 // Reserve the tries for this level. This effectively makes sure that the al gorithm
612 // will never go deeper than cStyleSearchLevelThreshold levels into recursio n. 612 // will never go deeper than cStyleSearchLevelThreshold levels into recursio n.
613 visitedNodeCount += cStyleSearchThreshold; 613 visitedNodeCount += cStyleSearchThreshold;
614 while (thisCousin) { 614 while (thisCousin) {
615 while (currentNode) { 615 while (currentNode) {
616 ++subcount; 616 ++subcount;
617 if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderSt yle() == parentStyle && currentNode->lastChild() 617 if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderSt yle() == parentStyle && currentNode->lastChild()
618 && currentNode->isElementNode() && !parentElementPreventsSharing (toElement(currentNode)) 618 && currentNode->isElementNode() && !parentElementPreventsSharing (toElement(currentNode))
619 && !toElement(currentNode)->shadow() 619 && !toElement(currentNode)->shadow()
620 ) { 620 ) {
621 // Adjust for unused reserved tries. 621 // Adjust for unused reserved tries.
622 visitedNodeCount -= cStyleSearchThreshold - subcount; 622 visitedNodeCount -= cStyleSearchThreshold - subcount;
623 return currentNode->lastChild(); 623 return currentNode->lastChild();
624 } 624 }
625 if (subcount >= cStyleSearchThreshold) 625 if (subcount >= cStyleSearchThreshold)
626 return 0; 626 return 0;
627 currentNode = currentNode->previousSibling(); 627 currentNode = currentNode->nextSibling();
628 } 628 }
629 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC ount); 629 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC ount);
630 thisCousin = currentNode; 630 thisCousin = currentNode;
631 } 631 }
632 632
633 return 0; 633 return 0;
634 } 634 }
635 635
636 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet) 636 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
637 { 637 {
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWe bVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNo de()) 813 if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWe bVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNo de())
814 return false; 814 return false;
815 815
816 if (element == element->document()->webkitCurrentFullScreenElement() || stat e.element() == state.document()->webkitCurrentFullScreenElement()) 816 if (element == element->document()->webkitCurrentFullScreenElement() || stat e.element() == state.document()->webkitCurrentFullScreenElement())
817 return false; 817 return false;
818 return true; 818 return true;
819 } 819 }
820 820
821 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsi gned& count) const 821 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsi gned& count) const
822 { 822 {
823 for (; node; node = node->previousSibling()) { 823 for (; node; node = node->nextSibling()) {
824 if (!node->isStyledElement()) 824 if (!node->isStyledElement())
825 continue; 825 continue;
826 if (canShareStyleWithElement(static_cast<StyledElement*>(node))) 826 if (canShareStyleWithElement(static_cast<StyledElement*>(node)))
827 break; 827 break;
828 if (count++ == cStyleSearchThreshold) 828 if (count++ == cStyleSearchThreshold)
829 return 0; 829 return 0;
830 } 830 }
831 return static_cast<StyledElement*>(node); 831 return static_cast<StyledElement*>(node);
832 } 832 }
833 833
(...skipping 24 matching lines...) Expand all
858 // When a dialog is first shown, its style is mutated to center it in the 858 // When a dialog is first shown, its style is mutated to center it in the
859 // viewport. So the styles can't be shared since the viewport position and 859 // viewport. So the styles can't be shared since the viewport position and
860 // size may be different each time a dialog is opened. 860 // size may be different each time a dialog is opened.
861 if (state.element()->hasTagName(dialogTag)) 861 if (state.element()->hasTagName(dialogTag))
862 return 0; 862 return 0;
863 863
864 // Cache whether state.element is affected by any known class selectors. 864 // Cache whether state.element is affected by any known class selectors.
865 // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver. 865 // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver.
866 state.setElementAffectedByClassRules(state.element() && state.element()->has Class() && classNamesAffectedByRules(state.element()->classNames())); 866 state.setElementAffectedByClassRules(state.element() && state.element()->has Class() && classNamesAffectedByRules(state.element()->classNames()));
867 867
868 // Check previous siblings and their cousins. 868 // Check next siblings and their cousins.
869 unsigned count = 0; 869 unsigned count = 0;
870 unsigned visitedNodeCount = 0; 870 unsigned visitedNodeCount = 0;
871 StyledElement* shareElement = 0; 871 StyledElement* shareElement = 0;
872 Node* cousinList = state.styledElement()->previousSibling(); 872 Node* cousinList = state.styledElement()->nextSibling();
873 while (cousinList) { 873 while (cousinList) {
874 shareElement = findSiblingForStyleSharing(cousinList, count); 874 shareElement = findSiblingForStyleSharing(cousinList, count);
875 if (shareElement) 875 if (shareElement)
876 break; 876 break;
877 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo unt); 877 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo unt);
878 } 878 }
879 879
880 // If we have exhausted all our budget or our cousins. 880 // If we have exhausted all our budget or our cousins.
881 if (!shareElement) 881 if (!shareElement)
882 return 0; 882 return 0;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 } 1077 }
1078 1078
1079 static inline bool isAtShadowBoundary(const Element* element) 1079 static inline bool isAtShadowBoundary(const Element* element)
1080 { 1080 {
1081 if (!element) 1081 if (!element)
1082 return false; 1082 return false;
1083 ContainerNode* parentNode = element->parentNode(); 1083 ContainerNode* parentNode = element->parentNode();
1084 return parentNode && parentNode->isShadowRoot(); 1084 return parentNode && parentNode->isShadowRoot();
1085 } 1085 }
1086 1086
1087 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS tyle* defaultParent, 1087 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS tyle* defaultParent, StyleSharingBehavior sharingBehavior,
1088 StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling) 1088 RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling, int c hildIndex)
1089 { 1089 {
1090 // Once an element has a renderer, we don't try to destroy it, since otherwi se the renderer 1090 // Once an element has a renderer, we don't try to destroy it, since otherwi se the renderer
1091 // will vanish if a style recalc happens during loading. 1091 // will vanish if a style recalc happens during loading.
1092 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStyles heetsLoaded() && !element->renderer()) { 1092 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStyles heetsLoaded() && !element->renderer()) {
1093 if (!s_styleNotYetAvailable) { 1093 if (!s_styleNotYetAvailable) {
1094 s_styleNotYetAvailable = RenderStyle::create().leakRef(); 1094 s_styleNotYetAvailable = RenderStyle::create().leakRef();
1095 s_styleNotYetAvailable->setDisplay(NONE); 1095 s_styleNotYetAvailable->setDisplay(NONE);
1096 s_styleNotYetAvailable->font().update(m_fontSelector); 1096 s_styleNotYetAvailable->font().update(m_fontSelector);
1097 } 1097 }
1098 element->document()->setHasNodesWithPlaceholderStyle(); 1098 element->document()->setHasNodesWithPlaceholderStyle();
1099 return s_styleNotYetAvailable; 1099 return s_styleNotYetAvailable;
1100 } 1100 }
1101 1101
1102 StyleResolverState& state = m_state; 1102 StyleResolverState& state = m_state;
1103 initElement(element); 1103 initElement(element, childIndex);
1104 state.initForStyleResolve(document(), element, defaultParent, regionForStyli ng); 1104 state.initForStyleResolve(document(), element, defaultParent, regionForStyli ng);
1105 if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoi nt()) { 1105 if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoi nt()) {
1106 RenderStyle* sharedStyle = locateSharedStyle(); 1106 RenderStyle* sharedStyle = locateSharedStyle();
1107 if (sharedStyle) { 1107 if (sharedStyle) {
1108 state.clear(); 1108 state.clear();
1109 return sharedStyle; 1109 return sharedStyle;
1110 } 1110 }
1111 } 1111 }
1112 1112
1113 if (state.parentStyle()) { 1113 if (state.parentStyle()) {
(...skipping 2625 matching lines...) Expand 10 before | Expand all | Expand 10 after
3739 info.addMember(m_state, "state"); 3739 info.addMember(m_state, "state");
3740 3740
3741 // FIXME: move this to a place where it would be called only once? 3741 // FIXME: move this to a place where it would be called only once?
3742 info.addMember(CSSDefaultStyleSheets::defaultStyle, "defaultStyle"); 3742 info.addMember(CSSDefaultStyleSheets::defaultStyle, "defaultStyle");
3743 info.addMember(CSSDefaultStyleSheets::defaultQuirksStyle, "defaultQuirksStyl e"); 3743 info.addMember(CSSDefaultStyleSheets::defaultQuirksStyle, "defaultQuirksStyl e");
3744 info.addMember(CSSDefaultStyleSheets::defaultPrintStyle, "defaultPrintStyle" ); 3744 info.addMember(CSSDefaultStyleSheets::defaultPrintStyle, "defaultPrintStyle" );
3745 info.addMember(CSSDefaultStyleSheets::defaultViewSourceStyle, "defaultViewSo urceStyle"); 3745 info.addMember(CSSDefaultStyleSheets::defaultViewSourceStyle, "defaultViewSo urceStyle");
3746 } 3746 }
3747 3747
3748 } // namespace WebCore 3748 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698