Title: [94089] trunk/Source/WebCore
Revision
94089
Author
[email protected]
Date
2011-08-30 10:43:24 -0700 (Tue, 30 Aug 2011)

Log Message

querySelector/querySelectorAll should use selector checker fast path 
https://bugs.webkit.org/show_bug.cgi?id=67161

Reviewed by Sam Weinig.

Descendant and child selectors can be matches substantially faster using
SelectorChecker::fastCheckSelector() path. Currently it is used for style matching only.  
        
Add SelectorQuery class that can do both querySelector and querySelectorAll efficiently using
fast path. Use inlined loop for DOM traversal.
        
The patch is ~25% speedup in the overall native score of http://www.webkit.org/perf/slickspeed/.
Some individual subtests (using child or descendant selectors) execute twice as fast.

* CMakeLists.txt:
* GNUmakefile.list.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::SelectorChecker::checkSelector):
(WebCore::CSSStyleSelector::SelectorChecker::isFastCheckableSelector):
(WebCore::RuleData::RuleData):
* css/CSSStyleSelector.h:
        
    Make fast path checking available outside CSSStyleSelector.
            
* dom/DOMAllInOne.cpp:
* dom/Node.cpp:
(WebCore::Node::querySelector):
(WebCore::Node::querySelectorAll):
        
    Switch to SelectorQuery.
        
* dom/SelectorNodeList.cpp: Removed.
* dom/SelectorNodeList.h: Removed.
        
    SelectorQuery makes these obsolete.

* dom/SelectorQuery.cpp: Added.
(WebCore::SelectorQuery::SelectorQuery):
(WebCore::SelectorQuery::queryAll):
(WebCore::SelectorQuery::queryFirst):
(WebCore::SelectorQuery::canUseIdLookup):
(WebCore::SelectorQuery::execute):
* dom/SelectorQuery.h: Added.
        
    Class for selector matching in tree.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/WebCore/CMakeLists.txt (94088 => 94089)


--- trunk/Source/WebCore/CMakeLists.txt	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/CMakeLists.txt	2011-08-30 17:43:24 UTC (rev 94089)
@@ -568,7 +568,7 @@
     dom/ScriptExecutionContext.cpp
     dom/ScriptRunner.cpp
     dom/SelectElement.cpp
-    dom/SelectorNodeList.cpp
+    dom/SelectorQuery.cpp
     dom/ShadowContentElement.cpp
     dom/ShadowInclusionSelector.cpp
     dom/ShadowRoot.cpp

Modified: trunk/Source/WebCore/ChangeLog (94088 => 94089)


--- trunk/Source/WebCore/ChangeLog	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/ChangeLog	2011-08-30 17:43:24 UTC (rev 94089)
@@ -1,3 +1,55 @@
+2011-08-30  Antti Koivisto  <[email protected]>
+
+        querySelector/querySelectorAll should use selector checker fast path 
+        https://bugs.webkit.org/show_bug.cgi?id=67161
+
+        Reviewed by Sam Weinig.
+
+        Descendant and child selectors can be matches substantially faster using
+        SelectorChecker::fastCheckSelector() path. Currently it is used for style matching only.  
+        
+        Add SelectorQuery class that can do both querySelector and querySelectorAll efficiently using
+        fast path. Use inlined loop for DOM traversal.
+        
+        The patch is ~25% speedup in the overall native score of http://www.webkit.org/perf/slickspeed/.
+        Some individual subtests (using child or descendant selectors) execute twice as fast.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::SelectorChecker::checkSelector):
+        (WebCore::CSSStyleSelector::SelectorChecker::isFastCheckableSelector):
+        (WebCore::RuleData::RuleData):
+        * css/CSSStyleSelector.h:
+        
+            Make fast path checking available outside CSSStyleSelector.
+            
+        * dom/DOMAllInOne.cpp:
+        * dom/Node.cpp:
+        (WebCore::Node::querySelector):
+        (WebCore::Node::querySelectorAll):
+        
+            Switch to SelectorQuery.
+        
+        * dom/SelectorNodeList.cpp: Removed.
+        * dom/SelectorNodeList.h: Removed.
+        
+            SelectorQuery makes these obsolete.
+
+        * dom/SelectorQuery.cpp: Added.
+        (WebCore::SelectorQuery::SelectorQuery):
+        (WebCore::SelectorQuery::queryAll):
+        (WebCore::SelectorQuery::queryFirst):
+        (WebCore::SelectorQuery::canUseIdLookup):
+        (WebCore::SelectorQuery::execute):
+        * dom/SelectorQuery.h: Added.
+        
+            Class for selector matching in tree.
+    
 2011-08-30  Dmitry Titov  <[email protected]>
 
         REGRESSION (r93913): Failures in fast/replaced/frame-removed-during-resize.html and scrollbars/scrollable-iframe-remove-crash.html

