Skip to content

Instantly share code, notes, and snippets.

@Constellation
Created September 12, 2014 18:28
Show Gist options
  • Select an option

  • Save Constellation/b3ad0e9158c5b265232a to your computer and use it in GitHub Desktop.

Select an option

Save Constellation/b3ad0e9158c5b265232a to your computer and use it in GitHub Desktop.
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 1948fa9..392decf 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2014-09-12 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ CSS JIT: Apply CSS JIT to SelectorQuery with multiple selectors
+ https://bugs.webkit.org/show_bug.cgi?id=135255
+
+ Reviewed by NOBODY (OOPS!).
+
+ * fast/selectors/querySelector-multiple-selectors-expected.txt: Added.
+ * fast/selectors/querySelector-multiple-selectors.html: Added.
+
2014-09-11 Alexey Proskuryakov <ap@apple.com>
fast/forms/submit-to-blank-multiple-times.html crashes with JSC_slowPathAllocsBetweenGCs
diff --git a/LayoutTests/fast/selectors/querySelector-multiple-selectors-expected.txt b/LayoutTests/fast/selectors/querySelector-multiple-selectors-expected.txt
new file mode 100644
index 0000000..c1d6ed7
--- /dev/null
+++ b/LayoutTests/fast/selectors/querySelector-multiple-selectors-expected.txt
@@ -0,0 +1,17 @@
+Test cases when the multiple selectors are provided
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.body.querySelectorAll("t0, t1").length is 4
+PASS document.body.querySelectorAll("#t2, t3").length is 1
+PASS document.body.querySelectorAll("t4> #t5, t6 t7.ok").length is 2
+PASS document.body.querySelectorAll("t8 + t9, t10 t11.ok").length is 1
+PASS document.body.querySelectorAll("t8 + t9, t10 t11.ok").length is 1
+PASS document.body.querySelectorAll(".t12, .t13, .t14, .t15").length is 2
+CSS JIT compile may fail, fallback to the slow path.
+PASS document.body.querySelectorAll(".t16, .t17>t18:nth-last-child(1)").length is 3
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/selectors/querySelector-multiple-selectors.html b/LayoutTests/fast/selectors/querySelector-multiple-selectors.html
new file mode 100644
index 0000000..c5ff97e
--- /dev/null
+++ b/LayoutTests/fast/selectors/querySelector-multiple-selectors.html
@@ -0,0 +1,69 @@
+<!doctype html>
+<html id=htmlDocument>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<div style="display:none">
+<t0>
+ <t0></t0>
+</t0>
+<t1>
+ <t0></t0>
+</t1>
+
+
+<t3></t3>
+
+<t4>
+ <t5 id="t5"></t5>
+</t4>
+<t6>
+ <ng>
+ <t7 class="ok"></t7>
+ </ng>
+</t6>
+
+<t8></t8>
+<t9></t9>
+<t9></t9>
+<t10>
+ <t11 class="ng"></t11>
+</t10>
+
+<ok class="t12"></ok>
+<ok class="t13 t14 t15"></ok>
+
+<ok class="t16"></ok>
+<ok class="t17">
+ <t18></t18>
+ <t18></t18>
+ <t18></t18>
+ <t18></t18>
+ <t18></t18>
+</ok>
+<ok class="t17">
+ <t18></t18>
+ <t18></t18>
+ <t18></t18>
+ <t18></t18>
+ <t18></t18>
+</ok>
+
+</div>
+</body>
+<script>
+description('Test cases when the multiple selectors are provided');
+
+shouldBe('document.body.querySelectorAll("t0, t1").length', '4');
+shouldBe('document.body.querySelectorAll("#t2, t3").length', '1');
+shouldBe('document.body.querySelectorAll("t4> #t5, t6 t7.ok").length', '2');
+shouldBe('document.body.querySelectorAll("t8 + t9, t10 t11.ok").length', '1');
+shouldBe('document.body.querySelectorAll("t8 + t9, t10 t11.ok").length', '1');
+shouldBe('document.body.querySelectorAll(".t12, .t13, .t14, .t15").length', '2');
+
+debug('CSS JIT compile may fail, fallback to the slow path.')
+shouldBe('document.body.querySelectorAll(".t16, .t17>t18:nth-last-child(1)").length', '3');
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index b744640..a9770cd 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,33 @@
+2014-09-12 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ CSS JIT: Apply CSS JIT to SelectorQuery with multiple selectors
+ https://bugs.webkit.org/show_bug.cgi?id=135255
+
+ Reviewed by NOBODY (OOPS!).
+
+ After dropping SelectorCheckerFastPath, Dromaeo cssquery-jquery test
+ result becomes significantly worse. 400.26/s to 348.16/s, 13%
+ performance regression.
+
+ Investigated the cause of it and we found that the test results for
+ querySelector with multiple selectors causes performance regressions.
+
+ To solve this, we attempt to JIT compile all selectors in multiple
+ selectors. And if compiling some selectors is failed, SelectorQuery
+ fallbacks to the slower implementation.
+
+ This change improves the performance. After applying this patch,
+ cssquery-jquery test result becomes 418.71/s, 4.61% better than the
+ previous good performance case.
+
+ Test: fast/selectors/querySelector-multiple-selectors.html
+
+ * dom/SelectorQuery.cpp:
+ (WebCore::SelectorDataList::SelectorDataList):
+ (WebCore::SelectorDataList::executeCompiledSingleMultiSelectorData):
+ (WebCore::SelectorDataList::execute):
+ * dom/SelectorQuery.h:
+
2014-09-11 Ryuan Choi <ryuan.choi@gmail.com>
Unreviewed build fix attempt on windows port since r173553.
diff --git a/Source/WebCore/dom/SelectorQuery.cpp b/Source/WebCore/dom/SelectorQuery.cpp
index c9dd60e..03aa542 100644
--- a/Source/WebCore/dom/SelectorQuery.cpp
+++ b/Source/WebCore/dom/SelectorQuery.cpp
@@ -108,7 +108,7 @@ static IdMatchingType findIdMatchingType(const CSSSelector& firstSelector)
}
}
} else
- m_matchType = MultipleSelectorMatch;
+ m_matchType = CompilableMultipleSelectorMatch;
}
inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData, Element& element, const ContainerNode& rootNode) const
@@ -389,6 +389,37 @@ ALWAYS_INLINE void SelectorDataList::executeCompiledSelectorCheckerWithCheckingC
}
}
+template <typename SelectorQueryTrait>
+ALWAYS_INLINE void SelectorDataList::executeCompiledSingleMultiSelectorData(const ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
+{
+ SelectorChecker::CheckingContext checkingContext(SelectorChecker::Mode::QueryingRules);
+ checkingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode;
+ unsigned selectorCount = m_selectors.size();
+ for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) {
+ for (unsigned i = 0; i < selectorCount; ++i) {
+#if CSS_SELECTOR_JIT_PROFILING
+ m_selectors[i].compiledSelectorUsed();
+#endif
+ bool matched = false;
+ void* compiledSelectorChecker = m_selectors[i].compiledSelectorCodeRef.code().executableAddress();
+ if (m_selectors[i].compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker) {
+ SelectorCompiler::SimpleSelectorChecker selectorChecker = SelectorCompiler::simpleSelectorCheckerFunction(compiledSelectorChecker, m_selectors[i].compilationStatus);
+ matched = selectorChecker(&element);
+ } else {
+ ASSERT(m_selectors[i].compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
+ SelectorCompiler::SelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::selectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, m_selectors[i].compilationStatus);
+ matched = selectorChecker(&element, &checkingContext);
+ }
+ if (matched) {
+ SelectorQueryTrait::appendOutputForElement(output, &element);
+ if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
+ return;
+ break;
+ }
+ }
+ }
+}
+
static bool isCompiledSelector(SelectorCompilationStatus compilationStatus)
{
return compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker || compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext;
@@ -489,7 +520,34 @@ ALWAYS_INLINE void SelectorDataList::execute(ContainerNode& rootNode, typename S
case ClassNameMatch:
executeSingleClassNameSelectorData<SelectorQueryTrait>(*searchRootNode, m_selectors.first(), output);
break;
+ case CompilableMultipleSelectorMatch:
+#if ENABLE(CSS_SELECTOR_JIT)
+ {
+ unsigned selectorCount = m_selectors.size();
+ for (unsigned i = 0; i < selectorCount; ++i) {
+ if (!compileSelector(m_selectors[i], *searchRootNode)) {
+ m_matchType = MultipleSelectorMatch;
+ goto MultipleSelectorMatch;
+ }
+ }
+ m_matchType = CompiledMultipleSelectorMatch;
+ goto CompiledMultipleSelectorMatch;
+#else
+ FALLTHROUGH;
+#endif // ENABLE(CSS_SELECTOR_JIT)
+ }
+ case CompiledMultipleSelectorMatch:
+#if ENABLE(CSS_SELECTOR_JIT)
+ CompiledMultipleSelectorMatch:
+ executeCompiledSingleMultiSelectorData<SelectorQueryTrait>(*searchRootNode, output);
+ break;
+#else
+ FALLTHROUGH;
+#endif // ENABLE(CSS_SELECTOR_JIT)
case MultipleSelectorMatch:
+#if ENABLE(CSS_SELECTOR_JIT)
+ MultipleSelectorMatch:
+#endif
executeSingleMultiSelectorData<SelectorQueryTrait>(*searchRootNode, output);
break;
}
diff --git a/Source/WebCore/dom/SelectorQuery.h b/Source/WebCore/dom/SelectorQuery.h
index c075be3..a0f4bbc 100644
--- a/Source/WebCore/dom/SelectorQuery.h
+++ b/Source/WebCore/dom/SelectorQuery.h
@@ -89,6 +89,7 @@ class SelectorDataList {
#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;
+ template <typename SelectorQueryTrait> void executeCompiledSingleMultiSelectorData(const ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const;
static bool compileSelector(const SelectorData&, const ContainerNode& rootNode);
#endif // ENABLE(CSS_SELECTOR_JIT)
@@ -96,8 +97,10 @@ class SelectorDataList {
mutable enum MatchType {
CompilableSingle,
CompilableSingleWithRootFilter,
+ CompilableMultipleSelectorMatch,
CompiledSingle,
CompiledSingleWithRootFilter,
+ CompiledMultipleSelectorMatch,
SingleSelector,
RightMostWithIdMatch,
TagNameMatch,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment