Title: [143686] trunk/Source/WebCore
Revision
143686
Author
[email protected]
Date
2013-02-21 21:15:35 -0800 (Thu, 21 Feb 2013)

Log Message

Split SelectorChecker's fast-checking logic into its own class.
https://bugs.webkit.org/show_bug.cgi?id=106860

Reviewed by Antti Koivisto.

No functional changes, covered by existing tests.

* CMakeLists.txt: Added new class to existing build system.
* GNUmakefile.list.am: Ditto.
* Target.pri: Ditto.
* WebCore.gypi: Ditto.
* WebCore.xcodeproj/project.pbxproj: Ditto.
* css/CSSAllInOne.cpp: Ditto.
* css/RuleSet.cpp:
(WebCore::RuleData::RuleData): Changed to use SelectorCheckerFastPath.
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::matches): Ditto.
* css/SelectorChecker.h:
(SelectorChecker): Move fast path code into SelectorCheckerFastPath.
* css/SelectorCheckerFastPath.cpp: Added.
* css/SelectorCheckerFastPath.h: Added.
* css/StyleResolver.cpp:
(WebCore::StyleResolver::ruleMatches): Changed to use SelectorCheckerFastPath.
* dom/SelectorQuery.cpp:
(WebCore::SelectorDataList::initialize): Ditto.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/CMakeLists.txt (143685 => 143686)


--- trunk/Source/WebCore/CMakeLists.txt	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/CMakeLists.txt	2013-02-22 05:15:35 UTC (rev 143686)
@@ -1087,6 +1087,7 @@
     css/RuleSet.h
     css/RuleSet.cpp
     css/SelectorChecker.cpp
+    css/SelectorCheckerFastPath.cpp
     css/SelectorFilter.cpp
     css/ShadowValue.cpp
     css/StyleBuilder.cpp

Modified: trunk/Source/WebCore/ChangeLog (143685 => 143686)


--- trunk/Source/WebCore/ChangeLog	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/ChangeLog	2013-02-22 05:15:35 UTC (rev 143686)
@@ -1,3 +1,31 @@
+2013-02-21  Dimitri Glazkov  <[email protected]>
+
+        Split SelectorChecker's fast-checking logic into its own class.
+        https://bugs.webkit.org/show_bug.cgi?id=106860
+
+        Reviewed by Antti Koivisto.
+
+        No functional changes, covered by existing tests.
+
+        * CMakeLists.txt: Added new class to existing build system.
+        * GNUmakefile.list.am: Ditto.
+        * Target.pri: Ditto.
+        * WebCore.gypi: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * css/CSSAllInOne.cpp: Ditto.
+        * css/RuleSet.cpp:
+        (WebCore::RuleData::RuleData): Changed to use SelectorCheckerFastPath.
+        * css/SelectorChecker.cpp:
+        (WebCore::SelectorChecker::matches): Ditto.
+        * css/SelectorChecker.h:
+        (SelectorChecker): Move fast path code into SelectorCheckerFastPath.
+        * css/SelectorCheckerFastPath.cpp: Added.
+        * css/SelectorCheckerFastPath.h: Added.
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::ruleMatches): Changed to use SelectorCheckerFastPath.
+        * dom/SelectorQuery.cpp:
+        (WebCore::SelectorDataList::initialize): Ditto.
+
 2013-02-21  Tony Gentilcore  <[email protected]>
 
         Invalidate outstanding checkpoints for the background input stream and preload scanner

Modified: trunk/Source/WebCore/GNUmakefile.list.am (143685 => 143686)


--- trunk/Source/WebCore/GNUmakefile.list.am	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2013-02-22 05:15:35 UTC (rev 143686)
@@ -2690,6 +2690,8 @@
 	Source/WebCore/css/RuleSet.h \
 	Source/WebCore/css/SelectorChecker.cpp \
 	Source/WebCore/css/SelectorChecker.h \
+	Source/WebCore/css/SelectorCheckerFastPath.cpp \
+	Source/WebCore/css/SelectorCheckerFastPath.h \
 	Source/WebCore/css/SelectorFilter.cpp \
 	Source/WebCore/css/SelectorFilter.h \
 	Source/WebCore/css/ShadowValue.cpp \