Modified: trunk/Source/WebCore/GNUmakefile.list.am (94088 => 94089)


--- trunk/Source/WebCore/GNUmakefile.list.am	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2011-08-30 17:43:24 UTC (rev 94089)
@@ -1284,8 +1284,8 @@
 	Source/WebCore/dom/ScriptRunner.h \
 	Source/WebCore/dom/SelectElement.cpp \
 	Source/WebCore/dom/SelectElement.h \
-	Source/WebCore/dom/SelectorNodeList.cpp \
-	Source/WebCore/dom/SelectorNodeList.h \
+	Source/WebCore/dom/SelectorQuery.cpp \
+	Source/WebCore/dom/SelectorQuery.h \
 	Source/WebCore/dom/ShadowContentElement.cpp \
 	Source/WebCore/dom/ShadowContentElement.h \
 	Source/WebCore/dom/ShadowInclusionSelector.cpp \

Modified: trunk/Source/WebCore/WebCore.gypi (94088 => 94089)


--- trunk/Source/WebCore/WebCore.gypi	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/WebCore.gypi	2011-08-30 17:43:24 UTC (rev 94089)
@@ -5354,8 +5354,8 @@
             'dom/ScriptedAnimationController.h',
             'dom/SelectElement.cpp',
             'dom/SelectElement.h',
-            'dom/SelectorNodeList.cpp',
-            'dom/SelectorNodeList.h',
+            'dom/SelectorQuery.cpp',
+            'dom/SelectorQuery.h',
             'dom/ShadowContentElement.cpp',
             'dom/ShadowContentElement.h',
             'dom/ShadowInclusionSelector.cpp',

Modified: trunk/Source/WebCore/WebCore.pro (94088 => 94089)


--- trunk/Source/WebCore/WebCore.pro	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/WebCore.pro	2011-08-30 17:43:24 UTC (rev 94089)
@@ -542,7 +542,7 @@
     dom/ScriptExecutionContext.cpp \
     dom/ScriptRunner.cpp \
     dom/SelectElement.cpp \
-    dom/SelectorNodeList.cpp \
+    dom/SelectorQuery.cpp \
     dom/ShadowContentElement.cpp \
     dom/ShadowInclusionSelector.cpp \
     dom/ShadowRoot.cpp \
@@ -1536,7 +1536,7 @@
     dom/ScriptElement.h \
     dom/ScriptExecutionContext.h \
     dom/SelectElement.h \
-    dom/SelectorNodeList.h \
+    dom/SelectorQuery.h \
     dom/ShadowContentElement.h \
     dom/ShadowInclusionSelector.h \
     dom/ShadowRoot.h \

Modified: trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj (94088 => 94089)


--- trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2011-08-30 17:43:24 UTC (rev 94089)
@@ -48330,7 +48330,7 @@
 				>
 			</File>
 			<File
