Merge CheckingContexts from SelectorCompiler and SelectorChecker
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Sep 2014 10:12:53 +0000 (10:12 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Sep 2014 10:12:53 +0000 (10:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=135255

Reviewed by Benjamin Poulain.

In this patch, we merge SelectorChecker::SelectorCheckingContext and SelectorCompiler::CheckingContext.
We expose only SelectorChecker::CheckingContext. That is the same to the old SelectorCompiler::CheckingContext.

In SelectorChecker.cpp, we define SelectorChecker::CheckingContextWithStatus and use it internally.
And we move VisitedMatchType from SelectorChecker.h to SelectorChecker.cpp.

VisitedMatchType is also explicitly used by SelectorCheckerFastPath. However, SelectorCheckerFastPath is now
used only from SelectorQuery (Style resolution algorithm no longer uses it: r171059).
In this patch, we remove SelectorCheckerFastPath since the major cases are covered by CSS JIT.
In `RightMostWithIdMatch`, `Element#matches` and multiple selectors `querySelector('a, b')` cases,
CSS JIT is not used. So dropping fast path affects them. But 1) these cases are rare or 2) the target node
is typically only one since nodes are filtered before matching. So it doesn't have performance regression.

And now since CheckingContextWithStatus is the derived class of CheckingContext, we can use
the same test functions; template parameter is not necessary. It reduces code size.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSAllInOne.cpp:
* css/ElementRuleCollector.cpp:
(WebCore::ElementRuleCollector::ruleMatches):
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::CheckingContextWithStatus::CheckingContextWithStatus):
(WebCore::SelectorChecker::match):
(WebCore::checkingContextForParent):
(WebCore::SelectorChecker::matchRecursively):
(WebCore::canMatchHoverOrActiveInQuirksMode):
(WebCore::SelectorChecker::checkOne):
(WebCore::SelectorChecker::checkScrollbarPseudoClass):
* css/SelectorChecker.h:
(WebCore::SelectorChecker::CheckingContext::CheckingContext):
(WebCore::SelectorChecker::SelectorCheckingContext::SelectorCheckingContext): Deleted.
* css/SelectorCheckerFastPath.cpp: Removed.
* css/SelectorCheckerFastPath.h: Removed.
* css/SelectorCheckerTestFunctions.h:
(WebCore::scrollbarMatchesEnabledPseudoClass):
(WebCore::scrollbarMatchesDisabledPseudoClass):
(WebCore::scrollbarMatchesHoverPseudoClass):
(WebCore::scrollbarMatchesActivePseudoClass):
(WebCore::scrollbarMatchesHorizontalPseudoClass):
(WebCore::scrollbarMatchesVerticalPseudoClass):
(WebCore::scrollbarMatchesDecrementPseudoClass):
(WebCore::scrollbarMatchesIncrementPseudoClass):
(WebCore::scrollbarMatchesStartPseudoClass):
(WebCore::scrollbarMatchesEndPseudoClass):
(WebCore::scrollbarMatchesDoubleButtonPseudoClass):
(WebCore::scrollbarMatchesSingleButtonPseudoClass):
(WebCore::scrollbarMatchesNoButtonPseudoClass):
(WebCore::scrollbarMatchesCornerPresentPseudoClass):
* css/StyleResolver.h:
(WebCore::checkRegionSelector):
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorFragment::appendUnoptimizedPseudoClassWithContext):
(WebCore::SelectorCompiler::addScrollbarPseudoClassType):
(WebCore::SelectorCompiler::SelectorCodeGenerator::addFlagsToElementStyleFromContext):
(WebCore::SelectorCompiler::SelectorCodeGenerator::branchOnResolvingModeWithCheckingContext):
(WebCore::SelectorCompiler::elementIsActiveForStyleResolution):
(WebCore::SelectorCompiler::setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary):
(WebCore::SelectorCompiler::elementIsHoveredForStyleResolution):
(WebCore::SelectorCompiler::makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown):
(WebCore::SelectorCompiler::makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateRequestedPseudoElementEqualsToSelectorPseudoElement):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsScopeRoot):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateMarkPseudoStyleForPseudoElement):
* cssjit/SelectorCompiler.h:
(WebCore::SelectorCompiler::CheckingContext::CheckingContext): Deleted.
* dom/SelectorQuery.cpp:
(WebCore::SelectorDataList::SelectorDataList):
(WebCore::SelectorDataList::selectorMatches):
(WebCore::SelectorDataList::executeCompiledSelectorCheckerWithCheckingContext):
(WebCore::isCompiledSelector):
(WebCore::SelectorDataList::compileSelector):
(WebCore::SelectorDataList::execute):
* dom/SelectorQuery.h:
(WebCore::SelectorDataList::SelectorData::SelectorData):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@173457 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSAllInOne.cpp
Source/WebCore/css/ElementRuleCollector.cpp
Source/WebCore/css/SelectorChecker.cpp
Source/WebCore/css/SelectorChecker.h
Source/WebCore/css/SelectorCheckerFastPath.cpp [deleted file]
Source/WebCore/css/SelectorCheckerFastPath.h [deleted file]
Source/WebCore/css/SelectorCheckerTestFunctions.h
Source/WebCore/css/StyleResolver.h
Source/WebCore/cssjit/SelectorCompiler.cpp
Source/WebCore/cssjit/SelectorCompiler.h
Source/WebCore/dom/SelectorQuery.cpp
Source/WebCore/dom/SelectorQuery.h

