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

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

Issue 22966004: Revert "Replace style sharing cousin list search with LRU" (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 4 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/SharedStyleFinder.h ('k') | Source/core/css/resolver/StyleResolver.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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 #include "core/html/track/WebVTTElement.h" 49 #include "core/html/track/WebVTTElement.h"
50 #include "core/rendering/style/RenderStyle.h" 50 #include "core/rendering/style/RenderStyle.h"
51 #include "core/svg/SVGElement.h" 51 #include "core/svg/SVGElement.h"
52 #include "wtf/HashSet.h" 52 #include "wtf/HashSet.h"
53 #include "wtf/text/AtomicString.h" 53 #include "wtf/text/AtomicString.h"
54 54
55 namespace WebCore { 55 namespace WebCore {
56 56
57 using namespace HTMLNames; 57 using namespace HTMLNames;
58 58
59 static const unsigned cStyleSearchThreshold = 10;
60 static const unsigned cStyleSearchLevelThreshold = 10;
61
59 static inline bool parentElementPreventsSharing(const Element* parentElement) 62 static inline bool parentElementPreventsSharing(const Element* parentElement)
60 { 63 {
64 if (!parentElement)
65 return false;
61 return parentElement->hasFlagsSetDuringStylingOfChildren(); 66 return parentElement->hasFlagsSetDuringStylingOfChildren();
62 } 67 }
63 68
69 Node* SharedStyleFinder::locateCousinList(Element* parent, unsigned& visitedNode Count) const
70 {
71 if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
72 return 0;
73 if (!parent || !parent->isStyledElement())
74 return 0;
75 if (parent->hasScopedHTMLStyleChild())
76 return 0;
77 if (parent->inlineStyle())
78 return 0;
79 if (parent->isSVGElement() && toSVGElement(parent)->animatedSMILStylePropert ies())
80 return 0;
81 if (parent->hasID() && m_features.idsInRules.contains(parent->idForStyleReso lution().impl()))
82 return 0;
83 if (isShadowHost(parent) && parent->shadow()->containsActiveStyles())
84 return 0;
85
86 RenderStyle* parentStyle = parent->renderStyle();
87 unsigned subcount = 0;
88 Node* thisCousin = parent;
89 Node* currentNode = parent->previousSibling();
90
91 // Reserve the tries for this level. This effectively makes sure that the al gorithm
92 // will never go deeper than cStyleSearchLevelThreshold levels into recursio n.
93 visitedNodeCount += cStyleSearchThreshold;
94 while (thisCousin) {
95 while (currentNode) {
96 ++subcount;
97 if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderSt yle() == parentStyle && currentNode->lastChild()
98 && currentNode->isElementNode() && !parentElementPreventsSharing (toElement(currentNode))
99 && !toElement(currentNode)->shadow()
100 ) {
101 // Adjust for unused reserved tries.
102 visitedNodeCount -= cStyleSearchThreshold - subcount;
103 return currentNode->lastChild();
104 }
105 if (subcount >= cStyleSearchThreshold)
106 return 0;
107 currentNode = currentNode->previousSibling();
108 }
109 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeC ount);
110 thisCousin = currentNode;
111 }
112
113 return 0;
114 }
115
116
64 bool SharedStyleFinder::canShareStyleWithControl(const ElementResolveContext& co ntext, Element* element) const 117 bool SharedStyleFinder::canShareStyleWithControl(const ElementResolveContext& co ntext, Element* element) const
65 { 118 {
66 if (!element->hasTagName(inputTag) || !context.element()->hasTagName(inputTa g)) 119 if (!element->hasTagName(inputTag) || !context.element()->hasTagName(inputTa g))
67 return false; 120 return false;
68 121
69 HTMLInputElement* thisInputElement = toHTMLInputElement(element); 122 HTMLInputElement* thisInputElement = toHTMLInputElement(element);
70 HTMLInputElement* otherInputElement = toHTMLInputElement(context.element()); 123 HTMLInputElement* otherInputElement = toHTMLInputElement(context.element());
71 if (thisInputElement->elementData() != otherInputElement->elementData()) { 124 if (thisInputElement->elementData() != otherInputElement->elementData()) {
72 if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->f astGetAttribute(typeAttr)) 125 if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->f astGetAttribute(typeAttr))
73 return false; 126 return false;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 if (context.element()->hasTagName(progressTag)) { 207 if (context.element()->hasTagName(progressTag)) {
155 if (context.element()->shouldAppearIndeterminate() != sharingCandidate-> shouldAppearIndeterminate()) 208 if (context.element()->shouldAppearIndeterminate() != sharingCandidate-> shouldAppearIndeterminate())
156 return false; 209 return false;
157 } 210 }
158 211
159 return true; 212 return true;
160 } 213 }
161 214
162 bool SharedStyleFinder::canShareStyleWithElement(const ElementResolveContext& co ntext, Element* element) const 215 bool SharedStyleFinder::canShareStyleWithElement(const ElementResolveContext& co ntext, Element* element) const
163 { 216 {
164 if (context.element() == element)
165 return false;
166 Element* parent = element->parentElement();
167 RenderStyle* style = element->renderStyle(); 217 RenderStyle* style = element->renderStyle();
168 if (!style) 218 if (!style)
169 return false; 219 return false;
170 if (!parent)
171 return false;
172 if (context.element()->parentElement()->renderStyle() != parent->renderStyle ())
173 return false;
174 if (style->unique()) 220 if (style->unique())
175 return false; 221 return false;
176 if (style->hasUniquePseudoStyle()) 222 if (style->hasUniquePseudoStyle())
177 return false; 223 return false;
178 if (element->tagQName() != context.element()->tagQName()) 224 if (element->tagQName() != context.element()->tagQName())
179 return false; 225 return false;
180 if (element->inlineStyle()) 226 if (element->inlineStyle())
181 return false; 227 return false;
182 if (element->needsStyleRecalc()) 228 if (element->needsStyleRecalc())
183 return false; 229 return false;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 return false; 289 return false;
244 290
245 if (element->isWebVTTElement() && context.element()->isWebVTTElement() && to WebVTTElement(element)->isPastNode() != toWebVTTElement(context.element())->isPa stNode()) 291 if (element->isWebVTTElement() && context.element()->isWebVTTElement() && to WebVTTElement(element)->isPastNode() != toWebVTTElement(context.element())->isPa stNode())
246 return false; 292 return false;
247 293
248 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExist s(context.document())) { 294 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExist s(context.document())) {
249 if (element == fullscreen->webkitCurrentFullScreenElement() || context.e lement() == fullscreen->webkitCurrentFullScreenElement()) 295 if (element == fullscreen->webkitCurrentFullScreenElement() || context.e lement() == fullscreen->webkitCurrentFullScreenElement())
250 return false; 296 return false;
251 } 297 }
252 298
253 if (context.element()->parentElement() != parent) {
254 if (!parent->isStyledElement())
255 return false;
256 if (parent->hasScopedHTMLStyleChild())
257 return false;
258 if (parent->inlineStyle())
259 return false;
260 if (parent->isSVGElement() && toSVGElement(parent)->animatedSMILStylePro perties())
261 return false;
262 if (parent->hasID() && m_features.idsInRules.contains(parent->idForStyle Resolution().impl()))
263 return false;
264 if (parentElementPreventsSharing(parent))
265 return false;
266 }
267
268 return true; 299 return true;
269 } 300 }
270 301
302 inline Element* SharedStyleFinder::findSiblingForStyleSharing(const ElementResol veContext& context, Node* node, unsigned& count) const
303 {
304 for (; node; node = node->previousSibling()) {
305 if (!node->isStyledElement())
306 continue;
307 if (canShareStyleWithElement(context, toElement(node)))
308 break;
309 if (count++ == cStyleSearchThreshold)
310 return 0;
311 }
312 return toElement(node);
313 }
314
271 #ifdef STYLE_STATS 315 #ifdef STYLE_STATS
272 Element* SharedStyleFinder::searchDocumentForSharedStyle(const ElementResolveCon text& context) const 316 Element* SharedStyleFinder::searchDocumentForSharedStyle(const ElementResolveCon text& context) const
273 { 317 {
274 for (Element* element = context.element()->document()->documentElement(); el ement; element = ElementTraversal::next(element)) { 318 for (Element* element = context.element()->document()->documentElement(); el ement; element = ElementTraversal::next(element)) {
275 if (canShareStyleWithElement(context, element)) 319 if (canShareStyleWithElement(context, element))
276 return element; 320 return element;
277 } 321 }
278 return 0; 322 return 0;
279 } 323 }
280 #endif 324 #endif
281 325
282 inline Element* SharedStyleFinder::findElementForStyleSharing(const ElementResol veContext& context) const
283 {
284 StyleSharingList& styleSharingList = m_styleResolver->styleSharingList();
285 for (StyleSharingList::iterator iter = styleSharingList.begin(); iter != sty leSharingList.end(); ++iter) {
286 if (canShareStyleWithElement(context, *iter)) {
287 Element* element = *iter;
288 if (iter != styleSharingList.begin()) {
289 // Move the element to the front of the LRU
290 styleSharingList.remove(iter);
291 styleSharingList.prepend(element);
292 }
293 return element;
294 }
295 }
296 m_styleResolver->addToStyleSharingList(context.element());
297 return 0;
298 }
299
300 RenderStyle* SharedStyleFinder::locateSharedStyle(const ElementResolveContext& c ontext, RenderStyle* newStyle) 326 RenderStyle* SharedStyleFinder::locateSharedStyle(const ElementResolveContext& c ontext, RenderStyle* newStyle)
301 { 327 {
302 STYLE_STATS_ADD_SEARCH(); 328 STYLE_STATS_ADD_SEARCH();
303 if (!context.element() || !context.element()->isStyledElement() || !context. element()->parentElement()) 329 if (!context.element() || !context.element()->isStyledElement())
304 return 0; 330 return 0;
305 331
306 // If the element has inline style it is probably unique. 332 // If the element has inline style it is probably unique.
307 if (context.element()->inlineStyle()) 333 if (context.element()->inlineStyle())
308 return 0; 334 return 0;
309 if (context.element()->isSVGElement() && toSVGElement(context.element())->an imatedSMILStyleProperties()) 335 if (context.element()->isSVGElement() && toSVGElement(context.element())->an imatedSMILStyleProperties())
310 return 0; 336 return 0;
311 // Ids stop style sharing if they show up in the stylesheets. 337 // Ids stop style sharing if they show up in the stylesheets.
312 if (context.element()->hasID() && m_features.idsInRules.contains(context.ele ment()->idForStyleResolution().impl())) 338 if (context.element()->hasID() && m_features.idsInRules.contains(context.ele ment()->idForStyleResolution().impl()))
313 return 0; 339 return 0;
(...skipping 23 matching lines...) Expand all
337 return 0; 363 return 0;
338 if (isShadowHost(context.element()) && context.element()->shadow()->contains ActiveStyles()) 364 if (isShadowHost(context.element()) && context.element()->shadow()->contains ActiveStyles())
339 return 0; 365 return 0;
340 366
341 STYLE_STATS_ADD_ELEMENT_ELIGIBLE_FOR_SHARING(); 367 STYLE_STATS_ADD_ELEMENT_ELIGIBLE_FOR_SHARING();
342 368
343 // Cache whether context.element() is affected by any known class selectors. 369 // Cache whether context.element() is affected by any known class selectors.
344 // FIXME: This should be an explicit out parameter, instead of a member vari able. 370 // FIXME: This should be an explicit out parameter, instead of a member vari able.
345 m_elementAffectedByClassRules = context.element() && context.element()->hasC lass() && classNamesAffectedByRules(context.element()->classNames()); 371 m_elementAffectedByClassRules = context.element() && context.element()->hasC lass() && classNamesAffectedByRules(context.element()->classNames());
346 372
347 Element* shareElement = findElementForStyleSharing(context); 373 // Check previous siblings and their cousins.
374 unsigned count = 0;
375 unsigned visitedNodeCount = 0;
376 Element* shareElement = 0;
377 Node* cousinList = context.element()->previousSibling();
378 while (cousinList) {
379 shareElement = findSiblingForStyleSharing(context, cousinList, count);
380 if (shareElement)
381 break;
382 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCo unt);
383 }
348 384
349 #ifdef STYLE_STATS 385 #ifdef STYLE_STATS
350 // FIXME: these stats don't to into account whether or not sibling/attribute 386 // FIXME: these stats don't to into account whether or not sibling/attribute
351 // rules prevent these nodes from actually sharing 387 // rules prevent these nodes from actually sharing
352 if (shareElement) { 388 if (shareElement) {
353 STYLE_STATS_ADD_SEARCH_FOUND_SIBLING_FOR_SHARING(); 389 STYLE_STATS_ADD_SEARCH_FOUND_SIBLING_FOR_SHARING();
354 } else { 390 } else {
355 shareElement = searchDocumentForSharedStyle(context); 391 shareElement = searchDocumentForSharedStyle(context);
356 if (shareElement) 392 if (shareElement)
357 STYLE_STATS_ADD_SEARCH_MISSED_SHARING(); 393 STYLE_STATS_ADD_SEARCH_MISSED_SHARING();
(...skipping 12 matching lines...) Expand all
370 if (m_styleResolver->styleSharingCandidateMatchesRuleSet(context, newStyle, m_uncommonAttributeRuleSet)) 406 if (m_styleResolver->styleSharingCandidateMatchesRuleSet(context, newStyle, m_uncommonAttributeRuleSet))
371 return 0; 407 return 0;
372 // Tracking child index requires unique style for each node. This may get se t by the sibling rule match above. 408 // Tracking child index requires unique style for each node. This may get se t by the sibling rule match above.
373 if (parentElementPreventsSharing(context.element()->parentElement())) 409 if (parentElementPreventsSharing(context.element()->parentElement()))
374 return 0; 410 return 0;
375 STYLE_STATS_ADD_STYLE_SHARED(); 411 STYLE_STATS_ADD_STYLE_SHARED();
376 return shareElement->renderStyle(); 412 return shareElement->renderStyle();
377 } 413 }
378 414
379 } 415 }
OLDNEW
« no previous file with comments | « Source/core/css/resolver/SharedStyleFinder.h ('k') | Source/core/css/resolver/StyleResolver.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698