-				RelativePath="..\dom\SelectorNodeList.cpp"
+				RelativePath="..\dom\SelectorQuery.cpp"
 				>
 				<FileConfiguration
 					Name="Debug|Win32"
@@ -48382,66 +48382,10 @@
 				</FileConfiguration>
 			</File>
 			<File
-				RelativePath="..\dom\SelectorNodeList.cpp"
+				RelativePath="..\dom\SelectorQuery.h"
 				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug_Cairo_CFLite|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release_Cairo_CFLite|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug_All|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Production|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
 			</File>
 			<File
-				RelativePath="..\dom\SelectorNodeList.h"
-				>
-			</File>
-			<File
-				RelativePath="..\dom\SelectorNodeList.h"
-				>
-			</File>
-			<File
 				RelativePath="..\dom\ShadowContentElement.cpp"
 				>
 				<FileConfiguration

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (94088 => 94089)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2011-08-30 17:43:24 UTC (rev 94089)
@@ -5098,8 +5098,6 @@
 		BC7FA6210D1F0CBD00DB22A9 /* DynamicNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7FA61F0D1F0CBD00DB22A9 /* DynamicNodeList.h */; };
 		BC7FA62D0D1F0EFF00DB22A9 /* StaticNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7FA62B0D1F0EFF00DB22A9 /* StaticNodeList.h */; };
 		BC7FA62E0D1F0EFF00DB22A9 /* StaticNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7FA62C0D1F0EFF00DB22A9 /* StaticNodeList.cpp */; };
-		BC7FA6810D1F167900DB22A9 /* SelectorNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7FA67F0D1F167900DB22A9 /* SelectorNodeList.h */; };
-		BC7FA6820D1F167900DB22A9 /* SelectorNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7FA6800D1F167900DB22A9 /* SelectorNodeList.cpp */; };
 		BC80C9870CD294EE00A0B7B3 /* CSSTimingFunctionValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC80C9850CD294EE00A0B7B3 /* CSSTimingFunctionValue.cpp */; };
 		BC80C9880CD294EE00A0B7B3 /* CSSTimingFunctionValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC80C9860CD294EE00A0B7B3 /* CSSTimingFunctionValue.h */; };
 		BC8243290D0CE8A200460C8F /* JSSQLError.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8243250D0CE8A200460C8F /* JSSQLError.h */; };
@@ -5652,6 +5650,8 @@
 		E446143C0CD689CC00FADA75 /* JSHTMLSourceElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E4B423720CBFB6E000AF2ECE /* JSHTMLSourceElement.h */; };
 		E44614510CD68A3500FADA75 /* RenderVideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4B41E330CBFB60900AF2ECE /* RenderVideo.cpp */; };
 		E44614520CD68A3500FADA75 /* RenderVideo.h in Headers */ = {isa = PBXBuildFile; fileRef = E4B41E340CBFB60900AF2ECE /* RenderVideo.h */; };
+		E45322AB140CE267005A0F92 /* SelectorQuery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E45322A9140CE267005A0F92 /* SelectorQuery.cpp */; };
+		E45322AC140CE267005A0F92 /* SelectorQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = E45322AA140CE267005A0F92 /* SelectorQuery.h */; };
 		E462A4A1113E71BE004A4220 /* IntPointHash.h in Headers */ = {isa = PBXBuildFile; fileRef = E462A4A0113E71BE004A4220 /* IntPointHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E4778B7F115A581A00B5D372 /* JSCustomEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4778B7D115A581A00B5D372 /* JSCustomEvent.cpp */; };
 		E4778B80115A581A00B5D372 /* JSCustomEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = E4778B7E115A581A00B5D372 /* JSCustomEvent.h */; };