index b24f20a..b46cec3 100644 (file)
@@ -1302,7 +1302,6 @@ set(WebCore_SOURCES
     css/SVGCSSParser.cpp
     css/SVGCSSStyleSelector.cpp
     css/SelectorChecker.cpp
-    css/SelectorCheckerFastPath.cpp
     css/SelectorFilter.cpp
     css/SourceSizeList.cpp
     css/StyleInvalidationAnalysis.cpp
index bf6b6e4..39d760e 100644 (file)
@@ -1,3 +1,86 @@
+2014-09-10  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Merge CheckingContexts from SelectorCompiler and SelectorChecker
+        https://bugs.webkit.org/show_bug.cgi?id=135255
+
+        Reviewed by Benjamin Poulain.
+
+        In this patch, we merge SelectorChecker::SelectorCheckingContext and SelectorCompiler::CheckingContext.
+        We expose only SelectorChecker::CheckingContext. That is the same to the old SelectorCompiler::CheckingContext.
+
+        In SelectorChecker.cpp, we define SelectorChecker::CheckingContextWithStatus and use it internally.
+        And we move VisitedMatchType from SelectorChecker.h to SelectorChecker.cpp.
+
+        VisitedMatchType is also explicitly used by SelectorCheckerFastPath. However, SelectorCheckerFastPath is now
+        used only from SelectorQuery (Style resolution algorithm no longer uses it: r171059).
+        In this patch, we remove SelectorCheckerFastPath since the major cases are covered by CSS JIT.
+        In `RightMostWithIdMatch`, `Element#matches` and multiple selectors `querySelector('a, b')` cases,
+        CSS JIT is not used. So dropping fast path affects them. But 1) these cases are rare or 2) the target node
+        is typically only one since nodes are filtered before matching. So it doesn't have performance regression.
+
+        And now since CheckingContextWithStatus is the derived class of CheckingContext, we can use
+        the same test functions; template parameter is not necessary. It reduces code size.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSAllInOne.cpp:
+        * css/ElementRuleCollector.cpp:
+        (WebCore::ElementRuleCollector::ruleMatches):
+        * css/SelectorChecker.cpp:
+        (WebCore::SelectorChecker::CheckingContextWithStatus::CheckingContextWithStatus):
+        (WebCore::SelectorChecker::match):
+        (WebCore::checkingContextForParent):
+        (WebCore::SelectorChecker::matchRecursively):
+        (WebCore::canMatchHoverOrActiveInQuirksMode):
+        (WebCore::SelectorChecker::checkOne):
+        (WebCore::SelectorChecker::checkScrollbarPseudoClass):
+        * css/SelectorChecker.h:
+        (WebCore::SelectorChecker::CheckingContext::CheckingContext):
+        (WebCore::SelectorChecker::SelectorCheckingContext::SelectorCheckingContext): Deleted.
+        * css/SelectorCheckerFastPath.cpp: Removed.
+        * css/SelectorCheckerFastPath.h: Removed.
+        * css/SelectorCheckerTestFunctions.h:
+        (WebCore::scrollbarMatchesEnabledPseudoClass):
+        (WebCore::scrollbarMatchesDisabledPseudoClass):
+        (WebCore::scrollbarMatchesHoverPseudoClass):
+        (WebCore::scrollbarMatchesActivePseudoClass):
+        (WebCore::scrollbarMatchesHorizontalPseudoClass):
+        (WebCore::scrollbarMatchesVerticalPseudoClass):
+        (WebCore::scrollbarMatchesDecrementPseudoClass):
+        (WebCore::scrollbarMatchesIncrementPseudoClass):
+        (WebCore::scrollbarMatchesStartPseudoClass):
+        (WebCore::scrollbarMatchesEndPseudoClass):
+        (WebCore::scrollbarMatchesDoubleButtonPseudoClass):
+        (WebCore::scrollbarMatchesSingleButtonPseudoClass):
+        (WebCore::scrollbarMatchesNoButtonPseudoClass):
+        (WebCore::scrollbarMatchesCornerPresentPseudoClass):
+        * css/StyleResolver.h:
+        (WebCore::checkRegionSelector):
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorFragment::appendUnoptimizedPseudoClassWithContext):
+        (WebCore::SelectorCompiler::addScrollbarPseudoClassType):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::addFlagsToElementStyleFromContext):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::branchOnResolvingModeWithCheckingContext):
+        (WebCore::SelectorCompiler::elementIsActiveForStyleResolution):
+        (WebCore::SelectorCompiler::setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary):
+        (WebCore::SelectorCompiler::elementIsHoveredForStyleResolution):
+        (WebCore::SelectorCompiler::makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown):
+        (WebCore::SelectorCompiler::makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateRequestedPseudoElementEqualsToSelectorPseudoElement):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsScopeRoot):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateMarkPseudoStyleForPseudoElement):
+        * cssjit/SelectorCompiler.h:
+        (WebCore::SelectorCompiler::CheckingContext::CheckingContext): Deleted.
+        * dom/SelectorQuery.cpp:
+        (WebCore::SelectorDataList::SelectorDataList):
+        (WebCore::SelectorDataList::selectorMatches):
+        (WebCore::SelectorDataList::executeCompiledSelectorCheckerWithCheckingContext):
+        (WebCore::isCompiledSelector):
+        (WebCore::SelectorDataList::compileSelector):
+        (WebCore::SelectorDataList::execute):
+        * dom/SelectorQuery.h:
+        (WebCore::SelectorDataList::SelectorData::SelectorData):
+
 2014-09-09  Jer Noble  <jer.noble@apple.com>
 
         [MSE] http/tests/media/media-source/mediasource-config-change-mp4-v-bitrate.html failing after r173318
index 5be3d37..4fde70d 100644 (file)
                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 */; };
                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 */; };
                41BF70100FE86F61005E8DEC /* PlatformMessagePortChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 41BF700E0FE86F61005E8DEC /* PlatformMessagePortChannel.h */; };
                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>"; };
                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>"; };
                41BF700E0FE86F61005E8DEC /* PlatformMessagePortChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformMessagePortChannel.h; path = default/PlatformMessagePortChannel.h; sourceTree = "<group>"; };
                                A79BADA0161E7F3F00C2E652 /* RuleSet.h */,
                                E44B4BB1141650D7002B1D8B /* SelectorChecker.cpp */,
                                E44B4BB2141650D7002B1D8B /* SelectorChecker.h */,
-                               41B8CD4316D04591000E8CC0 /* SelectorCheckerFastPath.cpp */,
-                               41B8CD4416D04591000E8CC0 /* SelectorCheckerFastPath.h */,
                                432D3FE718A8658400D7DC03 /* SelectorCheckerTestFunctions.h */,
                                415071551685067300C3C7B3 /* SelectorFilter.cpp */,
                                415071561685067300C3C7B3 /* SelectorFilter.h */,
                                B2C3DA2F0D006C1D00EF6F26 /* SegmentedString.h in Headers */,
                                BEA807C90F714A0300524199 /* SelectionRect.h in Headers */,
                                E44B4BB4141650D7002B1D8B /* SelectorChecker.h in Headers */,
-                               41B8CD4616D04591000E8CC0 /* SelectorCheckerFastPath.h in Headers */,
                                432D3FE818A8658400D7DC03 /* SelectorCheckerTestFunctions.h in Headers */,
                                26B999971804D54200D01121 /* SelectorCompiler.h in Headers */,
                                415071581685067300C3C7B3 /* SelectorFilter.h in Headers */,
                                B2C3DA2E0D006C1D00EF6F26 /* SegmentedString.cpp in Sources */,
                                BEA807C80F714A0300524199 /* SelectionRect.cpp in Sources */,
                                E44B4BB3141650D7002B1D8B /* SelectorChecker.cpp in Sources */,
