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

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

Issue 18276003: Avoid N^2 walk placing renderers when building the render tree (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Removing extra parens (whoops) Created 7 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/css/resolver/StyleResolver.h ('k') | Source/core/css/resolver/StyleResolverState.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 502 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 if (parent->inlineStyle()) 513 if (parent->inlineStyle())
514 return 0; 514 return 0;
515 if (parent->isSVGElement() && toSVGElement(parent)->animatedSMILStylePropert ies()) 515 if (parent->isSVGElement() && toSVGElement(parent)->animatedSMILStylePropert ies())
516 return 0; 516 return 0;
517 if (parent->hasID() && m_features.idsInRules.contains(parent->idForStyleReso lution().impl())) 517 if (parent->hasID() && m_features.idsInRules.contains(parent->idForStyleReso lution().impl()))
518 return 0; 518 return 0;
519 519
520 RenderStyle* parentStyle = parent->renderStyle(); 520 RenderStyle* parentStyle = parent->renderStyle();
521 unsigned subcount = 0; 521 unsigned subcount = 0;
522 Node* thisCousin = parent; 522 Node* thisCousin = parent;
523 Node* currentNode = parent->previousSibling(); 523 Node* currentNode = parent->nextSibling();
524 524
525 // Reserve the tries for this level. This effectively makes sure that the al gorithm 525 // Reserve the tries for this level. This effectively makes sure that the al gorithm
526 // will never go deeper than cStyleSearchLevelThreshold levels into recursio n. 526 // will never go deeper than cStyleSearchLevelThreshold levels into recursio n.
527 visitedNodeCount += cStyleSearchThreshold; 527 visitedNodeCount += cStyleSearchThreshold;
528 while (thisCousin) { 528 while (thisCousin) {
529 while (currentNode) { 529 while (currentNode) {
530 ++subcount; 530 ++subcount;
531 if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderSt yle() == parentStyle && currentNode->lastChild() 531 if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderSt yle() == parentStyle && currentNode->lastChild()
532 && currentNode->isElementNode() && !parentElementPreventsSharing (toElement(currentNode)) 532 && currentNode->isElementNode() && !parentElementPreventsSharing (toElement(currentNode))
533 && !toElement(currentNode)->shadow() 533 && !toElement(currentNode)->shadow()
534 ) { 534 ) {
535 // Adjust for unused reserved tries. 535 // Adjust for unused reserved tries.
536 visitedNodeCount -= cStyleSearchThreshold - subcount; 536 visitedNodeCount -= cStyleSearchThreshold - subcount;
537 return currentNode->lastChild(); 537 return currentNode->lastChild();
538 } 538 }
539 if (subcount >= cStyleSearchThreshold) 539 if (subcount >= cStyleSearchThreshold)
540 return 0; 540 return 0;
541 currentNode = currentNode->previousSibling(); 541 currentNode = currentNode->nextSibling();
542 } 542 }
543 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC ount); 543 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC ount);
544 thisCousin = currentNode; 544 thisCousin = currentNode;
545 } 545 }
546 546
547 return 0; 547 return 0;
548 } 548 }
549 549
550 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet) 550 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
551 { 551 {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 if (FullscreenController* fullscreen = FullscreenController::fromIfExists(st ate.document())) { 730 if (FullscreenController* fullscreen = FullscreenController::fromIfExists(st ate.document())) {
731 if (element == fullscreen->webkitCurrentFullScreenElement() || state.ele ment() == fullscreen->webkitCurrentFullScreenElement()) 731 if (element == fullscreen->webkitCurrentFullScreenElement() || state.ele ment() == fullscreen->webkitCurrentFullScreenElement())
732 return false; 732 return false;
733 } 733 }
734 734
735 return true; 735 return true;
736 } 736 }
737 737
738 inline Element* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const 738 inline Element* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const
739 { 739 {
740 for (; node; node = node->previousSibling()) { 740 for (; node; node = node->nextSibling()) {
741 if (!node->isStyledElement()) 741 if (!node->isStyledElement())
742 continue; 742 continue;
743 if (canShareStyleWithElement(toElement(node))) 743 if (canShareStyleWithElement(toElement(node)))
744 break; 744 break;
745 if (count++ == cStyleSearchThreshold) 745 if (count++ == cStyleSearchThreshold)
746 return 0; 746 return 0;
747 } 747 }
748 return toElement(node); 748 return toElement(node);
749 } 749 }
750 750
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 // When a dialog is first shown, its style is mutated to center it in the 784 // When a dialog is first shown, its style is mutated to center it in the
785 // viewport. So the styles can't be shared since the viewport position and 785 // viewport. So the styles can't be shared since the viewport position and
786 // size may be different each time a dialog is opened. 786 // size may be different each time a dialog is opened.
787 if (state.element()->hasTagName(dialogTag)) 787 if (state.element()->hasTagName(dialogTag))
788 return 0; 788 return 0;
789 789
790 // Cache whether state.element is affected by any known class selectors. 790 // Cache whether state.element is affected by any known class selectors.
791 // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver. 791 // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver.
792 state.setElementAffectedByClassRules(state.element() && state.element()->has Class() && classNamesAffectedByRules(state.element()->classNames())); 792 state.setElementAffectedByClassRules(state.element() && state.element()->has Class() && classNamesAffectedByRules(state.element()->classNames()));
793 793
794 // Check previous siblings and their cousins. 794 // Check next siblings and their cousins.
795 unsigned count = 0; 795 unsigned count = 0;
796 unsigned visitedNodeCount = 0; 796 unsigned visitedNodeCount = 0;
797 Element* shareElement = 0; 797 Element* shareElement = 0;
798 Node* cousinList = state.styledElement()->previousSibling(); 798 Node* cousinList = state.styledElement()->nextSibling();
799 while (cousinList) { 799 while (cousinList) {
800 shareElement = findSiblingForStyleSharing(cousinList, count); 800 shareElement = findSiblingForStyleSharing(cousinList, count);
801 if (shareElement) 801 if (shareElement)
802 break; 802 break;
803 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo unt); 803 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo unt);
804 } 804 }
805 805
806 // If we have exhausted all our budget or our cousins. 806 // If we have exhausted all our budget or our cousins.
807 if (!shareElement) 807 if (!shareElement)
808 return 0; 808 return 0;
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 } 990 }
991 991
992 static inline bool isAtShadowBoundary(const Element* element) 992 static inline bool isAtShadowBoundary(const Element* element)
993 { 993 {
994 if (!element) 994 if (!element)
995 return false; 995 return false;
996 ContainerNode* parentNode = element->parentNode(); 996 ContainerNode* parentNode = element->parentNode();
997 return parentNode && parentNode->isShadowRoot(); 997 return parentNode && parentNode->isShadowRoot();
998 } 998 }
999 999
1000 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS tyle* defaultParent, 1000 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS tyle* defaultParent, StyleSharingBehavior sharingBehavior,
1001 StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling) 1001 RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling, int c hildIndex)
1002 { 1002 {
1003 // Once an element has a renderer, we don't try to destroy it, since otherwi se the renderer 1003 // Once an element has a renderer, we don't try to destroy it, since otherwi se the renderer
1004 // will vanish if a style recalc happens during loading. 1004 // will vanish if a style recalc happens during loading.
1005 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStyles heetsLoaded() && !element->renderer()) { 1005 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStyles heetsLoaded() && !element->renderer()) {
1006 if (!s_styleNotYetAvailable) { 1006 if (!s_styleNotYetAvailable) {
1007 s_styleNotYetAvailable = RenderStyle::create().leakRef(); 1007 s_styleNotYetAvailable = RenderStyle::create().leakRef();
1008 s_styleNotYetAvailable->setDisplay(NONE); 1008 s_styleNotYetAvailable->setDisplay(NONE);
1009 s_styleNotYetAvailable->font().update(m_fontSelector); 1009 s_styleNotYetAvailable->font().update(m_fontSelector);
1010 } 1010 }
1011 element->document()->setHasNodesWithPlaceholderStyle(); 1011 element->document()->setHasNodesWithPlaceholderStyle();
1012 return s_styleNotYetAvailable; 1012 return s_styleNotYetAvailable;
1013 } 1013 }
1014 1014
1015 StyleResolverState& state = m_state; 1015 StyleResolverState& state = m_state;
1016 state.initForStyleResolve(document(), element, defaultParent, regionForStyli ng); 1016 state.initForStyleResolve(document(), element, childIndex, defaultParent, re gionForStyling);
1017 if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoi nt()) { 1017 if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoi nt()) {
1018 RenderStyle* sharedStyle = locateSharedStyle(); 1018 RenderStyle* sharedStyle = locateSharedStyle();
1019 if (sharedStyle) { 1019 if (sharedStyle) {
1020 state.clear(); 1020 state.clear();
1021 return sharedStyle; 1021 return sharedStyle;
1022 } 1022 }
1023 } 1023 }
1024 1024
1025 if (state.parentStyle()) { 1025 if (state.parentStyle()) {
1026 state.setStyle(RenderStyle::create()); 1026 state.setStyle(RenderStyle::create());
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 } 1197 }
1198 1198
1199 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const P seudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle) 1199 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const P seudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
1200 { 1200 {
1201 ASSERT(parentStyle); 1201 ASSERT(parentStyle);
1202 if (!e) 1202 if (!e)
1203 return 0; 1203 return 0;
1204 1204
1205 StyleResolverState& state = m_state; 1205 StyleResolverState& state = m_state;
1206 1206
1207 state.initForStyleResolve(document(), e, parentStyle); 1207 state.initForStyleResolve(document(), e, 0, parentStyle);
1208 1208
1209 if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) { 1209 if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) {
1210 state.setStyle(RenderStyle::create()); 1210 state.setStyle(RenderStyle::create());
1211 state.style()->inheritFrom(state.parentStyle()); 1211 state.style()->inheritFrom(state.parentStyle());
1212 } else { 1212 } else {
1213 state.setStyle(defaultStyleForElement()); 1213 state.setStyle(defaultStyleForElement());
1214 state.setParentStyle(RenderStyle::clone(state.style())); 1214 state.setParentStyle(RenderStyle::clone(state.style()));
1215 } 1215 }
1216 1216
1217 // Since we don't use pseudo-elements in any of our quirk/print user agent r ules, don't waste time walking 1217 // Since we don't use pseudo-elements in any of our quirk/print user agent r ules, don't waste time walking
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
1697 PassRefPtr<CSSRuleList> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude) 1697 PassRefPtr<CSSRuleList> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
1698 { 1698 {
1699 return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude); 1699 return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
1700 } 1700 }
1701 1701
1702 PassRefPtr<CSSRuleList> StyleResolver::pseudoStyleRulesForElement(Element* e, Ps eudoId pseudoId, unsigned rulesToInclude) 1702 PassRefPtr<CSSRuleList> StyleResolver::pseudoStyleRulesForElement(Element* e, Ps eudoId pseudoId, unsigned rulesToInclude)
1703 { 1703 {
1704 if (!e || !e->document()->haveStylesheetsLoaded()) 1704 if (!e || !e->document()->haveStylesheetsLoaded())
1705 return 0; 1705 return 0;
1706 1706
1707 m_state.initForStyleResolve(document(), e, 0); 1707 m_state.initForStyleResolve(document(), e);
1708 1708
1709 ElementRuleCollector collector(this, m_state); 1709 ElementRuleCollector collector(this, m_state);
1710 collector.setMode(SelectorChecker::CollectingRules); 1710 collector.setMode(SelectorChecker::CollectingRules);
1711 collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId)); 1711 collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
1712 1712
1713 if (rulesToInclude & UAAndUserCSSRules) { 1713 if (rulesToInclude & UAAndUserCSSRules) {
1714 // First we match rules from the user agent sheet. 1714 // First we match rules from the user agent sheet.
1715 matchUARules(collector); 1715 matchUARules(collector);
1716 1716
1717 // Now we check user sheet rules. 1717 // Now we check user sheet rules.
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 2044
2045 if (cachedMatchedProperties || !cacheHash) 2045 if (cachedMatchedProperties || !cacheHash)
2046 return; 2046 return;
2047 if (!MatchedPropertiesCache::isCacheable(state.element(), state.style(), sta te.parentStyle())) 2047 if (!MatchedPropertiesCache::isCacheable(state.element(), state.style(), sta te.parentStyle()))
2048 return; 2048 return;
2049 m_matchedPropertiesCache.add(state.style(), state.parentStyle(), cacheHash, matchResult); 2049 m_matchedPropertiesCache.add(state.style(), state.parentStyle(), cacheHash, matchResult);
2050 } 2050 }
2051 2051
2052 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, Rend erStyle* style) 2052 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, Rend erStyle* style)
2053 { 2053 {
2054 m_state.initForStyleResolve(document(), 0, style); 2054 m_state.initForStyleResolve(document(), 0, 0, style);
2055 m_state.setStyle(style); 2055 m_state.setStyle(style);
2056 applyPropertyToCurrentStyle(id, value); 2056 applyPropertyToCurrentStyle(id, value);
2057 } 2057 }
2058 2058
2059 void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* valu e) 2059 void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* valu e)
2060 { 2060 {
2061 if (value) 2061 if (value)
2062 applyProperty(id, value); 2062 applyProperty(id, value);
2063 } 2063 }
2064 2064
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
2395 void CachedMatchedProperties::reportMemoryUsage(MemoryObjectInfo* memoryObjectIn fo) const 2395 void CachedMatchedProperties::reportMemoryUsage(MemoryObjectInfo* memoryObjectIn fo) const
2396 { 2396 {
2397 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); 2397 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
2398 info.addMember(matchedProperties, "matchedProperties"); 2398 info.addMember(matchedProperties, "matchedProperties");
2399 info.addMember(ranges, "ranges"); 2399 info.addMember(ranges, "ranges");
2400 info.addMember(renderStyle, "renderStyle"); 2400 info.addMember(renderStyle, "renderStyle");
2401 info.addMember(parentRenderStyle, "parentRenderStyle"); 2401 info.addMember(parentRenderStyle, "parentRenderStyle");
2402 } 2402 }
2403 2403
2404 } // namespace WebCore 2404 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/css/resolver/StyleResolver.h ('k') | Source/core/css/resolver/StyleResolverState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698