Title: [169569] trunk
Revision
169569
Author
commit-qu...@webkit.org
Date
2014-06-03 14:26:50 -0700 (Tue, 03 Jun 2014)

Log Message

CSS JIT: add support for the "any" pseudo class
https://bugs.webkit.org/show_bug.cgi?id=133473

Patch by Yusuke Suzuki <utatane....@gmail.com> on 2014-06-03
Reviewed by Benjamin Poulain.

Add support for the :any pseudo class.

Source/WebCore:
Test: fast/selectors/pseudo-class-any.html

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::addPseudoClassType):
(WebCore::SelectorCompiler::minimumRegisterRequirements):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatchesAnyPseudoClass):

LayoutTests:
* fast/selectors/pseudo-class-any-expected.txt: Added.
* fast/selectors/pseudo-class-any.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (169568 => 169569)


--- trunk/LayoutTests/ChangeLog	2014-06-03 21:09:07 UTC (rev 169568)
+++ trunk/LayoutTests/ChangeLog	2014-06-03 21:26:50 UTC (rev 169569)
@@ -1,3 +1,15 @@
+2014-06-03  Yusuke Suzuki  <utatane....@gmail.com>
+
+        CSS JIT: add support for the "any" pseudo class
+        https://bugs.webkit.org/show_bug.cgi?id=133473
+
+        Reviewed by Benjamin Poulain.
+
+        Add support for the :any pseudo class.
+
+        * fast/selectors/pseudo-class-any-expected.txt: Added.
+        * fast/selectors/pseudo-class-any.html: Added.
+
 2014-06-02  Jer Noble  <jer.no...@apple.com>
 
         Update PlatformTimeRanges to use MediaTime rather than doubles for time values.

Added: trunk/LayoutTests/fast/selectors/pseudo-class-any-expected.txt (0 => 169569)


--- trunk/LayoutTests/fast/selectors/pseudo-class-any-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/pseudo-class-any-expected.txt	2014-06-03 21:26:50 UTC (rev 169569)
@@ -0,0 +1,41 @@
+The pseudo class :any
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+simple :any selector list matched.
+PASS getComputedStyle(document.getElementById("target1")).backgroundColor is "rgb(1, 2, 3)"
+simple :any selector list matched.
+PASS getComputedStyle(document.getElementById("target2")).backgroundColor is "rgb(1, 2, 3)"
+simple :any selector unmatched.
+PASS getComputedStyle(document.getElementById("target3")).backgroundColor is "rgb(0, 0, 0)"
+multiple :any selector list matched.
+PASS getComputedStyle(document.getElementById("target4")).backgroundColor is "rgb(2, 3, 4)"
+multiple :any selector list matched.
+PASS getComputedStyle(document.getElementById("target5")).backgroundColor is "rgb(2, 3, 4)"
+multiple :any selector list unmatched.
+PASS getComputedStyle(document.getElementById("target6")).backgroundColor is "rgb(0, 0, 0)"
+multiple :any selector list unmatched.
+PASS getComputedStyle(document.getElementById("target7")).backgroundColor is "rgb(0, 0, 0)"
+multiple :any selector list unmatched.
+PASS getComputedStyle(document.getElementById("target8")).backgroundColor is "rgb(0, 0, 0)"
+simple :any selector list including :not matched.
+PASS getComputedStyle(document.getElementById("target9")).backgroundColor is "rgb(3, 4, 5)"
+simple :any selector list including :not matched.
+PASS getComputedStyle(document.getElementById("target10")).backgroundColor is "rgb(3, 4, 5)"
+simple :any selector list including :not matched.
+PASS getComputedStyle(document.getElementById("target11")).backgroundColor is "rgb(3, 4, 5)"
+simple :any selector list including :not unmatched.
+PASS getComputedStyle(document.getElementById("target12")).backgroundColor is "rgb(0, 0, 0)"
+simple :any selector list including :not unmatched.
+PASS getComputedStyle(document.getElementById("target13")).backgroundColor is "rgb(0, 0, 0)"
+:any selector including attributes matched.
+PASS getComputedStyle(document.getElementById("target14")).backgroundColor is "rgb(4, 5, 6)"
+:any selector including attributes matched.
+PASS getComputedStyle(document.getElementById("target15")).backgroundColor is "rgb(4, 5, 6)"
+:any selector including attributes unmatched.
+PASS getComputedStyle(document.getElementById("target16")).backgroundColor is "rgb(0, 0, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/pseudo-class-any.html (0 => 169569)