-                               41B8CD4516D04591000E8CC0 /* SelectorCheckerFastPath.cpp in Sources */,
                                26B999961804D54200D01121 /* SelectorCompiler.cpp in Sources */,
                                415071571685067300C3C7B3 /* SelectorFilter.cpp in Sources */,
                                E45322AB140CE267005A0F92 /* SelectorQuery.cpp in Sources */,
index ec08536..d5372e6 100644 (file)
@@ -81,7 +81,6 @@
 #include "PageRuleCollector.cpp"
 #include "RuleFeature.cpp"
 #include "RuleSet.cpp"
-#include "SelectorCheckerFastPath.cpp"
 #include "SelectorFilter.cpp"
 #include "StyleProperties.cpp"
 #include "StylePropertyShorthand.cpp"
index dad4a22..e88234d 100644 (file)
@@ -295,23 +295,28 @@ inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData)
         compiledSelectorChecker = ruleData.compiledSelectorCodeRef().code().executableAddress();
     }
 
-    if (compiledSelectorChecker) {
-        if (ruleData.compilationStatus() == SelectorCompilationStatus::SimpleSelectorChecker) {
-            SelectorCompiler::SimpleSelectorChecker selectorChecker = SelectorCompiler::simpleSelectorCheckerFunction(compiledSelectorChecker, ruleData.compilationStatus());
-            ASSERT_WITH_MESSAGE(!selectorChecker(&m_element) || m_pseudoStyleRequest.pseudoId == NOPSEUDO, "When matching pseudo elements, we should never compile a selector checker without context unless it cannot match anything.");
+    if (compiledSelectorChecker && ruleData.compilationStatus() == SelectorCompilationStatus::SimpleSelectorChecker) {
+        SelectorCompiler::SimpleSelectorChecker selectorChecker = SelectorCompiler::simpleSelectorCheckerFunction(compiledSelectorChecker, ruleData.compilationStatus());
+        ASSERT_WITH_MESSAGE(!selectorChecker(&m_element) || m_pseudoStyleRequest.pseudoId == NOPSEUDO, "When matching pseudo elements, we should never compile a selector checker without context unless it cannot match anything.");
 #if CSS_SELECTOR_JIT_PROFILING
-            ruleData.compiledSelectorUsed();
+        ruleData.compiledSelectorUsed();
 #endif
-            return selectorChecker(&m_element);
-        }
+        return selectorChecker(&m_element);
+    }
+#endif // ENABLE(CSS_SELECTOR_JIT)
+
+    SelectorChecker::CheckingContext context(m_mode);
+    context.elementStyle = m_style;
+    context.pseudoId = m_pseudoStyleRequest.pseudoId;
+    context.scrollbar = m_pseudoStyleRequest.scrollbar;
+    context.scrollbarPart = m_pseudoStyleRequest.scrollbarPart;
+
+#if ENABLE(CSS_SELECTOR_JIT)
+    if (compiledSelectorChecker) {
         ASSERT(ruleData.compilationStatus() == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
 
         SelectorCompiler::SelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::selectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, ruleData.compilationStatus());
-        SelectorCompiler::CheckingContext context(m_mode);
-        context.elementStyle = m_style;
-        context.pseudoId = m_pseudoStyleRequest.pseudoId;
-        context.scrollbar = m_pseudoStyleRequest.scrollbar;
-        context.scrollbarPart = m_pseudoStyleRequest.scrollbarPart;
+
 #if CSS_SELECTOR_JIT_PROFILING
         ruleData.compiledSelectorUsed();
 #endif
@@ -321,12 +326,7 @@ inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData)
 
     // Slow path.
     SelectorChecker selectorChecker(m_element.document());
-    SelectorChecker::SelectorCheckingContext context(ruleData.selector(), &m_element, m_mode);
-    context.elementStyle = m_style;
-    context.pseudoId = m_pseudoStyleRequest.pseudoId;
-    context.scrollbar = m_pseudoStyleRequest.scrollbar;
-    context.scrollbarPart = m_pseudoStyleRequest.scrollbarPart;
-    return selectorChecker.match(context);
+    return selectorChecker.match(ruleData.selector(), &m_element, context);
 }
 
 void ElementRuleCollector::collectMatchingRulesForList(const Vector<RuleData>* rules, const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange)