@@ -11817,8 +11817,6 @@
 		BC7FA61F0D1F0CBD00DB22A9 /* DynamicNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicNodeList.h; sourceTree = "<group>"; };
 		BC7FA62B0D1F0EFF00DB22A9 /* StaticNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticNodeList.h; sourceTree = "<group>"; };
 		BC7FA62C0D1F0EFF00DB22A9 /* StaticNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticNodeList.cpp; sourceTree = "<group>"; };
-		BC7FA67F0D1F167900DB22A9 /* SelectorNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorNodeList.h; sourceTree = "<group>"; };
-		BC7FA6800D1F167900DB22A9 /* SelectorNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorNodeList.cpp; sourceTree = "<group>"; };
 		BC80C9850CD294EE00A0B7B3 /* CSSTimingFunctionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSSTimingFunctionValue.cpp; sourceTree = "<group>"; };
 		BC80C9860CD294EE00A0B7B3 /* CSSTimingFunctionValue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSSTimingFunctionValue.h; sourceTree = "<group>"; };
 		BC8243250D0CE8A200460C8F /* JSSQLError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLError.h; sourceTree = "<group>"; };
@@ -12405,6 +12403,8 @@
 		E44614110CD6826900FADA75 /* JSMediaError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMediaError.h; sourceTree = "<group>"; };
 		E44614120CD6826900FADA75 /* JSTimeRanges.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTimeRanges.cpp; sourceTree = "<group>"; };
 		E44614130CD6826900FADA75 /* JSTimeRanges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTimeRanges.h; sourceTree = "<group>"; };
+		E45322A9140CE267005A0F92 /* SelectorQuery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorQuery.cpp; sourceTree = "<group>"; };
+		E45322AA140CE267005A0F92 /* SelectorQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorQuery.h; sourceTree = "<group>"; };
 		E462A4A0113E71BE004A4220 /* IntPointHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntPointHash.h; sourceTree = "<group>"; };
 		E4778B7D115A581A00B5D372 /* JSCustomEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomEvent.cpp; sourceTree = "<group>"; };
 		E4778B7E115A581A00B5D372 /* JSCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomEvent.h; sourceTree = "<group>"; };
@@ -20062,8 +20062,8 @@
 				8A413ADE1207BBA50082016E /* ScriptRunner.h */,
 				084AEBE20FB505FA0038483E /* SelectElement.cpp */,
 				084AEBE30FB505FA0038483E /* SelectElement.h */,
-				BC7FA6800D1F167900DB22A9 /* SelectorNodeList.cpp */,
-				BC7FA67F0D1F167900DB22A9 /* SelectorNodeList.h */,
+				E45322A9140CE267005A0F92 /* SelectorQuery.cpp */,
+				E45322AA140CE267005A0F92 /* SelectorQuery.h */,
 				A766CF8B13810E0C0011A0B3 /* ShadowContentElement.cpp */,
 				A74C2D3B13811E0D00F83572 /* ShadowContentElement.h */,
 				A71C30B61381265E00DBC351 /* ShadowInclusionSelector.cpp */,
@@ -22839,7 +22839,6 @@
 				371F4FFC0D25E7F300ECE0D5 /* SegmentedFontData.h in Headers */,
 				B2C3DA2F0D006C1D00EF6F26 /* SegmentedString.h in Headers */,
 				084AEBE50FB505FA0038483E /* SelectElement.h in Headers */,
-				BC7FA6810D1F167900DB22A9 /* SelectorNodeList.h in Headers */,
 				A75E497610752ACB00C9B896 /* SerializedScriptValue.h in Headers */,
 				93309E10099E64920056E581 /* SetNodeAttributeCommand.h in Headers */,
 				B8DBDB4C130B0F8A00F5CDB1 /* SetSelectionCommand.h in Headers */,
@@ -23448,6 +23447,7 @@
 				93500F3213FDE3BE0099EC24 /* NSScrollerImpDetails.h in Headers */,
 				D0A3A7311405A39800FB8ED3 /* ResourceLoaderOptions.h in Headers */,
 				BCE43897140B0051005E437E /* EventConstructors.h in Headers */,
