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

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: Adding a mitigation for the perf regression to Element::recalcStyle. 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
« 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 497 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 } 508 }
509 509
510 // Now check SMIL animation override style. 510 // Now check SMIL animation override style.
511 if (includeSMILProperties && matchAuthorAndUserStyles && m_state.styledEleme nt() && m_state.styledElement()->isSVGElement()) 511 if (includeSMILProperties && matchAuthorAndUserStyles && m_state.styledEleme nt() && m_state.styledElement()->isSVGElement())
512 collector.addElementStyleProperties(toSVGElement(m_state.styledElement() )->animatedSMILStyleProperties(), false /* isCacheable */); 512 collector.addElementStyleProperties(toSVGElement(m_state.styledElement() )->animatedSMILStyleProperties(), false /* isCacheable */);
513 513
514 if (m_state.styledElement() && m_state.styledElement()->hasActiveAnimations( )) 514 if (m_state.styledElement() && m_state.styledElement()->hasActiveAnimations( ))
515 collector.matchedResult().isCacheable = false; 515 collector.matchedResult().isCacheable = false;
516 } 516 }
517 517
518 inline void StyleResolver::initElement(Element* e) 518 inline void StyleResolver::initElement(Element* e, int childIndex)
519 { 519 {
520 if (m_state.element() != e) { 520 if (m_state.element() != e) {
521 m_state.initElement(e); 521 m_state.initElement(e, childIndex);
522 if (e && e == e->document()->documentElement()) { 522 if (e && e == e->document()->documentElement()) {
523 e->document()->setDirectionSetOnDocumentElement(false); 523 e->document()->setDirectionSetOnDocumentElement(false);
524 e->document()->setWritingModeSetOnDocumentElement(false); 524 e->document()->setWritingModeSetOnDocumentElement(false);
525 } 525 }
526 } 526 }
527 } 527 }
528 528
529 static const unsigned cStyleSearchThreshold = 10; 529 static const unsigned cStyleSearchThreshold = 10;
530 static const unsigned cStyleSearchLevelThreshold = 10; 530 static const unsigned cStyleSearchLevelThreshold = 10;
531 531
(...skipping 15 matching lines...) Expand all
547 if (parent->inlineStyle()) 547 if (parent->inlineStyle())
548 return 0; 548 return 0;
549 if (parent->isSVGElement() && toSVGElement(parent)->animatedSMILStylePropert ies()) 549 if (parent->isSVGElement() && toSVGElement(parent)->animatedSMILStylePropert ies())
550 return 0; 550 return 0;
551 if (parent->hasID() && m_features.idsInRules.contains(parent->idForStyleReso lution().impl())) 551 if (parent->hasID() && m_features.idsInRules.contains(parent->idForStyleReso lution().impl()))
552 return 0; 552 return 0;
553 553
554 RenderStyle* parentStyle = parent->renderStyle(); 554 RenderStyle* parentStyle = parent->renderStyle();
555 unsigned subcount = 0; 555 unsigned subcount = 0;
556 Node* thisCousin = parent; 556 Node* thisCousin = parent;
557 Node* currentNode = parent->previousSibling(); 557 Node* currentNode = parent->nextSibling();
558 558
559 // Reserve the tries for this level. This effectively makes sure that the al gorithm 559 // Reserve the tries for this level. This effectively makes sure that the al gorithm
560 // will never go deeper than cStyleSearchLevelThreshold levels into recursio n. 560 // will never go deeper than cStyleSearchLevelThreshold levels into recursio n.
561 visitedNodeCount += cStyleSearchThreshold; 561 visitedNodeCount += cStyleSearchThreshold;
562 while (thisCousin) { 562 while (thisCousin) {
563 while (currentNode) { 563 while (currentNode) {
564 ++subcount; 564 ++subcount;
565 if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderSt yle() == parentStyle && currentNode->lastChild() 565 if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderSt yle() == parentStyle && currentNode->lastChild()
566 && currentNode->isElementNode() && !parentElementPreventsSharing (toElement(currentNode)) 566 && currentNode->isElementNode() && !parentElementPreventsSharing (toElement(currentNode))
567 && !toElement(currentNode)->shadow() 567 && !toElement(currentNode)->shadow()
568 ) { 568 ) {
569 // Adjust for unused reserved tries. 569 // Adjust for unused reserved tries.
570 visitedNodeCount -= cStyleSearchThreshold - subcount; 570 visitedNodeCount -= cStyleSearchThreshold - subcount;
571 return currentNode->lastChild(); 571 return currentNode->lastChild();
572 } 572 }
573 if (subcount >= cStyleSearchThreshold) 573 if (subcount >= cStyleSearchThreshold)
574 return 0; 574 return 0;
575 currentNode = currentNode->previousSibling(); 575 currentNode = currentNode->nextSibling();
576 } 576 }
577 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC ount); 577 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC ount);
578 thisCousin = currentNode; 578 thisCousin = currentNode;
579 } 579 }
580 580
581 return 0; 581 return 0;
582 } 582 }
583 583
584 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet) 584 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
585 { 585 {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 if (FullscreenController* fullscreen = FullscreenController::fromIfExists(st ate.document())) { 764 if (FullscreenController* fullscreen = FullscreenController::fromIfExists(st ate.document())) {
765 if (element == fullscreen->webkitCurrentFullScreenElement() || state.ele ment() == fullscreen->webkitCurrentFullScreenElement()) 765 if (element == fullscreen->webkitCurrentFullScreenElement() || state.ele ment() == fullscreen->webkitCurrentFullScreenElement())
766 return false; 766 return false;
767 } 767 }
768 768
769 return true; 769 return true;
770 } 770 }
771 771
772 inline Element* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const 772 inline Element* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const
773 { 773 {
774 for (; node; node = node->previousSibling()) { 774 for (; node; node = node->nextSibling()) {
775 if (!node->isStyledElement()) 775 if (!node->isStyledElement())
776 continue; 776 continue;
777 if (canShareStyleWithElement(toElement(node))) 777 if (canShareStyleWithElement(toElement(node)))
778 break; 778 break;
779 if (count++ == cStyleSearchThreshold) 779 if (count++ == cStyleSearchThreshold)
780 return 0; 780 return 0;
781 } 781 }
782 return toElement(node); 782 return toElement(node);
783 } 783 }
784 784
(...skipping 24 matching lines...) Expand all
809 // When a dialog is first shown, its style is mutated to center it in the 809 // When a dialog is first shown, its style is mutated to center it in the
810 // viewport. So the styles can't be shared since the viewport position and 810 // viewport. So the styles can't be shared since the viewport position and
811 // size may be different each time a dialog is opened. 811 // size may be different each time a dialog is opened.
812 if (state.element()->hasTagName(dialogTag)) 812 if (state.element()->hasTagName(dialogTag))
813 return 0; 813 return 0;
814 814
815 // Cache whether state.element is affected by any known class selectors. 815 // Cache whether state.element is affected by any known class selectors.
816 // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver. 816 // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver.
817 state.setElementAffectedByClassRules(state.element() && state.element()->has Class() && classNamesAffectedByRules(state.element()->classNames())); 817 state.setElementAffectedByClassRules(state.element() && state.element()->has Class() && classNamesAffectedByRules(state.element()->classNames()));
818 818
819 // Check previous siblings and their cousins. 819 // Check next siblings and their cousins.
820 unsigned count = 0; 820 unsigned count = 0;
821 unsigned visitedNodeCount = 0; 821 unsigned visitedNodeCount = 0;
822 Element* shareElement = 0; 822 Element* shareElement = 0;
823 Node* cousinList = state.styledElement()->previousSibling(); 823 Node* cousinList = state.styledElement()->nextSibling();
824 while (cousinList) { 824 while (cousinList) {
825 shareElement = findSiblingForStyleSharing(cousinList, count); 825 shareElement = findSiblingForStyleSharing(cousinList, count);
826 if (shareElement) 826 if (shareElement)
827 break; 827 break;
828 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo unt); 828 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo unt);
829 } 829 }
830 830
831 // If we have exhausted all our budget or our cousins. 831 // If we have exhausted all our budget or our cousins.
832 if (!shareElement) 832 if (!shareElement)
833 return 0; 833 return 0;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 } 1028 }
1029 1029
1030 static inline bool isAtShadowBoundary(const Element* element) 1030 static inline bool isAtShadowBoundary(const Element* element)
1031 { 1031 {
1032 if (!element) 1032 if (!element)
1033 return false; 1033 return false;
1034 ContainerNode* parentNode = element->parentNode(); 1034 ContainerNode* parentNode = element->parentNode();
1035 return parentNode && parentNode->isShadowRoot(); 1035 return parentNode && parentNode->isShadowRoot();
1036 } 1036 }
1037 1037
1038 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS tyle* defaultParent, 1038 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS tyle* defaultParent, StyleSharingBehavior sharingBehavior,
1039 StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling) 1039 RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling, int c hildIndex)
1040 { 1040 {
1041 // Once an element has a renderer, we don't try to destroy it, since otherwi se the renderer 1041 // Once an element has a renderer, we don't try to destroy it, since otherwi se the renderer
1042 // will vanish if a style recalc happens during loading. 1042 // will vanish if a style recalc happens during loading.
1043 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStyles heetsLoaded() && !element->renderer()) { 1043 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStyles heetsLoaded() && !element->renderer()) {
1044 if (!s_styleNotYetAvailable) { 1044 if (!s_styleNotYetAvailable) {
1045 s_styleNotYetAvailable = RenderStyle::create().leakRef(); 1045 s_styleNotYetAvailable = RenderStyle::create().leakRef();
1046 s_styleNotYetAvailable->setDisplay(NONE); 1046 s_styleNotYetAvailable->setDisplay(NONE);
1047 s_styleNotYetAvailable->font().update(m_fontSelector); 1047 s_styleNotYetAvailable->font().update(m_fontSelector);
1048 } 1048 }
1049 element->document()->setHasNodesWithPlaceholderStyle(); 1049 element->document()->setHasNodesWithPlaceholderStyle();
1050 return s_styleNotYetAvailable; 1050 return s_styleNotYetAvailable;
1051 } 1051 }
1052 1052
1053 StyleResolverState& state = m_state; 1053 StyleResolverState& state = m_state;
1054 initElement(element); 1054 initElement(element, childIndex);
1055 state.initForStyleResolve(document(), element, defaultParent, regionForStyli ng); 1055 state.initForStyleResolve(document(), element, defaultParent, regionForStyli ng);
1056 if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoi nt()) { 1056 if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoi nt()) {
1057 RenderStyle* sharedStyle = locateSharedStyle(); 1057 RenderStyle* sharedStyle = locateSharedStyle();
1058 if (sharedStyle) { 1058 if (sharedStyle) {
1059 state.clear(); 1059 state.clear();
1060 return sharedStyle; 1060 return sharedStyle;
1061 } 1061 }
1062 } 1062 }
1063 1063
1064 if (state.parentStyle()) { 1064 if (state.parentStyle()) {
(...skipping 2625 matching lines...) Expand 10 before | Expand all | Expand 10 after
3690 info.addMember(m_state, "state"); 3690 info.addMember(m_state, "state");
3691 3691
3692 // FIXME: move this to a place where it would be called only once? 3692 // FIXME: move this to a place where it would be called only once?
3693 info.addMember(CSSDefaultStyleSheets::defaultStyle, "defaultStyle"); 3693 info.addMember(CSSDefaultStyleSheets::defaultStyle, "defaultStyle");
3694 info.addMember(CSSDefaultStyleSheets::defaultQuirksStyle, "defaultQuirksStyl e"); 3694 info.addMember(CSSDefaultStyleSheets::defaultQuirksStyle, "defaultQuirksStyl e");
3695 info.addMember(CSSDefaultStyleSheets::defaultPrintStyle, "defaultPrintStyle" ); 3695 info.addMember(CSSDefaultStyleSheets::defaultPrintStyle, "defaultPrintStyle" );
3696 info.addMember(CSSDefaultStyleSheets::defaultViewSourceStyle, "defaultViewSo urceStyle"); 3696 info.addMember(CSSDefaultStyleSheets::defaultViewSourceStyle, "defaultViewSo urceStyle");
3697 } 3697 }
3698 3698
3699 } // namespace WebCore 3699 } // 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