index 82a3af6..ee623c6 100644 (file)
 namespace WebCore {
 
 using namespace HTMLNames;
-    
+
+enum class VisitedMatchType : unsigned char {
+    Disabled, Enabled
+};
+
+struct SelectorChecker::CheckingContextWithStatus : public SelectorChecker::CheckingContext {
+    CheckingContextWithStatus(const SelectorChecker::CheckingContext& checkingContext, const CSSSelector* selector, Element* element)
+        : SelectorChecker::CheckingContext(checkingContext)
+        , selector(selector)
+        , element(element)
+        , visitedMatchType(resolvingMode == SelectorChecker::Mode::QueryingRules ? VisitedMatchType::Disabled : VisitedMatchType::Enabled)
+        , firstSelectorOfTheFragment(selector)
+        , inFunctionalPseudoClass(false)
+        , hasScrollbarPseudo(false)
+        , hasSelectionPseudo(false)
+    { }
+
+    const CSSSelector* selector;
+    Element* element;
+    VisitedMatchType visitedMatchType;
+    const CSSSelector* firstSelectorOfTheFragment;
+    bool inFunctionalPseudoClass;
+    bool hasScrollbarPseudo;
+    bool hasSelectionPseudo;
+};
+
 static inline bool isFirstChildElement(const Element* element)
 {
     return !ElementTraversal::previousSibling(element);
@@ -142,8 +167,9 @@ SelectorChecker::SelectorChecker(Document& document)
 {
 }
 
-bool SelectorChecker::match(const SelectorCheckingContext& context) const
+bool SelectorChecker::match(const CSSSelector* selector, Element* element, const CheckingContext& providedContext) const
 {
+    CheckingContextWithStatus context(providedContext, selector, element);
     PseudoId pseudoId = NOPSEUDO;
     if (matchRecursively(context, pseudoId) != SelectorMatches)
         return false;
@@ -176,12 +202,12 @@ inline static bool hasScrollbarPseudoElement(PseudoId& dynamicPseudo)
     return dynamicPseudo == RESIZER;
 }
 
-static SelectorChecker::SelectorCheckingContext checkingContextForParent(const SelectorChecker::SelectorCheckingContext& context)
+static SelectorChecker::CheckingContextWithStatus checkingContextForParent(const SelectorChecker::CheckingContextWithStatus& context)
 {
-    SelectorChecker::SelectorCheckingContext updatedContext(context);
+    SelectorChecker::CheckingContextWithStatus updatedContext(context);
     // Disable :visited matching when we see the first link.
     if (context.element->isLink())
-        updatedContext.visitedMatchType = SelectorChecker::VisitedMatchDisabled;
+        updatedContext.visitedMatchType = VisitedMatchType::Disabled;
     updatedContext.element = context.element->parentElement();
     return updatedContext;
 }
@@ -192,7 +218,7 @@ static SelectorChecker::SelectorCheckingContext checkingContextForParent(const S
 // * SelectorFailsLocally     - the selector fails for the element e
 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
 // * SelectorFailsCompletely  - the selector fails for e and any sibling or ancestor of e
-SelectorChecker::Match SelectorChecker::matchRecursively(const SelectorCheckingContext& context, PseudoId& dynamicPseudo) const
+SelectorChecker::Match SelectorChecker::matchRecursively(const CheckingContextWithStatus& context, PseudoId& dynamicPseudo) const
 {
     // The first selector has to match.
     if (!checkOne(context))
@@ -231,7 +257,7 @@ SelectorChecker::Match SelectorChecker::matchRecursively(const SelectorCheckingC
     if (!historySelector)
         return SelectorMatches;
 
-    SelectorCheckingContext nextContext(context);
+    CheckingContextWithStatus nextContext(context);
     nextContext.selector = historySelector;
 
     PseudoId ignoreDynamicPseudo = NOPSEUDO;
@@ -242,7 +268,7 @@ SelectorChecker::Match SelectorChecker::matchRecursively(const SelectorCheckingC
 
         // Disable :visited matching when we try to match anything else than an ancestors.
         if (relation != CSSSelector::Descendant && relation != CSSSelector::Child)
-            nextContext.visitedMatchType = VisitedMatchDisabled;
+            nextContext.visitedMatchType = VisitedMatchType::Disabled;
 
         nextContext.pseudoId = NOPSEUDO;
     }
@@ -408,7 +434,7 @@ static bool anyAttributeMatches(Element* element, const CSSSelector* selector, c
     return false;
 }
 
-static bool canMatchHoverOrActiveInQuirksMode(const SelectorChecker::SelectorCheckingContext& context)
+static bool canMatchHoverOrActiveInQuirksMode(const SelectorChecker::CheckingContextWithStatus& context)
 {
     // For quirks mode, follow this: http://quirks.spec.whatwg.org/#the-:active-and-:hover-quirk
     // In quirks mode, a compound selector 'selector' that matches the following conditions must not match elements that would not also match the ':any-link' selector.
@@ -463,7 +489,7 @@ static bool canMatchHoverOrActiveInQuirksMode(const SelectorChecker::SelectorChe
     return false;
 }
 
-bool SelectorChecker::checkOne(const SelectorCheckingContext& context) const
+bool SelectorChecker::checkOne(const CheckingContextWithStatus& context) const
 {
     Element* const & element = context.element;
     const CSSSelector* const & selector = context.selector;
@@ -499,7 +525,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context) const
             if (!selectorList)
                 return false;
 
-            SelectorCheckingContext subContext(context);
+            CheckingContextWithStatus subContext(context);
             subContext.inFunctionalPseudoClass = true;
             subContext.firstSelectorOfTheFragment = selectorList->first();
             for (subContext.selector = selectorList->first(); subContext.selector; subContext.selector = subContext.selector->tagHistory()) {
@@ -509,7 +535,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context) const
                     // the parser enforces that this never occurs
                     ASSERT(subContext.selector->pseudoClassType() != CSSSelector::PseudoClassNot);
                     // We select between :visited and :link when applying. We don't know which one applied (or not) yet.
-                    if (subContext.selector->pseudoClassType() == CSSSelector::PseudoClassVisited || (subContext.selector->pseudoClassType() == CSSSelector::PseudoClassLink && subContext.visitedMatchType == VisitedMatchEnabled))
+                    if (subContext.selector->pseudoClassType() == CSSSelector::PseudoClassVisited || (subContext.selector->pseudoClassType() == CSSSelector::PseudoClassLink && subContext.visitedMatchType == VisitedMatchType::Enabled))
                         return true;
                 }
                 if (!checkOne(subContext))
@@ -698,7 +724,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context) const
             break;
         case CSSSelector::PseudoClassAny:
             {
-                SelectorCheckingContext subContext(context);
+                CheckingContextWithStatus subContext(context);
                 subContext.inFunctionalPseudoClass = true;
                 PseudoId ignoreDynamicPseudo = NOPSEUDO;
                 for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) {
@@ -719,7 +745,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context) const
             // Inside functional pseudo class except for :not, :visited never matches.
             if (context.inFunctionalPseudoClass)
                 return false;
-            return element->isLink() && context.visitedMatchType == VisitedMatchEnabled;
+            return element->isLink() && context.visitedMatchType == VisitedMatchType::Enabled;
         case CSSSelector::PseudoClassDrag:
             if (context.resolvingMode == Mode::ResolvingStyle) {
                 if (context.elementStyle)
@@ -843,7 +869,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context) const
     }
 #if ENABLE(VIDEO_TRACK)
     else if (selector->m_match == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementCue) {
-        SelectorCheckingContext subContext(context);
+        CheckingContextWithStatus subContext(context);
 
         PseudoId ignoreDynamicPseudo = NOPSEUDO;
         const CSSSelector* const & selector = context.selector;
@@ -860,7 +886,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context) const
     return true;
 }
 
-bool SelectorChecker::checkScrollbarPseudoClass(const SelectorCheckingContext& context, const CSSSelector* selector) const
+bool SelectorChecker::checkScrollbarPseudoClass(const CheckingContextWithStatus& context, const CSSSelector* selector) const
 {
     ASSERT(selector->m_match == CSSSelector::PseudoClass);
 
index f4393f3..886f363 100644 (file)
@@ -46,47 +46,33 @@ class SelectorChecker {
     enum Match { SelectorMatches, SelectorFailsLocally, SelectorFailsAllSiblings, SelectorFailsCompletely };
 
 public:
-    enum VisitedMatchType { VisitedMatchDisabled, VisitedMatchEnabled };
     enum class Mode : unsigned char {
         ResolvingStyle = 0, CollectingRules, CollectingRulesIgnoringVirtualPseudoElements, QueryingRules
     };
 
     SelectorChecker(Document&);
 
-    struct SelectorCheckingContext {
-        // Initial selector constructor
-        SelectorCheckingContext(const CSSSelector* selector, Element* element, Mode resolvingMode)
-            : selector(selector)
-            , resolvingMode(resolvingMode)
-            , element(element)
-            , scope(nullptr)
-            , visitedMatchType(resolvingMode == Mode::QueryingRules ? VisitedMatchDisabled : VisitedMatchEnabled)
-            , pseudoId(NOPSEUDO)
+    struct CheckingContext {
+        CheckingContext(SelectorChecker::Mode resolvingMode)
+            : resolvingMode(resolvingMode)
             , elementStyle(nullptr)
+            , pseudoId(NOPSEUDO)
             , scrollbar(nullptr)
-            , firstSelectorOfTheFragment(selector)
             , scrollbarPart(NoPart)
-            , inFunctionalPseudoClass(false)
-            , hasScrollbarPseudo(false)
-            , hasSelectionPseudo(false)
+            , scope(nullptr)
         { }
 
-        const CSSSelector* selector;
-        Mode resolvingMode;
-        Element* element;
-        const ContainerNode* scope;
-        VisitedMatchType visitedMatchType;
-        PseudoId pseudoId;
+        SelectorChecker::Mode resolvingMode;
         RenderStyle* elementStyle;
+        PseudoId pseudoId;
         RenderScrollbar* scrollbar;
-        const CSSSelector* firstSelectorOfTheFragment;
         ScrollbarPart scrollbarPart;
-        bool inFunctionalPseudoClass;
-        bool hasScrollbarPseudo;
-        bool hasSelectionPseudo;
+        const ContainerNode* scope;
     };
 
-    bool match(const SelectorCheckingContext&) const;
+    struct CheckingContextWithStatus;
+
+    bool match(const CSSSelector*, Element*, const CheckingContext&) const;
 
     static bool tagMatches(const Element*, const QualifiedName&);
     static bool isCommonPseudoClassSelector(const CSSSelector*);
@@ -97,10 +83,10 @@ public:
     static unsigned determineLinkMatchType(const CSSSelector*);
 
 private:
-    Match matchRecursively(const SelectorCheckingContext&, PseudoId&) const;
-    bool checkOne(const SelectorCheckingContext&) const;
+    Match matchRecursively(const CheckingContextWithStatus&, PseudoId&) const;
+    bool checkOne(const CheckingContextWithStatus&) const;
 
-    bool checkScrollbarPseudoClass(const SelectorCheckingContext&, const CSSSelector*) const;
+    bool checkScrollbarPseudoClass(const CheckingContextWithStatus&, const CSSSelector*) const;
 
     bool m_strictParsing;
     bool m_documentIsHTML;
diff --git a/Source/WebCore/css/SelectorCheckerFastPath.cpp b/Source/WebCore/css/SelectorCheckerFastPath.cpp
deleted file mode 100644 (file)
index 5f605d4..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
- * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
- * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
- * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
- * 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"
-#include "StyledElement.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() && element->classNames().contains(selector->value());
-}
-
-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, 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->pseudoClassType()) {
-    case CSSSelector::PseudoClassLink:
-    case CSSSelector::PseudoClassAnyLink:
-        return m_element->isLink();
-    case CSSSelector::PseudoClassVisited:
-        return m_element->isLink() && visitedMatchType == SelectorChecker::VisitedMatchEnabled;
-    case CSSSelector::PseudoClassFocus:
-        return SelectorChecker::matchesFocusPseudoClass(m_element);
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    return true;
-}
-
-
-}
diff --git a/Source/WebCore/css/SelectorCheckerFastPath.h b/Source/WebCore/css/SelectorCheckerFastPath.h
deleted file mode 100644 (file)
index f1d1045..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
- * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
- * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
- * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
- * 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, m_selector->attribute(), m_selector->value().impl());
-    ASSERT(!m_selector->isAttributeSelector());
-    return true;
-}
-
-}
-
-#endif
index cd70bbf..1db19ec 100644 (file)
@@ -168,21 +168,18 @@ ALWAYS_INLINE bool shouldAppearIndeterminate(const Element* element)
 {
     return element->shouldAppearIndeterminate();
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesEnabledPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesEnabledPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     return context.scrollbar && context.scrollbar->enabled();
 }
 
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesDisabledPseudoClass(const ContextType& context)
+ALWAYS_INLINE bool scrollbarMatchesDisabledPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     return context.scrollbar && !context.scrollbar->enabled();
 }
 
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesHoverPseudoClass(const ContextType& context)
+ALWAYS_INLINE bool scrollbarMatchesHoverPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     if (!context.scrollbar)
         return false;
