Title: [165300] trunk
Revision
165300
Author
[email protected]
Date
2014-03-07 16:40:11 -0800 (Fri, 07 Mar 2014)

Log Message

Traversal failure in a direct adjacent chain with tail backtracking lacks the path to clear the tail
https://bugs.webkit.org/show_bug.cgi?id=129863

Reviewed by Gavin Barraclough.

Source/WebCore: 

Direct adjacent backtracking use the stack to push the backtracking entry point and recover from there.
In case of traversal failure, their is no point in recovering from the indirect adjancent entry point and
we should clear entry point from the stack (which is the purpose of the tail).

The adjancent tail was missing the part for clearing the stack in one case.

The case with adjancent backtracking inside descendant backtracing was doing everything right. This patch
generalize this code and the correct tail is fully generated by generateAdjacentBacktrackingTail().

JumpToClearAdjacentDescendantTail becomes JumpToClearAdjacentTail, and this new backtracking state is added
to the missing traversal action.

Test: fast/selectors/long-adjacent-backtracking.html

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::solveBacktrackingAction):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::linkFailures):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateAdjacentBacktrackingTail):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateBacktrackingTailsIfNeeded):

LayoutTests: 

Test the faulty case.

* fast/selectors/long-adjacent-backtracking-expected.txt: Added.
* fast/selectors/long-adjacent-backtracking.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (165299 => 165300)


--- trunk/LayoutTests/ChangeLog	2014-03-08 00:33:55 UTC (rev 165299)
+++ trunk/LayoutTests/ChangeLog	2014-03-08 00:40:11 UTC (rev 165300)
@@ -1,3 +1,15 @@
+2014-03-07  Benjamin Poulain  <[email protected]>
+
+        Traversal failure in a direct adjacent chain with tail backtracking lacks the path to clear the tail
+        https://bugs.webkit.org/show_bug.cgi?id=129863
+
+        Reviewed by Gavin Barraclough.
+
+        Test the faulty case.
+
+        * fast/selectors/long-adjacent-backtracking-expected.txt: Added.
+        * fast/selectors/long-adjacent-backtracking.html: Added.
+
 2014-03-07  Bear Travis  <[email protected]>
 
         [CSS Shapes] Correctly serialize ellipse positions

Added: trunk/LayoutTests/fast/selectors/long-adjacent-backtracking-expected.txt (0 => 165300)


--- trunk/LayoutTests/fast/selectors/long-adjacent-backtracking-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/long-adjacent-backtracking-expected.txt	2014-03-08 00:40:11 UTC (rev 165300)
@@ -0,0 +1,12 @@
+Test very long backtracking of a direct adjacent chain.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll("li.first+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li~li").length is 20
+PASS allItems.length is 41
+PASS coloredCount is 20
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/long-adjacent-backtracking.html (0 => 165300)


--- trunk/LayoutTests/fast/selectors/long-adjacent-backtracking.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/long-adjacent-backtracking.html	2014-03-08 00:40:11 UTC (rev 165300)
@@ -0,0 +1,75 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+li.first+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li~li {
+    background-color: rgb(1, 2, 3);
+}
+</style>
+</head>
+<body>
+<div style="display:none">
+    <ul id=targetTree>
+        <li class=first></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+        <li class=target></li>
+    </ul>
+</div>
+</body>
+<script>
+description('Test very long backtracking of a direct adjacent chain.');
+
+shouldBe('document.querySelectorAll("li.first+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li+li~li").length', '20');
+
+var allItems = document.getElementById('targetTree').querySelectorAll('li');
+var coloredCount = 0;
+for (var i = 0; i < allItems.length; ++i) {
+    if (getComputedStyle(allItems[i]).backgroundColor === 'rgb(1, 2, 3)')
+        coloredCount++;
+}
+
+shouldBe('allItems.length', '41');
+shouldBe('coloredCount', '20');
+
+</script>
+<script src=""
+</html>

Modified: trunk/Source/WebCore/ChangeLog (165299 => 165300)


