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

Unified Diff: Source/core/css/resolver/SharedStyleFinder.cpp

Issue 24106007: Replace style sharing cousin list search with LRU (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Updating with esprehn's changes Created 7 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/css/resolver/SharedStyleFinder.h ('k') | Source/core/css/resolver/StyleResolver.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/css/resolver/SharedStyleFinder.cpp
diff --git a/Source/core/css/resolver/SharedStyleFinder.cpp b/Source/core/css/resolver/SharedStyleFinder.cpp
index 2cbc11f8bec7a4a49438de5d3018d5c837d9ff2e..aad32e73e0121d073a7c1fa85337fc2bc138e182 100644
--- a/Source/core/css/resolver/SharedStyleFinder.cpp
+++ b/Source/core/css/resolver/SharedStyleFinder.cpp
@@ -36,6 +36,7 @@
#include "core/dom/ContainerNode.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
+#include "core/dom/ElementTraversal.h"
#include "core/dom/FullscreenElementStack.h"
#include "core/dom/Node.h"
#include "core/dom/NodeRenderStyle.h"
@@ -55,64 +56,11 @@ namespace WebCore {
using namespace HTMLNames;
-static const unsigned cStyleSearchThreshold = 10;
-static const unsigned cStyleSearchLevelThreshold = 10;
-
static inline bool parentElementPreventsSharing(const Element* parentElement)
{
- if (!parentElement)
- return false;
return parentElement->hasFlagsSetDuringStylingOfChildren();
}
-Node* SharedStyleFinder::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
-{
- if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
- return 0;
- if (!parent || !parent->isStyledElement())
- return 0;
- if (parent->hasScopedHTMLStyleChild())
- return 0;
- if (parent->inlineStyle())
- return 0;
- if (parent->isSVGElement() && toSVGElement(parent)->animatedSMILStyleProperties())
- return 0;
- if (parent->hasID() && m_features.idsInRules.contains(parent->idForStyleResolution().impl()))
- return 0;
- if (isShadowHost(parent) && parent->shadow()->containsActiveStyles())
- return 0;
-
- RenderStyle* parentStyle = parent->renderStyle();
- unsigned subcount = 0;
- Node* thisCousin = parent;
- Node* currentNode = parent->previousSibling();
-
- // Reserve the tries for this level. This effectively makes sure that the algorithm
- // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
- visitedNodeCount += cStyleSearchThreshold;
- while (thisCousin) {
- while (currentNode) {
- ++subcount;
- if (!currentNode->hasScopedHTMLStyleChild() && currentNode->renderStyle() == parentStyle && currentNode->lastChild()
- && currentNode->isElementNode() && !parentElementPreventsSharing(toElement(currentNode))
- && !toElement(currentNode)->shadow()
- ) {
- // Adjust for unused reserved tries.
- visitedNodeCount -= cStyleSearchThreshold - subcount;
- return currentNode->lastChild();
- }
- if (subcount >= cStyleSearchThreshold)
- return 0;
- currentNode = currentNode->previousSibling();
- }
- currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
- thisCousin = currentNode;
- }
-
- return 0;
-}
-
-
bool SharedStyleFinder::canShareStyleWithControl(const ElementResolveContext& context, Element* element) const
{
if (!element->hasTagName(inputTag) || !context.element()->hasTagName(inputTag))
@@ -213,9 +161,16 @@ bool SharedStyleFinder::sharingCandidateHasIdenticalStyleAffectingAttributes(con
bool SharedStyleFinder::canShareStyleWithElement(const ElementResolveContext& context, Element* element) const
{
+ if (context.element() == element)
+ return false;
+ Element* parent = element->parentElement();
RenderStyle* style = element->renderStyle();
if (!style)
return false;
+ if (!parent)
+ return false;
+ if (context.element()->parentElement()->renderStyle() != parent->renderStyle())
+ return false;
if (style->unique())
return false;
if (style->hasUniquePseudoStyle())
@@ -295,20 +250,22 @@ bool SharedStyleFinder::canShareStyleWithElement(const ElementResolveContext& co
return false;
}
- return true;
-}
-
-inline Element* SharedStyleFinder::findSiblingForStyleSharing(const ElementResolveContext& context, Node* node, unsigned& count) const
-{
- for (; node; node = node->previousSibling()) {
- if (!node->isStyledElement())
- continue;
- if (canShareStyleWithElement(context, toElement(node)))
- break;
- if (count++ == cStyleSearchThreshold)
- return 0;
+ if (context.element()->parentElement() != parent) {
+ if (!parent->isStyledElement())
+ return false;
+ if (parent->hasScopedHTMLStyleChild())
+ return false;
+ if (parent->inlineStyle())
+ return false;
+ if (parent->isSVGElement() && toSVGElement(parent)->animatedSMILStyleProperties())
+ return false;
+ if (parent->hasID() && m_features.idsInRules.contains(parent->idForStyleResolution().impl()))
+ return false;
+ if (parentElementPreventsSharing(parent))
+ return false;
}
- return toElement(node);
+
+ return true;
}
#ifdef STYLE_STATS
@@ -322,45 +279,29 @@ Element* SharedStyleFinder::searchDocumentForSharedStyle(const ElementResolveCon
}
#endif
+inline Element* SharedStyleFinder::findElementForStyleSharing(const ElementResolveContext& context) const
+{
+ StyleSharingList& styleSharingList = m_styleResolver->styleSharingList();
+ for (StyleSharingList::iterator it = styleSharingList.begin(); it != styleSharingList.end(); ++it) {
+ if (!canShareStyleWithElement(context, it->get()))
+ continue;
+ Element* element = it->get();
+ if (it != styleSharingList.begin()) {
+ // Move the element to the front of the LRU
+ styleSharingList.remove(it);
+ styleSharingList.prepend(element);
+ }
+ return element;
+ }
+ m_styleResolver->addToStyleSharingList(context.element());
+ return 0;
+}
+
RenderStyle* SharedStyleFinder::locateSharedStyle(const ElementResolveContext& context, RenderStyle* newStyle)
{
STYLE_STATS_ADD_SEARCH();
- if (!context.element() || !context.element()->isStyledElement())
- return 0;
- // If the element has inline style it is probably unique.
- if (context.element()->inlineStyle())
- return 0;
- if (context.element()->isSVGElement() && toSVGElement(context.element())->animatedSMILStyleProperties())
- return 0;
- // Ids stop style sharing if they show up in the stylesheets.
- if (context.element()->hasID() && m_features.idsInRules.contains(context.element()->idForStyleResolution().impl()))
- return 0;
- // Active and hovered elements always make a chain towards the document node
- // and no siblings or cousins will have the same state.
- if (context.element()->hovered())
- return 0;
- if (context.element()->active())
- return 0;
- // There is always only one focused element.
- if (context.element()->focused())
- return 0;
- if (parentElementPreventsSharing(context.element()->parentElement()))
- return 0;
- if (context.element()->hasScopedHTMLStyleChild())
- return 0;
- if (context.element() == context.document().cssTarget())
- return 0;
- if (elementHasDirectionAuto(context.element()))
- return 0;
- if (context.element()->hasActiveAnimations())
- return 0;
- // When a dialog is first shown, its style is mutated to center it in the
- // viewport. So the styles can't be shared since the viewport position and
- // size may be different each time a dialog is opened.
- if (context.element()->hasTagName(dialogTag))
- return 0;
- if (isShadowHost(context.element()) && context.element()->shadow()->containsActiveStyles())
+ if (!m_styleResolver->supportsStyleSharing(context.element()))
return 0;
STYLE_STATS_ADD_ELEMENT_ELIGIBLE_FOR_SHARING();
@@ -369,17 +310,7 @@ RenderStyle* SharedStyleFinder::locateSharedStyle(const ElementResolveContext& c
// FIXME: This should be an explicit out parameter, instead of a member variable.
m_elementAffectedByClassRules = context.element() && context.element()->hasClass() && classNamesAffectedByRules(context.element()->classNames());
- // Check previous siblings and their cousins.
- unsigned count = 0;
- unsigned visitedNodeCount = 0;
- Element* shareElement = 0;
- Node* cousinList = context.element()->previousSibling();
- while (cousinList) {
- shareElement = findSiblingForStyleSharing(context, cousinList, count);
- if (shareElement)
- break;
- cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
- }
+ Element* shareElement = findElementForStyleSharing(context);
#ifdef STYLE_STATS
// FIXME: these stats don't to into account whether or not sibling/attribute
« 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