+				E45322AC140CE267005A0F92 /* SelectorQuery.h in Headers */,
 				B10B6980140C174000BC1C26 /* WebVTTToken.h in Headers */,
 				B10B6982140C174000BC1C26 /* WebVTTTokenizer.h in Headers */,
 			);
@@ -25781,7 +25781,6 @@
 				371F4FFD0D25E7F300ECE0D5 /* SegmentedFontData.cpp in Sources */,
 				B2C3DA2E0D006C1D00EF6F26 /* SegmentedString.cpp in Sources */,
 				084AEBE40FB505FA0038483E /* SelectElement.cpp in Sources */,
-				BC7FA6820D1F167900DB22A9 /* SelectorNodeList.cpp in Sources */,
 				A75E497710752ACB00C9B896 /* SerializedScriptValue.cpp in Sources */,
 				93309E0F099E64920056E581 /* SetNodeAttributeCommand.cpp in Sources */,
 				B8DBDB4B130B0F8A00F5CDB1 /* SetSelectionCommand.cpp in Sources */,
@@ -26259,6 +26258,7 @@
 				1A1414B513A0F0500019996C /* WebKitFontFamilyNames.cpp in Sources */,
 				DF9AFD7313FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.mm in Sources */,
 				BCE4389A140B0073005E437E /* JSEventConstructors.cpp in Sources */,