--- trunk/LayoutTests/fast/selectors/pseudo-class-any.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/pseudo-class-any.html	2014-06-03 21:26:50 UTC (rev 169569)
@@ -0,0 +1,183 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+span.target {
+    background-color:rgb(0,0,0);
+}
+
+a:-webkit-any(.house, .horse) span.target {
+    background-color:rgb(1,2,3);
+}
+
+b.rabbit:-webkit-any(.house, .horse):-webkit-any(.cocoa, .cappuccino) span.target {
+    background-color:rgb(2,3,4);
+}
+
+c.rabbit:-webkit-any(.house, :not(.horse)) span.target {
+    background-color:rgb(3,4,5);
+}
+
+/* Maximum register case */
+d > d:-webkit-any([rel="drink"][data-cocoa][data-cappuccino], .ok) > d > d span.target {
+    background-color:rgb(4,5,6);
+}
+</style>
+</head>
+<body>
+<div style="display:none">
+    <!-- a:any(.house, .horse) span.target -->
+    <test1>
+        <a class="house">
+            <span class="target" id="target1"></span>
+        </a>
+
+        <a class="house">
+            <span class="target" id="target2"></span>
+        </a>
+
+        <a>
+            <span class="target" id="target3"></span>
+        </a>
+    </test1>
+
+    <!-- b.rabbit:-webkit-any(.house, .horse):-webkit-any(.cocoa, .cappuccino) span.target -->
+    <test2>
+        <b class="rabbit horse cocoa">
+            <span class="target" id="target4"></span>
+        </b>
+
+        <b class="rabbit house cappuccino">
+            <span class="target" id="target5"></span>
+        </b>
+
+        <b class="rabbit house horse">
+            <span class="target" id="target6"></span>
+        </b>
+
+        <b class="horse cocoa">
+            <span class="target" id="target7"></span>
+        </b>
+
+        <b class="rabbit cocoa cappuccino">
+            <span class="target" id="target8"></span>
+        </b>
+    </test2>
+
+    <!-- c.rabbit:-webkit-any(.house, :not(.horse)) span.target -->
+    <test3>
+        <c class="rabbit house">
+            <span class="target" id="target9"></span>
+        </c>
+
+        <c class="rabbit cappuccino">
+            <span class="target" id="target10"></span>
+        </c>
+
+        <c class="rabbit">
+            <span class="target" id="target11"></span>
+        </c>
+
+        <c class="rabbit horse">
+            <span class="target" id="target12"></span>
+        </c>
+
+        <c class="house">
+            <span class="target" id="target13"></span>
+        </c>
+    </test3>
+
+    <!-- d > d:-webkit-any([rel="drink"][data-cocoa][data-cappuccino], .ok) > d > d span.target -->
+    <test4>
+        <d>  <!-- Matched. -->
+            <d rel="drink" data-cocoa data-cappuccino>
+                <d data-cocoa>  <!-- Failed. Backtracking from the tail. -->
+                    <d>
+                        <d>
+                            <span class="target" id="target14"></span>
+                        </d>
+                    </d>
+                </d>
+            </d>
+        </d>
+
+        <d>  <!-- Matched. -->
+            <d class="ok">
+                <d data-cocoa>  <!-- Failed. Backtracking from the tail. -->
+                    <d>
+                        <d>
+                            <span class="target" id="target15"></span>
+                        </d>
+                    </d>
+                </d>
+            </d>
+        </d>
+
+        <a>  <!-- Failed. -->
+            <d class="ok">
+                <d data-cocoa>  <!-- Failed. Backtracking from the tail. -->
+                    <d>
+                        <d>
+                            <span class="target" id="target16"></span>
+                        </d>
+                    </d>
+                </d>
+            </d>
+        </a>
+    </test4>
+</div>
+</body>
+<script>
+description('The pseudo class :any');
+
+debug("simple :any selector list matched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target1")).backgroundColor', 'rgb(1, 2, 3)');
+
+debug("simple :any selector list matched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target2")).backgroundColor', 'rgb(1, 2, 3)');
+
+debug("simple :any selector unmatched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target3")).backgroundColor', 'rgb(0, 0, 0)');
+
+debug("multiple :any selector list matched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target4")).backgroundColor', 'rgb(2, 3, 4)');
+
+debug("multiple :any selector list matched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target5")).backgroundColor', 'rgb(2, 3, 4)');
+
+debug("multiple :any selector list unmatched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target6")).backgroundColor', 'rgb(0, 0, 0)');
+
+debug("multiple :any selector list unmatched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target7")).backgroundColor', 'rgb(0, 0, 0)');
+
+debug("multiple :any selector list unmatched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target8")).backgroundColor', 'rgb(0, 0, 0)');
+
+debug("simple :any selector list including :not matched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target9")).backgroundColor', 'rgb(3, 4, 5)');
+
+debug("simple :any selector list including :not matched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target10")).backgroundColor', 'rgb(3, 4, 5)');
+
+debug("simple :any selector list including :not matched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target11")).backgroundColor', 'rgb(3, 4, 5)');
+
+debug("simple :any selector list including :not unmatched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target12")).backgroundColor', 'rgb(0, 0, 0)');
+
+debug("simple :any selector list including :not unmatched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target13")).backgroundColor', 'rgb(0, 0, 0)');
+
+debug(":any selector including attributes matched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target14")).backgroundColor', 'rgb(4, 5, 6)');
+
+debug(":any selector including attributes matched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target15")).backgroundColor', 'rgb(4, 5, 6)');
+
+debug(":any selector including attributes unmatched.");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target16")).backgroundColor', 'rgb(0, 0, 0)');
+</script>
+<script src=""
+</html>

Modified: trunk/Source/WebCore/ChangeLog (169568 => 169569)


--- trunk/Source/WebCore/ChangeLog	2014-06-03 21:09:07 UTC (rev 169568)
+++ trunk/Source/WebCore/ChangeLog	2014-06-03 21:26:50 UTC (rev 169569)
@@ -1,3 +1,20 @@
+2014-06-03  Yusuke Suzuki  <utatane....@gmail.com>
+
+        CSS JIT: add support for the "any" pseudo class
+        https://bugs.webkit.org/show_bug.cgi?id=133473
+
+        Reviewed by Benjamin Poulain.
+
+        Add support for the :any pseudo class.
+
+        Test: fast/selectors/pseudo-class-any.html
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::addPseudoClassType):
+        (WebCore::SelectorCompiler::minimumRegisterRequirements):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatchesAnyPseudoClass):
+
 2014-06-02  Jer Noble  <jer.no...@apple.com>
 
         Update PlatformTimeRanges to use MediaTime rather than doubles for time values.

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (169568 => 169569)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-06-03 21:09:07 UTC (rev 169568)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-06-03 21:26:50 UTC (rev 169569)
@@ -157,6 +157,7 @@
     Vector<AttributeMatchingInfo> attributes;
     Vector<std::pair<int, int>> nthChildFilters;
     Vector<SelectorFragment> notFilters;
+    Vector<Vector<SelectorFragment>> anyFilters;
 
     bool inFunctionalPseudoClass;
 };