@@ -194,8 +191,7 @@ ALWAYS_INLINE bool scrollbarMatchesHoverPseudoClass(const ContextType& context)
     return context.scrollbarPart == hoveredPart;
 }
 
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesActivePseudoClass(const ContextType& context)
+ALWAYS_INLINE bool scrollbarMatchesActivePseudoClass(const SelectorChecker::CheckingContext& context)
 {
     if (!context.scrollbar)
         return false;
@@ -206,45 +202,38 @@ ALWAYS_INLINE bool scrollbarMatchesActivePseudoClass(const ContextType& context)
         return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
     return context.scrollbarPart == pressedPart;
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesHorizontalPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesHorizontalPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     return context.scrollbar && context.scrollbar->orientation() == HorizontalScrollbar;
 }
 
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesVerticalPseudoClass(const ContextType& context)
+ALWAYS_INLINE bool scrollbarMatchesVerticalPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     return context.scrollbar && context.scrollbar->orientation() == VerticalScrollbar;
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesDecrementPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesDecrementPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     return context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == BackButtonEndPart || context.scrollbarPart == BackTrackPart;
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesIncrementPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesIncrementPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     return context.scrollbarPart == ForwardButtonStartPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == ForwardTrackPart;
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesStartPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesStartPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     return context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == ForwardButtonStartPart || context.scrollbarPart == BackTrackPart;
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesEndPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesEndPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     return context.scrollbarPart == BackButtonEndPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == ForwardTrackPart;
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesDoubleButtonPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesDoubleButtonPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     if (!context.scrollbar)
         return false;