Modified: trunk/Source/WebCore/Target.pri (143685 => 143686)


--- trunk/Source/WebCore/Target.pri	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/Target.pri	2013-02-22 05:15:35 UTC (rev 143686)
@@ -324,6 +324,7 @@
     css/RuleFeature.cpp \
     css/RuleSet.cpp \
     css/SelectorChecker.cpp \
+    css/SelectorCheckerFastPath.cpp \
     css/SelectorFilter.cpp \
     css/ShadowValue.cpp \
     css/StyleBuilder.cpp \

Modified: trunk/Source/WebCore/WebCore.gypi (143685 => 143686)


--- trunk/Source/WebCore/WebCore.gypi	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/WebCore.gypi	2013-02-22 05:15:35 UTC (rev 143686)
@@ -1590,6 +1590,8 @@
             'css/SVGCSSStyleSelector.cpp',
             'css/SelectorChecker.cpp',
             'css/SelectorChecker.h',
+            'css/SelectorCheckerFastPath.cpp',
+            'css/SelectorCheckerFastPath.h',
             'css/SelectorFilter.cpp',
             'css/SelectorFilter.h',
             'css/ShadowValue.cpp',

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (143685 => 143686)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2013-02-22 05:15:35 UTC (rev 143686)
@@ -1099,6 +1099,8 @@
 		419BC2DF1685329900D64D6D /* VisitedLinkState.h in Headers */ = {isa = PBXBuildFile; fileRef = 419BC2DD1685329900D64D6D /* VisitedLinkState.h */; };
 		41A3D58E101C152D00316D07 /* DedicatedWorkerThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41A3D58C101C152D00316D07 /* DedicatedWorkerThread.cpp */; };
 		41A3D58F101C152D00316D07 /* DedicatedWorkerThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 41A3D58D101C152D00316D07 /* DedicatedWorkerThread.h */; };
+		41B8CD4516D04591000E8CC0 /* SelectorCheckerFastPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41B8CD4316D04591000E8CC0 /* SelectorCheckerFastPath.cpp */; };
+		41B8CD4616D04591000E8CC0 /* SelectorCheckerFastPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 41B8CD4416D04591000E8CC0 /* SelectorCheckerFastPath.h */; };
 		41BF700B0FE86F49005E8DEC /* MessagePortChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41BF70090FE86F49005E8DEC /* MessagePortChannel.cpp */; };
 		41BF700C0FE86F49005E8DEC /* MessagePortChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 41BF700A0FE86F49005E8DEC /* MessagePortChannel.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		41BF700F0FE86F61005E8DEC /* PlatformMessagePortChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41BF700D0FE86F61005E8DEC /* PlatformMessagePortChannel.cpp */; };
@@ -8478,6 +8480,8 @@
 		419BC2DD1685329900D64D6D /* VisitedLinkState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisitedLinkState.h; sourceTree = "<group>"; };
 		41A3D58C101C152D00316D07 /* DedicatedWorkerThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DedicatedWorkerThread.cpp; path = workers/DedicatedWorkerThread.cpp; sourceTree = "<group>"; };
 		41A3D58D101C152D00316D07 /* DedicatedWorkerThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DedicatedWorkerThread.h; path = workers/DedicatedWorkerThread.h; sourceTree = "<group>"; };
+		41B8CD4316D04591000E8CC0 /* SelectorCheckerFastPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorCheckerFastPath.cpp; sourceTree = "<group>"; };
+		41B8CD4416D04591000E8CC0 /* SelectorCheckerFastPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorCheckerFastPath.h; sourceTree = "<group>"; };
 		41BF70090FE86F49005E8DEC /* MessagePortChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessagePortChannel.cpp; sourceTree = "<group>"; };
 		41BF700A0FE86F49005E8DEC /* MessagePortChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortChannel.h; sourceTree = "<group>"; };
 		41BF700D0FE86F61005E8DEC /* PlatformMessagePortChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformMessagePortChannel.cpp; path = default/PlatformMessagePortChannel.cpp; sourceTree = "<group>"; };
@@ -22104,6 +22108,8 @@
 				A79BADA0161E7F3F00C2E652 /* RuleSet.h */,
 				E44B4BB1141650D7002B1D8B /* SelectorChecker.cpp */,
 				E44B4BB2141650D7002B1D8B /* SelectorChecker.h */,
+				41B8CD4316D04591000E8CC0 /* SelectorCheckerFastPath.cpp */,
+				41B8CD4416D04591000E8CC0 /* SelectorCheckerFastPath.h */,
 				415071551685067300C3C7B3 /* SelectorFilter.cpp */,
 				415071561685067300C3C7B3 /* SelectorFilter.h */,
 				A80E6CCA0A1989CA007FB8C5 /* ShadowValue.cpp */,
@@ -26601,6 +26607,7 @@
 				977E2E0F12F0FC9C00C13379 /* XSSAuditor.h in Headers */,
 				977E2E0F12F0FC9C00C13380 /* XSSAuditorDelegate.h in Headers */,
 				FD537353137B651800008DCE /* ZeroPole.h in Headers */,
+				41B8CD4616D04591000E8CC0 /* SelectorCheckerFastPath.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -29795,6 +29802,7 @@
 				977E2E0E12F0FC9C00C13379 /* XSSAuditor.cpp in Sources */,
 				977E2E0E12F0FC9C00C13380 /* XSSAuditorDelegate.cpp in Sources */,
 				FD537352137B651800008DCE /* ZeroPole.cpp in Sources */,
+				41B8CD4516D04591000E8CC0 /* SelectorCheckerFastPath.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/WebCore/css/CSSAllInOne.cpp (143685 => 143686)


--- trunk/Source/WebCore/css/CSSAllInOne.cpp	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/css/CSSAllInOne.cpp	2013-02-22 05:15:35 UTC (rev 143686)
@@ -74,6 +74,7 @@
 #include "InspectorCSSOMWrappers.cpp"
 #include "RuleFeature.cpp"
 #include "RuleSet.cpp"
+#include "SelectorCheckerFastPath.cpp"
 #include "SelectorFilter.cpp"
 #include "StyleBuilder.cpp"
 #include "StylePropertySet.cpp"

Modified: trunk/Source/WebCore/css/RuleSet.cpp (143685 => 143686)


--- trunk/Source/WebCore/css/RuleSet.cpp	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/css/RuleSet.cpp	2013-02-22 05:15:35 UTC (rev 143686)
@@ -36,6 +36,7 @@
 #include "MediaQueryEvaluator.h"
 #include "SecurityOrigin.h"
 #include "SelectorChecker.h"
+#include "SelectorCheckerFastPath.h"
 #include "SelectorFilter.h"
 #include "StyleResolver.h"
 #include "StyleRule.h"
@@ -135,7 +136,7 @@
     : m_rule(rule)
     , m_selectorIndex(selectorIndex)
     , m_position(position)
-    , m_hasFastCheckableSelector((addRuleFlags & RuleCanUseFastCheckSelector) && SelectorChecker::isFastCheckableSelector(selector()))
+    , m_hasFastCheckableSelector((addRuleFlags & RuleCanUseFastCheckSelector) && SelectorCheckerFastPath::canUse(selector()))
     , m_specificity(selector()->specificity())
     , m_hasMultipartSelector(!!selector()->tagHistory())
     , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector()))

Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (143685 => 143686)


--- trunk/Source/WebCore/css/SelectorChecker.cpp	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp	2013-02-22 05:15:35 UTC (rev 143686)
@@ -50,6 +50,7 @@
 #include "RenderStyle.h"
 #include "ScrollableArea.h"
 #include "ScrollbarTheme.h"
+#include "SelectorCheckerFastPath.h"
 #include "ShadowRoot.h"
 #include "SiblingTraversalStrategies.h"
 #include "StyledElement.h"
@@ -73,173 +74,16 @@
 bool SelectorChecker::matches(const CSSSelector* selector, Element* element, bool isFastCheckableSelector) const
 {
     if (isFastCheckableSelector && !element->isSVGElement()) {
-        if (!fastCheckRightmostSelector(selector, element, VisitedMatchDisabled))
+        SelectorCheckerFastPath selectorCheckerFastPath(selector, element);
+        if (!selectorCheckerFastPath.matchesRightmostSelector(VisitedMatchDisabled))
             return false;
-        return fastCheck(selector, element);
+        return selectorCheckerFastPath.matches();
     }
 
     PseudoId ignoreDynamicPseudo = NOPSEUDO;
     return match(SelectorCheckingContext(selector, element, SelectorChecker::VisitedMatchDisabled), ignoreDynamicPseudo, DOMSiblingTraversalStrategy()) == SelectorMatches;
 }
 
-namespace {
-
-template <bool checkValue(const Element*, const CSSSelector*)>
-inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement)
-{
-    for (; element; element = element->parentElement()) {
-        if (checkValue(element, selector)) {
-            if (selector->relation() == CSSSelector::Descendant)
-                topChildOrSubselector = 0;
-            else if (!topChildOrSubselector) {
-                ASSERT(selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector);
-                topChildOrSubselector = selector;
-                topChildOrSubselectorMatchElement = element;
-            }
-            if (selector->relation() != CSSSelector::SubSelector)
-                element = element->parentElement();
-            selector = selector->tagHistory();
-            return true;
-        }
-        if (topChildOrSubselector) {
-            // Child or subselector check failed.
-            // If the match element is null, topChildOrSubselector was also the very topmost selector and had to match
-            // the original element we were checking.
-            if (!topChildOrSubselectorMatchElement)
-                return false;
-            // There may be other matches down the ancestor chain.
-            // Rewind to the topmost child or subselector and the element it matched, continue checking ancestors.
-            selector = topChildOrSubselector;
-            element = topChildOrSubselectorMatchElement->parentElement();
-            topChildOrSubselector = 0;
-            return true;
-        }
-    }
-    return false;
-}
-
-inline bool checkClassValue(const Element* element, const CSSSelector* selector)
-{
-    return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains(selector->value().impl());
-}
-
-inline bool checkIDValue(const Element* element, const CSSSelector* selector)
-{
-    return element->hasID() && element->idForStyleResolution().impl() == selector->value().impl();
-}
-
-inline bool checkExactAttributeValue(const Element* element, const CSSSelector* selector)
-{
-    return SelectorChecker::checkExactAttribute(element, selector->attribute(), selector->value().impl());
-}
-
-inline bool checkTagValue(const Element* element, const CSSSelector* selector)
-{
-    return SelectorChecker::tagMatches(element, selector->tagQName());
-}
-
-}
-
-bool SelectorChecker::fastCheckRightmostSelector(const CSSSelector* selector, const Element* element, SelectorChecker::VisitedMatchType visitedMatchType)
-{
-    ASSERT(SelectorChecker::isFastCheckableSelector(selector));
-
-    switch (selector->m_match) {
-    case CSSSelector::Tag:
-        return checkTagValue(element, selector);
-    case CSSSelector::Class:
-        return checkClassValue(element, selector);
-    case CSSSelector::Id:
-        return checkIDValue(element, selector);
-    case CSSSelector::Exact:
-    case CSSSelector::Set:
-        return checkExactAttributeValue(element, selector);
-    case CSSSelector::PseudoClass:
-        return commonPseudoClassSelectorMatches(element, selector, visitedMatchType);
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    return false;
-}
-
-bool SelectorChecker::fastCheck(const CSSSelector* selector, const Element* element)
-{
-    ASSERT(fastCheckRightmostSelector(selector, element, VisitedMatchEnabled));
-
-    const CSSSelector* topChildOrSubselector = 0;
-    const Element* topChildOrSubselectorMatchElement = 0;
-    if (selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector)
-        topChildOrSubselector = selector;
-
-    if (selector->relation() != CSSSelector::SubSelector)
-        element = element->parentElement();
-
-    selector = selector->tagHistory();
-
-    // We know this compound selector has descendant, child and subselector combinators only and all components are simple.
-    while (selector) {
-        switch (selector->m_match) {
-        case CSSSelector::Class:
-            if (!fastCheckSingleSelector<checkClassValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
-                return false;
-            break;
-        case CSSSelector::Id:
-            if (!fastCheckSingleSelector<checkIDValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
-                return false;
-            break;
-        case CSSSelector::Tag:
-            if (!fastCheckSingleSelector<checkTagValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
-                return false;
-            break;
-        case CSSSelector::Set:
-        case CSSSelector::Exact:
-            if (!fastCheckSingleSelector<checkExactAttributeValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
-                return false;
-            break;
-        default:
-            ASSERT_NOT_REACHED();
-        }
-    }
-    return true;
-}
-
-static inline bool isFastCheckableRelation(CSSSelector::Relation relation)
-{
-    return relation == CSSSelector::Descendant || relation == CSSSelector::Child || relation == CSSSelector::SubSelector;
-}
-
-static inline bool isFastCheckableMatch(const CSSSelector* selector)
-{
-    if (selector->m_match == CSSSelector::Set) {
-        // Style attribute is generated lazily but the fast path doesn't trigger it.
-        // Disallow them here rather than making the fast path more branchy.
-        return selector->attribute() != styleAttr;
-    }
-    if (selector->m_match == CSSSelector::Exact)
-        return selector->attribute() != styleAttr && HTMLDocument::isCaseSensitiveAttribute(selector->attribute());
-    return selector->m_match == CSSSelector::Tag || selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;
-}
-
-static inline bool isFastCheckableRightmostSelector(const CSSSelector* selector)
-{
-    if (!isFastCheckableRelation(selector->relation()))
-        return false;
-    return isFastCheckableMatch(selector) || SelectorChecker::isCommonPseudoClassSelector(selector);
-}
-
-bool SelectorChecker::isFastCheckableSelector(const CSSSelector* selector)
-{
-    if (!isFastCheckableRightmostSelector(selector))
-        return false;
-    for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) {
-        if (!isFastCheckableRelation(selector->relation()))
-            return false;
-        if (!isFastCheckableMatch(selector))
-            return false;
-    }
-    return true;
-}
-
 // Recursive check of selectors and combinators
 // It can return 4 different values:
 // * SelectorMatches          - the selector matches the element e
@@ -1023,23 +867,6 @@
     }
 }
 
-bool SelectorChecker::commonPseudoClassSelectorMatches(const Element* element, const CSSSelector* selector, VisitedMatchType visitedMatchType)
-{
-    ASSERT(isCommonPseudoClassSelector(selector));
-    switch (selector->pseudoType()) {
-    case CSSSelector::PseudoLink:
-    case CSSSelector::PseudoAnyLink:
-        return element->isLink();
-    case CSSSelector::PseudoVisited:
-        return element->isLink() && visitedMatchType == VisitedMatchEnabled;
-    case CSSSelector::PseudoFocus:
-        return matchesFocusPseudoClass(element);
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    return true;
-}
-
 unsigned SelectorChecker::determineLinkMatchType(const CSSSelector* selector)
 {
     unsigned linkMatchType = MatchAll;

Modified: trunk/Source/WebCore/css/SelectorChecker.h (143685 => 143686)


--- trunk/Source/WebCore/css/SelectorChecker.h	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/css/SelectorChecker.h	2013-02-22 05:15:35 UTC (rev 143686)
@@ -83,9 +83,6 @@
     template<typename SiblingTraversalStrategy>
     bool checkOne(const SelectorCheckingContext&, const SiblingTraversalStrategy&) const;
 
-    static bool isFastCheckableSelector(const CSSSelector*);
-    static bool fastCheck(const CSSSelector*, const Element*);
-
     bool strictParsing() const { return m_strictParsing; }
 
     Mode mode() const { return m_mode; }
@@ -93,7 +90,6 @@
     static bool tagMatches(const Element*, const QualifiedName&);
     static bool isCommonPseudoClassSelector(const CSSSelector*);
     static bool matchesFocusPseudoClass(const Element*);
-    static bool fastCheckRightmostAttributeSelector(const Element*, const CSSSelector*);
     static bool checkExactAttribute(const Element*, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value);
 
     enum LinkMatchMask { MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited };
@@ -104,9 +100,6 @@
 
     static bool isFrameFocused(const Element*);
 
-    static bool fastCheckRightmostSelector(const CSSSelector*, const Element*, VisitedMatchType);
-    static bool commonPseudoClassSelectorMatches(const Element*, const CSSSelector*, VisitedMatchType);
-
     bool m_strictParsing;
     bool m_documentIsHTML;
     Mode m_mode;
@@ -147,14 +140,6 @@
     return false;
 }
 
-inline bool SelectorChecker::fastCheckRightmostAttributeSelector(const Element* element, const CSSSelector* selector)
-{
-    if (selector->m_match == CSSSelector::Exact || selector->m_match == CSSSelector::Set)
-        return checkExactAttribute(element, selector->attribute(), selector->value().impl());
-    ASSERT(!selector->isAttributeSelector());
-    return true;
 }
 
-}
-
 #endif

Added: trunk/Source/WebCore/css/SelectorCheckerFastPath.cpp (0 => 143686)


--- trunk/Source/WebCore/css/SelectorCheckerFastPath.cpp	                        (rev 0)
+++ trunk/Source/WebCore/css/SelectorCheckerFastPath.cpp	2013-02-22 05:15:35 UTC (rev 143686)
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2004-2005 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2006, 2007 Nicholas Shanks ([email protected])
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ * Copyright (C) 2007, 2008 Eric Seidel <[email protected]>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "SelectorCheckerFastPath.h"
+
+#include "HTMLDocument.h"
+#include "HTMLNames.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+namespace {
+
+template <bool checkValue(const Element*, const CSSSelector*)>
+inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement)
+{
+    for (; element; element = element->parentElement()) {
+        if (checkValue(element, selector)) {
+            if (selector->relation() == CSSSelector::Descendant)
+                topChildOrSubselector = 0;
+            else if (!topChildOrSubselector) {
+                ASSERT(selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector);
+                topChildOrSubselector = selector;
+                topChildOrSubselectorMatchElement = element;
+            }
+            if (selector->relation() != CSSSelector::SubSelector)
+                element = element->parentElement();
+            selector = selector->tagHistory();
+            return true;
+        }
+        if (topChildOrSubselector) {
+            // Child or subselector check failed.
+            // If the match element is null, topChildOrSubselector was also the very topmost selector and had to match
+            // the original element we were checking.
+            if (!topChildOrSubselectorMatchElement)
+                return false;
+            // There may be other matches down the ancestor chain.
+            // Rewind to the topmost child or subselector and the element it matched, continue checking ancestors.
+            selector = topChildOrSubselector;
+            element = topChildOrSubselectorMatchElement->parentElement();
+            topChildOrSubselector = 0;
+            return true;
+        }
+    }
+    return false;
+}
+
+inline bool checkClassValue(const Element* element, const CSSSelector* selector)
+{
+    return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains(selector->value().impl());
+}
+
+inline bool checkIDValue(const Element* element, const CSSSelector* selector)
+{
+    return element->hasID() && element->idForStyleResolution().impl() == selector->value().impl();
+}
+
+inline bool checkExactAttributeValue(const Element* element, const CSSSelector* selector)
+{
+    return SelectorChecker::checkExactAttribute(element, selector->attribute(), selector->value().impl());
+}
+
+inline bool checkTagValue(const Element* element, const CSSSelector* selector)
+{
+    return SelectorChecker::tagMatches(element, selector->tagQName());
+}
+
+}
+
+SelectorCheckerFastPath::SelectorCheckerFastPath(const CSSSelector* selector, const Element* element)
+    : m_selector(selector)
+    , m_element(element)
+{
+}
+
+bool SelectorCheckerFastPath::matchesRightmostSelector(SelectorChecker::VisitedMatchType visitedMatchType) const
+{
+    ASSERT(SelectorCheckerFastPath::canUse(m_selector));
+
+    switch (m_selector->m_match) {
+    case CSSSelector::Tag:
+        return checkTagValue(m_element, m_selector);
+    case CSSSelector::Class:
+        return checkClassValue(m_element, m_selector);
+    case CSSSelector::Id:
+        return checkIDValue(m_element, m_selector);
+    case CSSSelector::Exact:
+    case CSSSelector::Set:
+        return checkExactAttributeValue(m_element, m_selector);
+    case CSSSelector::PseudoClass:
+        return commonPseudoClassSelectorMatches(visitedMatchType);
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return false;
+}
+
+bool SelectorCheckerFastPath::matches() const
+{
+    ASSERT(matchesRightmostSelector(SelectorChecker::VisitedMatchEnabled));
+    const CSSSelector* selector = m_selector;
+    const Element* element = m_element;
+
+    const CSSSelector* topChildOrSubselector = 0;
+    const Element* topChildOrSubselectorMatchElement = 0;
+    if (selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector)
+        topChildOrSubselector = selector;
+
+    if (selector->relation() != CSSSelector::SubSelector)
+        element = element->parentElement();
+
+    selector = selector->tagHistory();
+
+    // We know this compound selector has descendant, child and subselector combinators only and all components are simple.
+    while (selector) {
+        switch (selector->m_match) {
+        case CSSSelector::Class:
+            if (!fastCheckSingleSelector<checkClassValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
+                return false;
+            break;
+        case CSSSelector::Id:
+            if (!fastCheckSingleSelector<checkIDValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
+                return false;
+            break;
+        case CSSSelector::Tag:
+            if (!fastCheckSingleSelector<checkTagValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
+                return false;
+            break;
+        case CSSSelector::Set:
+        case CSSSelector::Exact:
+            if (!fastCheckSingleSelector<checkExactAttributeValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
+                return false;
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+    return true;
+}
+
+static inline bool isFastCheckableRelation(CSSSelector::Relation relation)
+{
+    return relation == CSSSelector::Descendant || relation == CSSSelector::Child || relation == CSSSelector::SubSelector;
+}
+
+static inline bool isFastCheckableMatch(const CSSSelector* selector)
+{
+    if (selector->m_match == CSSSelector::Set) {
+        // Style attribute is generated lazily but the fast path doesn't trigger it.
+        // Disallow them here rather than making the fast path more branchy.
+        return selector->attribute() != styleAttr;
+    }
+    if (selector->m_match == CSSSelector::Exact)
+        return selector->attribute() != styleAttr && HTMLDocument::isCaseSensitiveAttribute(selector->attribute());
+    return selector->m_match == CSSSelector::Tag || selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;
+}
+
+static inline bool isFastCheckableRightmostSelector(const CSSSelector* selector)
+{
+    if (!isFastCheckableRelation(selector->relation()))
+        return false;
+    return isFastCheckableMatch(selector) || SelectorChecker::isCommonPseudoClassSelector(selector);
+}
+
+bool SelectorCheckerFastPath::canUse(const CSSSelector* selector)
+{
+    if (!isFastCheckableRightmostSelector(selector))
+        return false;
+    for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) {
+        if (!isFastCheckableRelation(selector->relation()))
+            return false;
+        if (!isFastCheckableMatch(selector))
+            return false;
+    }
+    return true;
+}
+
+bool SelectorCheckerFastPath::commonPseudoClassSelectorMatches(SelectorChecker::VisitedMatchType visitedMatchType) const
+{
+    ASSERT(SelectorChecker::isCommonPseudoClassSelector(m_selector));
+    switch (m_selector->pseudoType()) {
+    case CSSSelector::PseudoLink:
+    case CSSSelector::PseudoAnyLink:
+        return m_element->isLink();
+    case CSSSelector::PseudoVisited:
+        return m_element->isLink() && visitedMatchType == SelectorChecker::VisitedMatchEnabled;
+    case CSSSelector::PseudoFocus:
+        return SelectorChecker::matchesFocusPseudoClass(m_element);
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return true;
+}
+
+
+}

Added: trunk/Source/WebCore/css/SelectorCheckerFastPath.h (0 => 143686)


--- trunk/Source/WebCore/css/SelectorCheckerFastPath.h	                        (rev 0)
+++ trunk/Source/WebCore/css/SelectorCheckerFastPath.h	2013-02-22 05:15:35 UTC (rev 143686)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ *           (C) 2004-2005 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2006, 2007 Nicholas Shanks ([email protected])
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ * Copyright (C) 2007, 2008 Eric Seidel <[email protected]>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SelectorCheckerFastPath_h
+#define SelectorCheckerFastPath_h
+
+#include "CSSSelector.h"
+#include "SelectorChecker.h"
+
+namespace WebCore {
+
+class SelectorCheckerFastPath {
+public:
+    SelectorCheckerFastPath(const CSSSelector*, const Element*);
+
+    bool matches() const;
+    bool matchesRightmostSelector(SelectorChecker::VisitedMatchType) const;
+    bool matchesRightmostAttributeSelector() const;
+
+    static bool canUse(const CSSSelector*);
+
+private:
+    bool commonPseudoClassSelectorMatches(SelectorChecker::VisitedMatchType) const;
+
+    const CSSSelector* m_selector;
+    const Element* m_element;
+};
+
+inline bool SelectorCheckerFastPath::matchesRightmostAttributeSelector() const
+{
+    if (m_selector->m_match == CSSSelector::Exact || m_selector->m_match == CSSSelector::Set)
+        return SelectorChecker::checkExactAttribute(m_element, m_selector->attribute(), m_selector->value().impl());
+    ASSERT(!m_selector->isAttributeSelector());
+    return true;
+}
+
+}
+
+#endif

Modified: trunk/Source/WebCore/css/StyleResolver.cpp (143685 => 143686)


--- trunk/Source/WebCore/css/StyleResolver.cpp	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/css/StyleResolver.cpp	2013-02-22 05:15:35 UTC (rev 143686)
@@ -103,6 +103,7 @@
 #include "SVGFontFaceElement.h"
 #include "ScaleTransformOperation.h"
 #include "SecurityOrigin.h"
+#include "SelectorCheckerFastPath.h"
 #include "Settings.h"
 #include "ShadowData.h"
 #include "ShadowRoot.h"
@@ -2084,10 +2085,11 @@
         }
         if (ruleData.selector()->m_match == CSSSelector::Tag && !SelectorChecker::tagMatches(state.element(), ruleData.selector()->tagQName()))
             return false;
-        if (!SelectorChecker::fastCheckRightmostAttributeSelector(state.element(), ruleData.selector()))
+        SelectorCheckerFastPath selectorCheckerFastPath(ruleData.selector(), state.element());
+        if (!selectorCheckerFastPath.matchesRightmostAttributeSelector())
             return false;
 
-        return SelectorChecker::fastCheck(ruleData.selector(), state.element());
+        return selectorCheckerFastPath.matches();
     }
 
     // Slow path.

Modified: trunk/Source/WebCore/dom/SelectorQuery.cpp (143685 => 143686)


--- trunk/Source/WebCore/dom/SelectorQuery.cpp	2013-02-22 04:03:41 UTC (rev 143685)
+++ trunk/Source/WebCore/dom/SelectorQuery.cpp	2013-02-22 05:15:35 UTC (rev 143686)
@@ -30,6 +30,7 @@
 #include "CSSSelectorList.h"
 #include "Document.h"
 #include "SelectorChecker.h"
+#include "SelectorCheckerFastPath.h"
 #include "StaticNodeList.h"
 #include "StyledElement.h"
 
@@ -45,7 +46,7 @@
 
     m_selectors.reserveInitialCapacity(selectorCount);
     for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
-        m_selectors.uncheckedAppend(SelectorData(selector, SelectorChecker::isFastCheckableSelector(selector)));
+        m_selectors.uncheckedAppend(SelectorData(selector, SelectorCheckerFastPath::canUse(selector)));
 }
 
 bool SelectorDataList::matches(Element* targetElement) const
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to