--- trunk/Source/WebCore/ChangeLog	2014-03-08 00:33:55 UTC (rev 165299)
+++ trunk/Source/WebCore/ChangeLog	2014-03-08 00:40:11 UTC (rev 165300)
@@ -1,3 +1,31 @@
+2014-03-07  Benjamin Poulain  <[email protected]>
+
+        Traversal failure in a direct adjacent chain with tail backtracking lacks the path to clear the tail
+        https://bugs.webkit.org/show_bug.cgi?id=129863
+
+        Reviewed by Gavin Barraclough.
+
+        Direct adjacent backtracking use the stack to push the backtracking entry point and recover from there.
+        In case of traversal failure, their is no point in recovering from the indirect adjancent entry point and
+        we should clear entry point from the stack (which is the purpose of the tail).
+
+        The adjancent tail was missing the part for clearing the stack in one case.
+
+        The case with adjancent backtracking inside descendant backtracing was doing everything right. This patch
+        generalize this code and the correct tail is fully generated by generateAdjacentBacktrackingTail().
+
+        JumpToClearAdjacentDescendantTail becomes JumpToClearAdjacentTail, and this new backtracking state is added
+        to the missing traversal action.
+
+        Test: fast/selectors/long-adjacent-backtracking.html
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::solveBacktrackingAction):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::linkFailures):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateAdjacentBacktrackingTail):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateBacktrackingTailsIfNeeded):
+
 2014-03-07  Andreas Kling  <[email protected]>
 
         [Mac] Notify system malloc of fake memory pressure.

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (165299 => 165300)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-03-08 00:33:55 UTC (rev 165299)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-03-08 00:40:11 UTC (rev 165300)
@@ -61,8 +61,8 @@
     JumpToIndirectAdjacentEntryPoint,
     JumpToDescendantTreeWalkerEntryPoint,
     JumpToDescendantTail,
-    JumpToClearAdjacentDescendantTail,
-    JumpToDirectAdjacentTail
+    JumpToDirectAdjacentTail,
+    JumpToClearAdjacentTail
 };
 
 struct BacktrackingFlag {
@@ -161,9 +161,9 @@
     void markParentElementIfResolvingStyle(JSC::FunctionPtr);
 
     void linkFailures(Assembler::JumpList& globalFailureCases, BacktrackingAction, Assembler::JumpList& localFailureCases);
-    void generateAdjacentBacktrackingTail(StackAllocator& adjacentTailStack);
+    void generateAdjacentBacktrackingTail(Assembler::JumpList& failureCases);
     void generateDescendantBacktrackingTail();
-    void generateBacktrackingTailsIfNeeded(const SelectorFragment&);
+    void generateBacktrackingTailsIfNeeded(Assembler::JumpList& failureCases, const SelectorFragment&);
 
     // Element properties matchers.
     void generateElementMatching(Assembler::JumpList& failureCases, const SelectorFragment&);
@@ -199,7 +199,7 @@
     Assembler::JumpList m_descendantBacktrackingFailureCases;
     StackAllocator::StackReference m_adjacentBacktrackingStart;
     Assembler::JumpList m_adjacentBacktrackingFailureCases;
-    Assembler::JumpList m_clearAdjacentEntryPointDescendantFailureCases;
+    Assembler::JumpList m_clearAdjacentBacktrackingFailureCases;
 
 #if CSS_SELECTOR_JIT_DEBUGGING
     const CSSSelector* m_originalSelector;
@@ -545,8 +545,12 @@
                 if (!hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain || isFirstAdjacent(adjacentPositionSinceIndirectAdjacentTreeWalk))
                     fragment.traversalBacktrackingAction = BacktrackingAction::JumpToDescendantTail;
                 else
-                    fragment.traversalBacktrackingAction = BacktrackingAction::JumpToClearAdjacentDescendantTail;
+                    fragment.traversalBacktrackingAction = BacktrackingAction::JumpToClearAdjacentTail;
             }
+        } else {
+            // If we are in a direct adjacent chain with backtracking, we need to clear the backtracking register on the stack.
+            if (hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain && !isFirstAdjacent(adjacentPositionSinceIndirectAdjacentTreeWalk))
+                fragment.traversalBacktrackingAction = BacktrackingAction::JumpToClearAdjacentTail;
         }
 
         // If the rightmost relation is a indirect adjacent, matching sould resume from there.
@@ -559,7 +563,7 @@
         } else if (hasDescendantRelationOnTheRight) {
             if (isAfterChildRelation(ancestorPositionSinceDescendantRelation))
                 fragment.matchingBacktrackingAction = BacktrackingAction::JumpToDescendantTail;
-            else if (hasDescendantRelationOnTheRight)
+            else
                 fragment.matchingBacktrackingAction = BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint;
         }
         break;
@@ -667,7 +671,7 @@
             generateIndirectAdjacentTreeWalker(failureCases, fragment);
             break;
         }
-        generateBacktrackingTailsIfNeeded(fragment);
+        generateBacktrackingTailsIfNeeded(failureCases, fragment);
     }
 
     m_registerAllocator.deallocateRegister(elementAddressRegister);
@@ -706,7 +710,7 @@
         StackAllocator failureStack = m_stackAllocator;
 
         LocalRegister checkingContextRegister(m_registerAllocator);