@@ -255,9 +244,8 @@ ALWAYS_INLINE bool scrollbarMatchesDoubleButtonPseudoClass(const ContextType& co
         return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
     return false;
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesSingleButtonPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesSingleButtonPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     if (!context.scrollbar)
         return false;
@@ -266,9 +254,8 @@ ALWAYS_INLINE bool scrollbarMatchesSingleButtonPseudoClass(const ContextType& co
         return buttonsPlacement == ScrollbarButtonsSingle;
     return false;
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesNoButtonPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesNoButtonPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     if (!context.scrollbar)
         return false;
@@ -279,9 +266,8 @@ ALWAYS_INLINE bool scrollbarMatchesNoButtonPseudoClass(const ContextType& contex
         return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
     return false;
 }
-    
-template <typename ContextType>
-ALWAYS_INLINE bool scrollbarMatchesCornerPresentPseudoClass(const ContextType& context)
+
+ALWAYS_INLINE bool scrollbarMatchesCornerPresentPseudoClass(const SelectorChecker::CheckingContext& context)
 {
     return context.scrollbar && context.scrollbar->scrollableArea()->isScrollCornerVisible();
 }
index c7ee7ab..c538741 100644 (file)
@@ -571,8 +571,8 @@ inline bool checkRegionSelector(const CSSSelector* regionSelector, Element* regi
 
     SelectorChecker selectorChecker(regionElement->document());
     for (const CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s)) {
-        SelectorChecker::SelectorCheckingContext selectorCheckingContext(s, regionElement, SelectorChecker::Mode::QueryingRules);
-        if (selectorChecker.match(selectorCheckingContext))
+        SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
+        if (selectorChecker.match(s, regionElement, selectorCheckingContext))
             return true;
     }
     return false;
index 6a6e6ef..99a5037 100644 (file)
@@ -157,8 +157,8 @@ struct SelectorFragment {
     unsigned tagNameNotMatchedBacktrackingStartWidthFromIndirectAdjacent;
     unsigned widthFromIndirectAdjacent;
 
-    FunctionType appendUnoptimizedPseudoClassWithContext(bool (*matcher)(const CheckingContext&));
-    
+    FunctionType appendUnoptimizedPseudoClassWithContext(bool (*matcher)(const SelectorChecker::CheckingContext&));
+
     const QualifiedName* tagName;
     const AtomicString* id;
     const AtomicString* langFilter;
@@ -363,7 +363,7 @@ static inline bool fragmentMatchesTheRightmostElement(SelectorContext selectorCo
     return fragment.relationToRightFragment == FragmentRelation::Rightmost && fragment.positionInRootFragments == FragmentPositionInRootFragments::Rightmost;
 }
 
-FunctionType SelectorFragment::appendUnoptimizedPseudoClassWithContext(bool (*matcher)(const CheckingContext&))
+FunctionType SelectorFragment::appendUnoptimizedPseudoClassWithContext(bool (*matcher)(const SelectorChecker::CheckingContext&))
 {
     unoptimizedPseudoClassesWithContext.append(JSC::FunctionPtr(matcher));
     return FunctionType::SelectorCheckerWithCheckingContext;
@@ -376,33 +376,33 @@ static inline FunctionType addScrollbarPseudoClassType(const CSSSelector& select
         fragment.unoptimizedPseudoClasses.append(JSC::FunctionPtr(isWindowInactive));
         return FunctionType::SimpleSelectorChecker;
     case CSSSelector::PseudoClassDisabled:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesDisabledPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesDisabledPseudoClass);
     case CSSSelector::PseudoClassEnabled:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesEnabledPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesEnabledPseudoClass);
     case CSSSelector::PseudoClassHorizontal:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesHorizontalPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesHorizontalPseudoClass);
     case CSSSelector::PseudoClassVertical:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesVerticalPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesVerticalPseudoClass);
     case CSSSelector::PseudoClassDecrement:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesDecrementPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesDecrementPseudoClass);
     case CSSSelector::PseudoClassIncrement:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesIncrementPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesIncrementPseudoClass);
     case CSSSelector::PseudoClassStart:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesStartPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesStartPseudoClass);
     case CSSSelector::PseudoClassEnd:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesEndPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesEndPseudoClass);
     case CSSSelector::PseudoClassDoubleButton:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesDoubleButtonPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesDoubleButtonPseudoClass);
     case CSSSelector::PseudoClassSingleButton:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesSingleButtonPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesSingleButtonPseudoClass);
     case CSSSelector::PseudoClassNoButton:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesNoButtonPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesNoButtonPseudoClass);
     case CSSSelector::PseudoClassCornerPresent:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesCornerPresentPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesCornerPresentPseudoClass);
     case CSSSelector::PseudoClassActive:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesActivePseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesActivePseudoClass);
     case CSSSelector::PseudoClassHover:
-        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesHoverPseudoClass<CheckingContext>);
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesHoverPseudoClass);
     default:
         return FunctionType::CannotMatchAnything;
     }
@@ -1610,7 +1610,7 @@ void SelectorCodeGenerator::addFlagsToElementStyleFromContext(Assembler::Registe
     ASSERT(m_selectorContext != SelectorContext::QuerySelector);
 
     LocalRegister childStyle(m_registerAllocator);
-    m_assembler.loadPtr(Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, elementStyle)), childStyle);
+    m_assembler.loadPtr(Assembler::Address(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, elementStyle)), childStyle);
 
     // FIXME: We should look into doing something smart in MacroAssembler instead.
     Assembler::Address flagAddress(childStyle, RenderStyle::noninheritedFlagsMemoryOffset() + RenderStyle::NonInheritedFlags::flagsMemoryOffset());
@@ -1666,7 +1666,7 @@ Assembler::Jump SelectorCodeGenerator::branchOnResolvingModeWithCheckingContext(
 {
     // Depend on the specified resolving mode and our current mode, branch.
     static_assert(sizeof(SelectorChecker::Mode) == 1, "We generate a byte load/test for the SelectorChecker::Mode.");
-    return m_assembler.branch8(condition, Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, resolvingMode)), Assembler::TrustedImm32(static_cast<std::underlying_type<SelectorChecker::Mode>::type>(mode)));
+    return m_assembler.branch8(condition, Assembler::Address(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, resolvingMode)), Assembler::TrustedImm32(static_cast<std::underlying_type<SelectorChecker::Mode>::type>(mode)));
 
 }
 
@@ -2406,7 +2406,7 @@ static bool elementIsActive(Element* element)
     return element->active() || InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoClassActive);
 }
 
-static bool elementIsActiveForStyleResolution(Element* element, const CheckingContext* checkingContext)
+static bool elementIsActiveForStyleResolution(Element* element, const SelectorChecker::CheckingContext* checkingContext)
 {
     if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
         element->setChildrenAffectedByActive();
@@ -2477,7 +2477,7 @@ static void setElementStyleIsAffectedByEmpty(Element* element)
     element->setStyleAffectedByEmpty();
 }
 
-static void setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary(CheckingContext* context, bool isEmpty)
+static void setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary(SelectorChecker::CheckingContext* context, bool isEmpty)
 {
     ASSERT(context->elementStyle);
     context->elementStyle->setEmptyState(isEmpty);
@@ -2585,7 +2585,7 @@ static bool elementIsHovered(Element* element)
     return element->hovered() || InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoClassHover);
 }
 