@@ -229,6 +230,7 @@
     void generateElementIsLink(Assembler::JumpList& failureCases);
     void generateElementIsNthChild(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementMatchesNotPseudoClass(Assembler::JumpList& failureCases, const SelectorFragment&);
+    void generateElementMatchesAnyPseudoClass(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementIsRoot(Assembler::JumpList& failureCases);
     void generateElementIsTarget(Assembler::JumpList& failureCases);
 
@@ -441,6 +443,42 @@
             return functionType;
         }
 
+    case CSSSelector::PseudoClassAny:
+        {
+            Vector<SelectorFragment> anyFragments;
+            FunctionType functionType = FunctionType::SimpleSelectorChecker;
+            for (const CSSSelector* rootSelector = selector.selectorList()->first(); rootSelector; rootSelector = CSSSelectorList::next(rootSelector)) {
+                SelectorFragmentList fragmentList;
+                FunctionType subFunctionType = constructFragments(rootSelector, selectorContext, fragmentList);
+
+                // Since this fragment always unmatch against the element, don't insert it to anyFragments.
+                if (subFunctionType == FunctionType::CannotMatchAnything)
+                    continue;
+
+                if (subFunctionType == FunctionType::CannotCompile)
+                    return FunctionType::CannotCompile;
+
+                // :any() may not contain complex selectors which have combinators.
+                ASSERT(fragmentList.size() == 1);
+                if (fragmentList.size() != 1)
+                    return FunctionType::CannotCompile;
+
+                SelectorFragment subFragment = fragmentList.first();
+                subFragment.inFunctionalPseudoClass = true;
+                anyFragments.append(subFragment);
+                functionType = mostRestrictiveFunctionType(functionType, subFunctionType);
+            }
+
+            // Since all fragments in :any() cannot match anything, this :any() filter cannot match anything.
+            if (anyFragments.isEmpty())
+                return FunctionType::CannotMatchAnything;
+
+            ASSERT(!anyFragments.isEmpty());
+            fragment.anyFilters.append(anyFragments);
+
+            return functionType;
+        }
+
     default:
         break;
     }
@@ -594,6 +632,15 @@
         unsigned notFilterMinimum = minimumRegisterRequirements(subFragment) + backtrackingRegisterRequirements;
         minimum = std::max(minimum, notFilterMinimum);
     }
+
+    // :any pseudo class filters cause some register pressure.
+    for (const auto& subFragments : selectorFragment.anyFilters) {
+        for (const SelectorFragment& subFragment : subFragments) {
+            unsigned anyFilterMinimum = minimumRegisterRequirements(subFragment) + backtrackingRegisterRequirements;
+            minimum = std::max(minimum, anyFilterMinimum);
+        }
+    }
+
     return minimum;
 }
 
@@ -1654,6 +1701,8 @@
         generateElementIsNthChild(matchingPostTagNameFailureCases, fragment);
     if (!fragment.notFilters.isEmpty())
         generateElementMatchesNotPseudoClass(matchingPostTagNameFailureCases, fragment);
+    if (!fragment.anyFilters.isEmpty())
+        generateElementMatchesAnyPseudoClass(matchingPostTagNameFailureCases, fragment);
 }
 
 void SelectorCodeGenerator::generateElementDataMatching(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
@@ -2566,6 +2615,26 @@
     }
 }
 
+void SelectorCodeGenerator::generateElementMatchesAnyPseudoClass(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
+{
+    for (const auto& subFragments : fragment.anyFilters) {
+        RELEASE_ASSERT(!subFragments.isEmpty());
+
+        // Don't handle the last fragment in this loop.
+        Assembler::JumpList successCases;
+        for (unsigned i = 0; i < subFragments.size() - 1; ++i) {
+            Assembler::JumpList localFailureCases;
+            generateElementMatching(localFailureCases, localFailureCases, subFragments[i]);
+            successCases.append(m_assembler.jump());
+            localFailureCases.link(&m_assembler);
+        }
+
+        // At the last fragment, optimize the failure jump to jump to the non-local failure directly.
+        generateElementMatching(failureCases, failureCases, subFragments.last());
+        successCases.link(&m_assembler);
+    }
+}
+
 void SelectorCodeGenerator::generateElementIsRoot(Assembler::JumpList& failureCases)
 {
     LocalRegister document(m_registerAllocator);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to