-        successStack.pop(m_checkingContextStackReference, checkingContextRegister);
+        successStack.popAndDiscardUpTo(m_checkingContextStackReference);
 
         // Failure.
         if (!failureCases.empty()) {
@@ -900,18 +904,32 @@
     case BacktrackingAction::JumpToDirectAdjacentTail:
         m_adjacentBacktrackingFailureCases.append(localFailureCases);
         break;
-    case BacktrackingAction::JumpToClearAdjacentDescendantTail:
-        m_clearAdjacentEntryPointDescendantFailureCases.append(localFailureCases);
+    case BacktrackingAction::JumpToClearAdjacentTail:
+        m_clearAdjacentBacktrackingFailureCases.append(localFailureCases);
         break;
     }
 }
 
-void SelectorCodeGenerator::generateAdjacentBacktrackingTail(StackAllocator& adjacentTailStack)
+void SelectorCodeGenerator::generateAdjacentBacktrackingTail(Assembler::JumpList& successCases)
 {
+    StackAllocator successStack = m_stackAllocator;
+    StackAllocator recoveryStack = m_stackAllocator;
+    StackAllocator failureStack = m_stackAllocator;
+
+    successStack.popAndDiscard(m_adjacentBacktrackingStart);
+    successCases.append(m_assembler.jump());
+
+    // Recovering tail.
     m_adjacentBacktrackingFailureCases.link(&m_assembler);
     m_adjacentBacktrackingFailureCases.clear();
-    adjacentTailStack.pop(m_adjacentBacktrackingStart, elementAddressRegister);
+    recoveryStack.pop(m_adjacentBacktrackingStart, elementAddressRegister);
     m_assembler.jump(m_indirectAdjacentEntryPoint);
+
+    // Total failure tail.
+    m_clearAdjacentBacktrackingFailureCases.link(&m_assembler);
+    failureStack.popAndDiscard(m_adjacentBacktrackingStart);
+
+    m_stackAllocator.merge(std::move(successStack), std::move(recoveryStack), std::move(failureStack));
 }
 
 void SelectorCodeGenerator::generateDescendantBacktrackingTail()
@@ -923,39 +941,18 @@
     m_assembler.jump(m_descendantEntryPoint);
 }
 
-void SelectorCodeGenerator::generateBacktrackingTailsIfNeeded(const SelectorFragment& fragment)
+void SelectorCodeGenerator::generateBacktrackingTailsIfNeeded(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
 {
     if (fragment.backtrackingFlags & BacktrackingFlag::DirectAdjacentTail && fragment.backtrackingFlags & BacktrackingFlag::DescendantTail) {
-        StackAllocator successStack = m_stackAllocator;
-        StackAllocator adjacentTailStack = m_stackAllocator;
-        StackAllocator descendantTailStack = m_stackAllocator;
-
-        successStack.popAndDiscard(m_adjacentBacktrackingStart);
-
-        Assembler::Jump normalCase = m_assembler.jump();
-
-        generateAdjacentBacktrackingTail(adjacentTailStack);
-
-        m_clearAdjacentEntryPointDescendantFailureCases.link(&m_assembler);
-        m_clearAdjacentEntryPointDescendantFailureCases.clear();
-        descendantTailStack.popAndDiscard(m_adjacentBacktrackingStart);
-
+        Assembler::JumpList successCases;
+        generateAdjacentBacktrackingTail(successCases);
         generateDescendantBacktrackingTail();
-
-        normalCase.link(&m_assembler);
-
-        m_stackAllocator.merge(std::move(successStack), std::move(adjacentTailStack), std::move(descendantTailStack));
+        successCases.link(&m_assembler);
     } else if (fragment.backtrackingFlags & BacktrackingFlag::DirectAdjacentTail) {
-        StackAllocator successStack = m_stackAllocator;
-        StackAllocator adjacentTailStack = m_stackAllocator;
-
-        successStack.popAndDiscard(m_adjacentBacktrackingStart);
-
-        Assembler::Jump normalCase = m_assembler.jump();
-        generateAdjacentBacktrackingTail(adjacentTailStack);
-        normalCase.link(&m_assembler);
-
-        m_stackAllocator.merge(std::move(successStack), std::move(adjacentTailStack));
+        Assembler::JumpList successCases;
+        generateAdjacentBacktrackingTail(successCases);
+        failureCases.append(m_assembler.jump());
+        successCases.link(&m_assembler);
     } else if (fragment.backtrackingFlags & BacktrackingFlag::DescendantTail) {
         Assembler::Jump normalCase = m_assembler.jump();
         generateDescendantBacktrackingTail();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to