-static bool elementIsHoveredForStyleResolution(Element* element, const CheckingContext* checkingContext)
+static bool elementIsHoveredForStyleResolution(Element* element, const SelectorChecker::CheckingContext* checkingContext)
 {
     if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
         element->setChildrenAffectedByHover();
@@ -2776,7 +2776,7 @@ void SelectorCodeGenerator::generateElementIsOnlyChild(Assembler::JumpList& fail
 }
 
 #if ENABLE(CSS_SELECTORS_LEVEL4)
-static bool makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const CheckingContext* checkingContext)
+static bool makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const SelectorChecker::CheckingContext* checkingContext)
 {
     if (isHTMLTextFormControlElement(*element)) {
         if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
@@ -2786,7 +2786,7 @@ static bool makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element*
     return false;
 }
 
-static bool makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const CheckingContext* checkingContext)
+static bool makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const SelectorChecker::CheckingContext* checkingContext)
 {
     if (isHTMLTextFormControlElement(*element)) {
         if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle) {
@@ -3077,10 +3077,10 @@ void SelectorCodeGenerator::generateRequestedPseudoElementEqualsToSelectorPseudo
     // Otherwise, if the requested pseudoId is not NOPSEUDO, the requested pseudoId need to equal to the pseudo element of the rightmost fragment.
     if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
         if (!fragment.pseudoElementSelector)
-            failureCases.append(m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, pseudoId)), Assembler::TrustedImm32(NOPSEUDO)));
+            failureCases.append(m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, pseudoId)), Assembler::TrustedImm32(NOPSEUDO)));
         else {
-            Assembler::Jump skip = m_assembler.branch8(Assembler::Equal, Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, pseudoId)), Assembler::TrustedImm32(NOPSEUDO));
-            failureCases.append(m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, pseudoId)), Assembler::TrustedImm32(CSSSelector::pseudoId(fragment.pseudoElementSelector->pseudoElementType()))));
+            Assembler::Jump skip = m_assembler.branch8(Assembler::Equal, Assembler::Address(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, pseudoId)), Assembler::TrustedImm32(NOPSEUDO));
+            failureCases.append(m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, pseudoId)), Assembler::TrustedImm32(CSSSelector::pseudoId(fragment.pseudoElementSelector->pseudoElementType()))));
             skip.link(&m_assembler);
         }
     }
@@ -3099,7 +3099,7 @@ void SelectorCodeGenerator::generateElementIsScopeRoot(Assembler::JumpList& fail
 
     LocalRegister scope(m_registerAllocator);
     loadCheckingContext(scope);
-    m_assembler.loadPtr(Assembler::Address(scope, OBJECT_OFFSETOF(CheckingContext, scope)), scope);
+    m_assembler.loadPtr(Assembler::Address(scope, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, scope)), scope);
 
     Assembler::Jump scopeIsNotNull = m_assembler.branchTestPtr(Assembler::NonZero, scope);
 
@@ -3131,7 +3131,7 @@ void SelectorCodeGenerator::generateMarkPseudoStyleForPseudoElement(Assembler::J
     Assembler::JumpList successCases;
 
     // When the requested pseudoId isn't NOPSEUDO, there's no need to mark the pseudo element style.
-    successCases.append(m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, pseudoId)), Assembler::TrustedImm32(NOPSEUDO)));
+    successCases.append(m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, pseudoId)), Assembler::TrustedImm32(NOPSEUDO)));
 
     // When resolving mode is CollectingRulesIgnoringVirtualPseudoElements, there's no need to mark the pseudo element style.
     successCases.append(branchOnResolvingModeWithCheckingContext(Assembler::Equal, SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements, checkingContext));