+				E45322AB140CE267005A0F92 /* SelectorQuery.cpp in Sources */,
 				B10B6981140C174000BC1C26 /* WebVTTTokenizer.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

Modified: trunk/Source/WebCore/css/CSSStyleSelector.cpp (94088 => 94089)


--- trunk/Source/WebCore/css/CSSStyleSelector.cpp	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/css/CSSStyleSelector.cpp	2011-08-30 17:43:24 UTC (rev 94089)
@@ -875,9 +875,20 @@
 #endif
 }
 
-bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const
+bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element, bool isFastCheckableSelector) const
 {
     PseudoId dynamicPseudo = NOPSEUDO;
+    if (isFastCheckableSelector && !element->isSVGElement()) {
+        // fastCheckSelector assumes class and id match for the top selector.
+        if (sel->m_match == CSSSelector::Class) {
+            if (!(element->hasClass() && static_cast<StyledElement*>(element)->classNames().contains(sel->value())))
+                return false;
+        } else if (sel->m_match == CSSSelector::Id) {
+            if (!(element->hasID() && element->idForStyleResolution() == sel->value()))
+                return false;
+        }
+        return fastCheckSelector(sel, element);
+    }
     return checkSelector(sel, element, dynamicPseudo, false, false) == SelectorMatches;
 }
 
@@ -2012,17 +2023,6 @@
     const AtomicString& namespaceURI = selector->tag().namespaceURI();
     return namespaceURI == starAtom || namespaceURI == element->namespaceURI();
 }
-
-inline bool isFastCheckableSelector(const CSSSelector* selector)
-{
-    for (; selector; selector = selector->tagHistory()) {
-        if (selector->relation() != CSSSelector::Descendant && selector->relation() != CSSSelector::Child && selector->relation() != CSSSelector::SubSelector)
-            return false;
-        if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
-            return false;
-    }
-    return true;
-}
     
 template <bool checkValue(const Element*, AtomicStringImpl*)>
 inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement)
@@ -2116,6 +2116,17 @@
     return true;
 }
 
+bool CSSStyleSelector::SelectorChecker::isFastCheckableSelector(const CSSSelector* selector)
+{
+    for (; selector; selector = selector->tagHistory()) {
+        if (selector->relation() != CSSSelector::Descendant && selector->relation() != CSSSelector::Child && selector->relation() != CSSSelector::SubSelector)
+            return false;
+        if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
+            return false;
+    }
+    return true;
+}
+
 // Recursive check of selectors and combinators
 // It can return 3 different values:
 // * SelectorMatches         - the selector matches the element e
@@ -3035,7 +3046,7 @@
     , m_selector(selector)
     , m_specificity(selector->specificity())
     , m_position(position)
-    , m_hasFastCheckableSelector(isFastCheckableSelector(selector))
+    , m_hasFastCheckableSelector(CSSStyleSelector::SelectorChecker::isFastCheckableSelector(selector))
     , m_hasMultipartSelector(selector->tagHistory())
     , m_hasTopSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
 {

Modified: trunk/Source/WebCore/css/CSSStyleSelector.h (94088 => 94089)


--- trunk/Source/WebCore/css/CSSStyleSelector.h	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/css/CSSStyleSelector.h	2011-08-30 17:43:24 UTC (rev 94089)
@@ -275,10 +275,11 @@
         public:
             SelectorChecker(Document*, bool strictParsing);
 
-            bool checkSelector(CSSSelector*, Element*) const;
+            bool checkSelector(CSSSelector*, Element*, bool isFastCheckableSelector = false) const;
             SelectorMatch checkSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
             bool checkOneSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle*, RenderStyle* elementParentStyle) const;
             bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const;
+            static bool isFastCheckableSelector(const CSSSelector*);
             static bool fastCheckSelector(const CSSSelector*, const Element*);
 
             EInsideLink determineLinkState(Element* element) const;

Modified: trunk/Source/WebCore/dom/DOMAllInOne.cpp (94088 => 94089)


--- trunk/Source/WebCore/dom/DOMAllInOne.cpp	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/dom/DOMAllInOne.cpp	2011-08-30 17:43:24 UTC (rev 94089)
@@ -115,7 +115,7 @@
 #include "ScriptRunner.cpp"
 #include "ScriptableDocumentParser.cpp"
 #include "SelectElement.cpp"
-#include "SelectorNodeList.cpp"
+#include "SelectorQuery.cpp"
 #include "ShadowContentElement.cpp"
 #include "ShadowInclusionSelector.cpp"
 #include "ShadowRoot.cpp"

Modified: trunk/Source/WebCore/dom/Node.cpp (94088 => 94089)


--- trunk/Source/WebCore/dom/Node.cpp	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/dom/Node.cpp	2011-08-30 17:43:24 UTC (rev 94089)
@@ -81,7 +81,7 @@
 #include "RenderTextControl.h"
 #include "RenderView.h"
 #include "ScopedEventQueue.h"
-#include "SelectorNodeList.h"
+#include "SelectorQuery.h"
 #include "ShadowRoot.h"
 #include "StaticNodeList.h"
 #include "TagNodeList.h"
@@ -1765,29 +1765,9 @@
         ec = NAMESPACE_ERR;
         return 0;
     }
-
-    CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
-
-    // FIXME: we could also optimize for the the [id="foo"] case
-    if (strictParsing && inDocument() && querySelectorList.hasOneSelector() && querySelectorList.first()->m_match == CSSSelector::Id) {
-        Element* element = treeScope()->getElementById(querySelectorList.first()->value());
-        if (element && (isDocumentNode() || element->isDescendantOf(this)) && selectorChecker.checkSelector(querySelectorList.first(), element))
-            return element;
-        return 0;
-    }
-
-    // FIXME: We can speed this up by implementing caching similar to the one use by getElementById
-    for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
-        if (n->isElementNode()) {
-            Element* element = static_cast<Element*>(n);
-            for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
-                if (selectorChecker.checkSelector(selector, element))
-                    return element;
-            }
-        }
-    }
     
-    return 0;
+    SelectorQuery selectorQuery(this, querySelectorList);
+    return selectorQuery.queryFirst();
 }
 
 PassRefPtr<NodeList> Node::querySelectorAll(const String& selectors, ExceptionCode& ec)
@@ -1813,7 +1793,8 @@
         return 0;
     }
 
-    return createSelectorNodeList(this, querySelectorList);
+    SelectorQuery selectorQuery(this, querySelectorList);
+    return selectorQuery.queryAll();
 }
 
 Document *Node::ownerDocument() const

Deleted: trunk/Source/WebCore/dom/SelectorNodeList.cpp (94088 => 94089)


--- trunk/Source/WebCore/dom/SelectorNodeList.cpp	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/dom/SelectorNodeList.cpp	2011-08-30 17:43:24 UTC (rev 94089)
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "SelectorNodeList.h"
-
-#include "CSSSelector.h"
-#include "CSSSelectorList.h"
-#include "CSSStyleSelector.h"
-#include "Document.h"
-#include "Element.h"
-#include "HTMLNames.h"
-#include "StaticNodeList.h"
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-PassRefPtr<StaticNodeList> createSelectorNodeList(Node* rootNode, const CSSSelectorList& querySelectorList)
-{
-    Vector<RefPtr<Node> > nodes;
-    Document* document = rootNode->document();
-    CSSSelector* _onlySelector_ = querySelectorList.hasOneSelector() ? querySelectorList.first() : 0;
-    bool strictParsing = !document->inQuirksMode();
-
-    CSSStyleSelector::SelectorChecker selectorChecker(document, strictParsing);
-
-    if (strictParsing && rootNode->inDocument() && onlySelector && onlySelector->m_match == CSSSelector::Id && !document->containsMultipleElementsWithId(onlySelector->value())) {
-        Element* element = document->getElementById(onlySelector->value());
-        if (element && (rootNode->isDocumentNode() || element->isDescendantOf(rootNode)) && selectorChecker.checkSelector(onlySelector, element))
-            nodes.append(element);
-    } else {
-        for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode)) {
-            if (n->isElementNode()) {
-                Element* element = static_cast<Element*>(n);
-                for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
-                    if (selectorChecker.checkSelector(selector, element)) {
-                        nodes.append(n);
-                        break;
-                    }
-                }
-            }
-        }
-    }
-    
-    return StaticNodeList::adopt(nodes);
-}
-
-} // namespace WebCore

Deleted: trunk/Source/WebCore/dom/SelectorNodeList.h (94088 => 94089)


--- trunk/Source/WebCore/dom/SelectorNodeList.h	2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/dom/SelectorNodeList.h	2011-08-30 17:43:24 UTC (rev 94089)
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SelectorNodeList_h
-#define SelectorNodeList_h
-
-#include <wtf/PassRefPtr.h>
-
-namespace WebCore {
-
-    class CSSSelectorList;
-    class Node;
-    class StaticNodeList;
-
-    PassRefPtr<StaticNodeList> createSelectorNodeList(Node* rootNode, const CSSSelectorList&);
-
-} // namespace WebCore
-
-#endif // SelectorNodeList_h

Added: trunk/Source/WebCore/dom/SelectorQuery.cpp (0 => 94089)


--- trunk/Source/WebCore/dom/SelectorQuery.cpp	                        (rev 0)
+++ trunk/Source/WebCore/dom/SelectorQuery.cpp	2011-08-30 17:43:24 UTC (rev 94089)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SelectorQuery.h"
+
+#include "CSSSelectorList.h"
+#include "Document.h"
+#include "StaticNodeList.h"
+#include "StyledElement.h"
+
+namespace WebCore {
+
+SelectorQuery::SelectorQuery(Node* rootNode, const CSSSelectorList& selectorList)
+    : m_rootNode(rootNode)
+    , m_selectorChecker(rootNode->document(), !rootNode->document()->inQuirksMode())
+{
+    for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
+        m_selectors.append(SelectorData(selector, CSSStyleSelector::SelectorChecker::isFastCheckableSelector(selector)));
+}
+    
+PassRefPtr<NodeList> SelectorQuery::queryAll() const
+{
+    Vector<RefPtr<Node> > result;
+    execute<false>(result);
+    return StaticNodeList::adopt(result);
+}
+
+PassRefPtr<Element> SelectorQuery::queryFirst() const 
+{ 
+    Vector<RefPtr<Node> > result;
+    execute<true>(result);
+    if (result.isEmpty())
+        return 0;
+    ASSERT(result.size() == 1);
+    ASSERT(result.first()->isElementNode());
+    return static_cast<Element*>(result.first().get());
+}
+
+bool SelectorQuery::canUseIdLookup() const
+{
+    // We need to return the matches in document order. To use id lookup while there is possiblity of multiple matches
+    // we would need to sort the results. For now, just traverse the document in that case.
+    if (m_selectors.size() != 1)
+        return false;
+    if (m_selectors[0].selector->m_match != CSSSelector::Id)
+        return false;
+    if (!m_rootNode->inDocument())
+        return false;
+    if (m_rootNode->document()->inQuirksMode())
+        return false;
+    if (m_rootNode->document()->containsMultipleElementsWithId(m_selectors[0].selector->value()))
+        return false;
+    return true;
+}
+
+template <bool firstMatchOnly>
+void SelectorQuery::execute(Vector<RefPtr<Node> >& matchedElements) const
+{
+    if (canUseIdLookup()) {
+        ASSERT(m_selectors.size() == 1);
+        CSSSelector* selector = m_selectors[0].selector;
+        Element* element = m_rootNode->document()->getElementById(selector->value());
+        if (!element || !(m_rootNode->isDocumentNode() || element->isDescendantOf(m_rootNode)))
+            return;
+        if (m_selectorChecker.checkSelector(selector, element, m_selectors[0].isFastCheckable))
+            matchedElements.append(element);
+        return;
+    }
+    
+    unsigned selectorCount = m_selectors.size();
+    
+    Node* n = m_rootNode->firstChild();
+    while (n) {
+        if (n->isElementNode()) {
+            Element* element = static_cast<Element*>(n);
+            for (unsigned i = 0; i < selectorCount; ++i) {
+                if (m_selectorChecker.checkSelector(m_selectors[i].selector, element, m_selectors[i].isFastCheckable)) {
+                    matchedElements.append(element);
+                    if (firstMatchOnly)
+                        return;
+                    break;
+                }
+            }
+            if (element->firstChild()) {
+                n = element->firstChild();
+                continue;
+            }
+        }
+        while (!n->nextSibling()) {
+            n = n->parentNode();
+            if (n == m_rootNode)
+                return;
+        }
+        n = n->nextSibling();
+    }
+}
+
+}

Added: trunk/Source/WebCore/dom/SelectorQuery.h (0 => 94089)


--- trunk/Source/WebCore/dom/SelectorQuery.h	                        (rev 0)
+++ trunk/Source/WebCore/dom/SelectorQuery.h	2011-08-30 17:43:24 UTC (rev 94089)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SelectorQuery_h
+#define SelectorQuery_h
+
+#include "CSSStyleSelector.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+    
+class Node;
+class NodeList;
+class Element;
+class CSSSelector;
+class CSSSelectorList;
+
+class SelectorQuery {
+public:
+    SelectorQuery(Node* rootNode, const CSSSelectorList&);
+    
+    PassRefPtr<NodeList> queryAll() const;
+    PassRefPtr<Element> queryFirst() const;
+
+private:
+    bool canUseIdLookup() const;
+
+    template <bool firstMatchOnly>
+    void execute(Vector<RefPtr<Node> >&) const;
+    
+    struct SelectorData {
+        SelectorData(CSSSelector* selector, bool isFastCheckable) : selector(selector), isFastCheckable(isFastCheckable) { }
+        CSSSelector* selector;
+        bool isFastCheckable;
+    };
+    Node* m_rootNode;
+    Vector<SelectorData> m_selectors;
+    CSSStyleSelector::SelectorChecker m_selectorChecker;
+};
+
+}
+
+#endif
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to