index c0ca532..b107c43 100644 (file)
@@ -69,24 +69,6 @@ private:
 
 namespace SelectorCompiler {
 
-struct CheckingContext {
-    CheckingContext(SelectorChecker::Mode resolvingMode)
-        : resolvingMode(resolvingMode)
-        , elementStyle(nullptr)
-        , pseudoId(NOPSEUDO)
-        , scrollbar(nullptr)
-        , scrollbarPart(NoPart)
-        , scope(nullptr)
-    { }
-
-    SelectorChecker::Mode resolvingMode;
-    RenderStyle* elementStyle;
-    PseudoId pseudoId;
-    RenderScrollbar* scrollbar;
-    ScrollbarPart scrollbarPart;
-    const ContainerNode* scope;
-};
-
 enum class SelectorContext {
     // Rule Collector needs a resolvingMode and can modify the tree as it matches.
     RuleCollector,
@@ -96,7 +78,7 @@ enum class SelectorContext {
 };
 
 typedef unsigned (*SimpleSelectorChecker)(Element*);
-typedef unsigned (*SelectorCheckerWithCheckingContext)(Element*, const CheckingContext*);
+typedef unsigned (*SelectorCheckerWithCheckingContext)(Element*, const SelectorChecker::CheckingContext*);
 SelectorCompilationStatus compileSelector(const CSSSelector*, JSC::VM*, SelectorContext, JSC::MacroAssemblerCodeRef& outputCodeRef);
 
 inline SimpleSelectorChecker simpleSelectorCheckerFunction(void* executableAddress, SelectorCompilationStatus compilationStatus)
index 5c3f9bc..c9dd60e 100644 (file)
@@ -29,7 +29,6 @@
 #include "CSSParser.h"
 #include "ElementDescendantIterator.h"
 #include "SelectorChecker.h"
-#include "SelectorCheckerFastPath.h"
 #include "StaticNodeList.h"
 #include "StyledElement.h"
 
@@ -76,7 +75,7 @@ SelectorDataList::SelectorDataList(const CSSSelectorList& selectorList)
 
     m_selectors.reserveInitialCapacity(selectorCount);
     for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
-        m_selectors.uncheckedAppend(SelectorData(selector, SelectorCheckerFastPath::canUse(selector)));
+        m_selectors.uncheckedAppend(SelectorData(selector));
 
     if (selectorCount == 1) {
         const CSSSelector& selector = *m_selectors.first().selector;
@@ -114,17 +113,10 @@ SelectorDataList::SelectorDataList(const CSSSelectorList& selectorList)
 
 inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData, Element& element, const ContainerNode& rootNode) const
 {
-    if (selectorData.isFastCheckable && !element.isSVGElement()) {
-        SelectorCheckerFastPath selectorCheckerFastPath(selectorData.selector, &element);
-        if (!selectorCheckerFastPath.matchesRightmostSelector(SelectorChecker::VisitedMatchDisabled))
-            return false;
-        return selectorCheckerFastPath.matches();
-    }
-
     SelectorChecker selectorChecker(element.document());
-    SelectorChecker::SelectorCheckingContext selectorCheckingContext(selectorData.selector, &element, SelectorChecker::Mode::QueryingRules);
+    SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
     selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode;
-    return selectorChecker.match(selectorCheckingContext);
+    return selectorChecker.match(selectorData.selector, &element, selectorCheckingContext);
 }
 
 bool SelectorDataList::matches(Element& targetElement) const
@@ -380,7 +372,7 @@ ALWAYS_INLINE void SelectorDataList::executeCompiledSimpleSelectorChecker(const
 template <typename SelectorQueryTrait>
 ALWAYS_INLINE void SelectorDataList::executeCompiledSelectorCheckerWithCheckingContext(const ContainerNode& rootNode, const ContainerNode& searchRootNode, SelectorCompiler::SelectorCheckerWithCheckingContext selectorChecker, typename SelectorQueryTrait::OutputType& output, const SelectorData& selectorData) const
 {
-    SelectorCompiler::CheckingContext checkingContext(SelectorChecker::Mode::QueryingRules);
+    SelectorChecker::CheckingContext checkingContext(SelectorChecker::Mode::QueryingRules);
     checkingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode;
 
     for (auto& element : elementDescendants(const_cast<ContainerNode&>(searchRootNode))) {
@@ -396,6 +388,23 @@ ALWAYS_INLINE void SelectorDataList::executeCompiledSelectorCheckerWithCheckingC
         }
     }
 }
+
+static bool isCompiledSelector(SelectorCompilationStatus compilationStatus)
+{
+    return compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker || compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext;
+}
+
+bool SelectorDataList::compileSelector(const SelectorData& selectorData, const ContainerNode& rootNode)
+{
+    if (selectorData.compilationStatus != SelectorCompilationStatus::NotCompiled)
+        return isCompiledSelector(selectorData.compilationStatus);
+
+    JSC::VM& vm = rootNode.document().scriptExecutionContext()->vm();
+    selectorData.compilationStatus = SelectorCompiler::compileSelector(selectorData.selector, &vm, SelectorCompiler::SelectorContext::QuerySelector, selectorData.compiledSelectorCodeRef);
+    return isCompiledSelector(selectorData.compilationStatus);
+}
+
+
 #endif // ENABLE(CSS_SELECTOR_JIT)
 
 template <typename SelectorQueryTrait>
@@ -411,37 +420,34 @@ ALWAYS_INLINE void SelectorDataList::execute(ContainerNode& rootNode, typename S
             break;
         }
 #if ENABLE(CSS_SELECTOR_JIT)
-        if (selectorData.compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker || selectorData.compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext)
+        if (compileSelector(selectorData, *searchRootNode))
             goto CompiledSingleCase;
-#endif
-        }
+        goto SingleSelectorCase;
+        ASSERT_NOT_REACHED();
+#else
         FALLTHROUGH;
+#endif // ENABLE(CSS_SELECTOR_JIT)
+        }
     case CompilableSingleWithRootFilter:
     case CompilableSingle:
         {
 #if ENABLE(CSS_SELECTOR_JIT)
         const SelectorData& selectorData = m_selectors.first();
-        ASSERT(m_matchType == RightMostWithIdMatch || selectorData.compilationStatus == SelectorCompilationStatus::NotCompiled);
-
-        JSC::VM& vm = searchRootNode->document().scriptExecutionContext()->vm();
-        selectorData.compilationStatus = SelectorCompiler::compileSelector(selectorData.selector, &vm, SelectorCompiler::SelectorContext::QuerySelector, selectorData.compiledSelectorCodeRef);
-
-        if (selectorData.compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker || selectorData.compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext) {
+        ASSERT(selectorData.compilationStatus == SelectorCompilationStatus::NotCompiled);
+        ASSERT(m_matchType == CompilableSingle || m_matchType == CompilableSingleWithRootFilter);
+        if (compileSelector(selectorData, *searchRootNode)) {
             if (m_matchType == CompilableSingle) {
                 m_matchType = CompiledSingle;
                 goto CompiledSingleCase;
-            }
-            if (m_matchType == CompilableSingleWithRootFilter) {
+            } else {
+                ASSERT(m_matchType == CompilableSingleWithRootFilter);
                 m_matchType = CompiledSingleWithRootFilter;
                 goto CompiledSingleWithRootFilterCase;
             }
-            goto CompiledSingleCase;
         }
-        if (m_matchType != RightMostWithIdMatch)
-            m_matchType = SingleSelector;
+        m_matchType = SingleSelector;
         goto SingleSelectorCase;
         ASSERT_NOT_REACHED();
-        break;
 #else
         FALLTHROUGH;
 #endif // ENABLE(CSS_SELECTOR_JIT)
index d896a76..c075be3 100644 (file)
@@ -54,12 +54,11 @@ public:
 
 private:
     struct SelectorData {
-        SelectorData(const CSSSelector* selector, bool isFastCheckable)
+        SelectorData(const CSSSelector* selector)
             : selector(selector)
 #if ENABLE(CSS_SELECTOR_JIT) && CSS_SELECTOR_JIT_PROFILING
             , m_compiledSelectorUseCount(0)
 #endif
-            , isFastCheckable(isFastCheckable)
         {
         }
 
@@ -77,7 +76,6 @@ private:
         void compiledSelectorUsed() const { m_compiledSelectorUseCount++; }
 #endif
 #endif // ENABLE(CSS_SELECTOR_JIT)
-        bool isFastCheckable;
     };
 
     bool selectorMatches(const SelectorData&, Element&, const ContainerNode& rootNode) const;
@@ -91,6 +89,7 @@ private:
 #if ENABLE(CSS_SELECTOR_JIT)
     template <typename SelectorQueryTrait> void executeCompiledSimpleSelectorChecker(const ContainerNode& searchRootNode, SelectorCompiler::SimpleSelectorChecker, typename SelectorQueryTrait::OutputType&, const SelectorData&) const;
     template <typename SelectorQueryTrait> void executeCompiledSelectorCheckerWithCheckingContext(const ContainerNode& rootNode, const ContainerNode& searchRootNode, SelectorCompiler::SelectorCheckerWithCheckingContext, typename SelectorQueryTrait::OutputType&, const SelectorData&) const;
+    static bool compileSelector(const SelectorData&, const ContainerNode& rootNode);
 #endif // ENABLE(CSS_SELECTOR_JIT)
 
     Vector<SelectorData> m_selectors;