Title: [169298] trunk
Revision
169298
Author
commit-qu...@webkit.org
Date
2014-05-23 19:11:17 -0700 (Fri, 23 May 2014)

Log Message

CSS JIT: Apply backtracking optimization to adjacent backtracking
https://bugs.webkit.org/show_bug.cgi?id=132951

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

Apply the backtracking optimization to the adjacent backtracking.
This optimization is already done for the descendant backtracking.
We apply this to the adjacent backtracking similarly.

Source/WebCore:
Test: fast/selectors/backtracking-adjacent-optimized.html

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorFragment::SelectorFragment):
(WebCore::SelectorCompiler::solveAdjacentBacktrackingActionForDirectAdjacent):
(WebCore::SelectorCompiler::solveBacktrackingAction):
(WebCore::SelectorCompiler::computeBacktrackingStartOffsetInChain):
(WebCore::SelectorCompiler::computeBacktrackingHeightFromDescendant):
(WebCore::SelectorCompiler::computeBacktrackingWidthFromIndirectAdjacent):
(WebCore::SelectorCompiler::SelectorCodeGenerator::computeBacktrackingInformation):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::linkFailures):
(WebCore::SelectorCompiler::computeBacktrackingStartHeightFromDescendant): Deleted.

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

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (169297 => 169298)


--- trunk/LayoutTests/ChangeLog	2014-05-24 01:06:16 UTC (rev 169297)
+++ trunk/LayoutTests/ChangeLog	2014-05-24 02:11:17 UTC (rev 169298)
@@ -1,3 +1,17 @@
+2014-05-23  Yusuke Suzuki  <utatane....@gmail.com>
+
+        CSS JIT: Apply backtracking optimization to adjacent backtracking
+        https://bugs.webkit.org/show_bug.cgi?id=132951
+
+        Reviewed by Benjamin Poulain.
+
+        Apply the backtracking optimization to the adjacent backtracking.
+        This optimization is already done for the descendant backtracking.
+        We apply this to the adjacent backtracking similarly.
+
+        * fast/selectors/backtracking-adjacent-optimized-expected.txt: Added.
+        * fast/selectors/backtracking-adjacent-optimized.html: Added.
+
 2014-05-23  Simon Fraser  <simon.fra...@apple.com>
 
         Rebaseline two tests affected by r169229.

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


--- trunk/LayoutTests/fast/selectors/backtracking-adjacent-optimized-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/backtracking-adjacent-optimized-expected.txt	2014-05-24 02:11:17 UTC (rev 169298)
@@ -0,0 +1,25 @@
+The backtracking from direct adjacent combinators
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Backtracking as JumpToIndirectAdjacentEntryPoint
+PASS getComputedStyle(document.getElementById("target1")).backgroundColor is "rgb(1, 2, 3)"
+Backtracking as JumpToIndirectAdjacentEntryPoint and failed
+PASS getComputedStyle(document.getElementById("target2")).backgroundColor is "rgb(0, 0, 0)"
+Backtracking as JumpToIndirectAdjacentTreeWalkerEntryPoint
+PASS getComputedStyle(document.getElementById("target3")).backgroundColor is "rgb(1, 2, 3)"
+Backtracking as JumpToIndirectAdjacentTreeWalkerEntryPoint and failed
+PASS getComputedStyle(document.getElementById("target4")).backgroundColor is "rgb(0, 0, 0)"
+Backtracking with tail
+PASS getComputedStyle(document.getElementById("target5")).backgroundColor is "rgb(4, 5, 6)"
+Backtracking with tail and failed
+PASS getComputedStyle(document.getElementById("target6")).backgroundColor is "rgb(0, 0, 0)"
+Backtracking with tail
+PASS getComputedStyle(document.getElementById("target7")).backgroundColor is "rgb(4, 5, 6)"
+Backtracking with tail
+PASS getComputedStyle(document.getElementById("target8")).backgroundColor is "rgb(4, 5, 6)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

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


--- trunk/LayoutTests/fast/selectors/backtracking-adjacent-optimized.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/backtracking-adjacent-optimized.html	2014-05-24 02:11:17 UTC (rev 169298)
@@ -0,0 +1,155 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+span.target {
+    background-color:rgb(0,0,0);
+}
+
+a.ok+a~b span.target {
+    background-color:rgb(1,2,3);
+}
+
+e.ok+c.ok+c.ok+c~d span.target {
+    background-color:rgb(4,5,6);
+}
+</style>
+</head>
+<body>
+<div style="display:none">
+    <!-- a.ok+a~b span.target -->
+    <target1>
+        <a class="ok"></a>  <!-- Matched. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a></a>
+        <b>
+            <span class="target" id="target1"></span>
+        </b>
+    </target1>
+
+    <!-- a.ok+a~b span.target -->
+    <target2>
+        <a class="ng"></a>  <!-- Failed.-->
+        <a class="ng"></a>  <!-- Failed. And backtrack from here. -->
+        <a></a>
+        <b>
+            <span class="target" id="target2"></span>
+        </b>
+    </target2>
+
+    <!-- a.ok+a~b span.target -->
+    <target3>
+        <a class="ok"></a>  <!-- Matched. -->
+        <a></a>
+        <b></b>  <!-- Failed. And backtrack from here + 1. -->
+        <a></a>
+        <b>
+            <span class="target" id="target3"></span>
+        </b>
+    </target3>
+
+    <!-- a.ok+a~b span.target -->
+    <target4>
+        <a class="ng"></a>  <!-- Failed. -->
+        <a></a>
+        <b></b>  <!-- Failed. And backtrack from here + 1. -->
+        <a></a>
+        <b>
+            <span class="target" id="target4"></span>
+        </b>
+    </target4>
+
+    <!-- e.ok+c.ok+c.ok+c~d span.target -->
+    <target5>
+        <e class="ok"></e>  <!-- Matched. -->
+        <c class="ok"></c>  <!-- Failed. And backtrack with tail. -->
+        <c class="ok"></c>
+        <c class="ok"></c>
+        <c class="ok"></c>
+        <d>
+            <span class="target" id="target5"></span>
+        </d>
+    </target5>
+
+    <!-- e.ok+c.ok+c.ok+c~d span.target -->
+    <target6>
+        <e class="ng"></e>  <!-- Failed. -->
+        <c class="ok"></c>  <!-- Failed. And backtrack with tail. -->
+        <c class="ok"></c>
+        <c class="ok"></c>
+        <c class="ok"></c>
+        <d>
+            <span class="target" id="target6"></span>
+        </d>
+    </target6>
+
+    <!-- e.ok+c.ok+c.ok+c~d span.target -->
+    <target7>
+        <e class="ok"></e>  <!-- Matched. -->
+        <c class="ok"></c>
+        <c class="ok"></c>
+        <c class="ok"></c>
+        <c class="ng"></c>  <!-- Failed. And backtrack with tail. -->
+        <c></c>
+        <d>
+            <span class="target" id="target7"></span>
+        </d>
+    </target7>
+
+    <!-- e.ok+c.ok+c.ok+c~d span.target -->
+    <target8>
+        <e class="ok"></e>  <!-- Matched. -->
+        <c class="ok"></c>
+        <c class="ok"></c>
+        <c class="ng"></c>  <!-- Failed. And backtrack with tail. -->
+        <c class="ok"></c>
+        <c></c>
+        <d>
+            <span class="target" id="target8"></span>
+        </d>
+    </target8>
+</div>
+</body>
+<script>
+description('The backtracking from direct adjacent combinators');
+
+debug("Backtracking as JumpToIndirectAdjacentEntryPoint");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target1")).backgroundColor', 'rgb(1, 2, 3)');
+
+debug("Backtracking as JumpToIndirectAdjacentEntryPoint and failed");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target2")).backgroundColor', 'rgb(0, 0, 0)');
+
+debug("Backtracking as JumpToIndirectAdjacentTreeWalkerEntryPoint");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target3")).backgroundColor', 'rgb(1, 2, 3)');
+
+debug("Backtracking as JumpToIndirectAdjacentTreeWalkerEntryPoint and failed");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target4")).backgroundColor', 'rgb(0, 0, 0)');
+
+debug("Backtracking with tail");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target5")).backgroundColor', 'rgb(4, 5, 6)');
+
+debug("Backtracking with tail and failed");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target6")).backgroundColor', 'rgb(0, 0, 0)');
+
+debug("Backtracking with tail");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target7")).backgroundColor', 'rgb(4, 5, 6)');
+
+debug("Backtracking with tail");
+shouldBeEqualToString('getComputedStyle(document.getElementById("target8")).backgroundColor', 'rgb(4, 5, 6)');
+
+</script>
+<script src=""
+</html>

Modified: trunk/Source/WebCore/ChangeLog (169297 => 169298)


--- trunk/Source/WebCore/ChangeLog	2014-05-24 01:06:16 UTC (rev 169297)
+++ trunk/Source/WebCore/ChangeLog	2014-05-24 02:11:17 UTC (rev 169298)
@@ -1,3 +1,28 @@
+2014-05-23  Yusuke Suzuki  <utatane....@gmail.com>
+
+        CSS JIT: Apply backtracking optimization to adjacent backtracking
+        https://bugs.webkit.org/show_bug.cgi?id=132951
+
+        Reviewed by Benjamin Poulain.
+
+        Apply the backtracking optimization to the adjacent backtracking.
+        This optimization is already done for the descendant backtracking.
+        We apply this to the adjacent backtracking similarly.
+
+        Test: fast/selectors/backtracking-adjacent-optimized.html
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorFragment::SelectorFragment):
+        (WebCore::SelectorCompiler::solveAdjacentBacktrackingActionForDirectAdjacent):
+        (WebCore::SelectorCompiler::solveBacktrackingAction):
+        (WebCore::SelectorCompiler::computeBacktrackingStartOffsetInChain):
+        (WebCore::SelectorCompiler::computeBacktrackingHeightFromDescendant):
+        (WebCore::SelectorCompiler::computeBacktrackingWidthFromIndirectAdjacent):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::computeBacktrackingInformation):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::linkFailures):
+        (WebCore::SelectorCompiler::computeBacktrackingStartHeightFromDescendant): Deleted.
+
 2014-05-23  Alex Christensen  <achristen...@webkit.org>
 
         Make CSS JIT run on ARM64.

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (169297 => 169298)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-05-24 01:06:16 UTC (rev 169297)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-05-24 02:11:17 UTC (rev 169298)
@@ -64,6 +64,7 @@
     JumpToDescendantEntryPoint,
     JumpToIndirectAdjacentEntryPoint,
     JumpToDescendantTreeWalkerEntryPoint,
+    JumpToIndirectAdjacentTreeWalkerEntryPoint,
     JumpToDescendantTail,
     JumpToDirectAdjacentTail
 };
@@ -112,6 +113,7 @@
 };
 
 static const unsigned invalidHeight = std::numeric_limits<unsigned>::max();
+static const unsigned invalidWidth = std::numeric_limits<unsigned>::max();
 
 struct SelectorFragment {
     SelectorFragment()
@@ -122,6 +124,9 @@
         , tagNameMatchedBacktrackingStartHeightFromDescendant(invalidHeight)
         , tagNameNotMatchedBacktrackingStartHeightFromDescendant(invalidHeight)
         , heightFromDescendant(0)
+        , tagNameMatchedBacktrackingStartWidthFromIndirectAdjacent(invalidWidth)
+        , tagNameNotMatchedBacktrackingStartWidthFromIndirectAdjacent(invalidWidth)
+        , widthFromIndirectAdjacent(0)
         , tagName(nullptr)
         , id(nullptr)
     {
@@ -136,6 +141,9 @@
     unsigned tagNameMatchedBacktrackingStartHeightFromDescendant;
     unsigned tagNameNotMatchedBacktrackingStartHeightFromDescendant;
     unsigned heightFromDescendant;
+    unsigned tagNameMatchedBacktrackingStartWidthFromIndirectAdjacent;
+    unsigned tagNameNotMatchedBacktrackingStartWidthFromIndirectAdjacent;
+    unsigned widthFromIndirectAdjacent;
 
     const QualifiedName* tagName;
     const AtomicString* id;
@@ -240,6 +248,7 @@
     Assembler::Label m_descendantEntryPoint;
     Assembler::Label m_indirectAdjacentEntryPoint;
     Assembler::Label m_descendantTreeWalkerBacktrackingPoint;
+    Assembler::Label m_indirectAdjacentTreeWalkerBacktrackingPoint;
     Assembler::RegisterID m_descendantBacktrackingStart;
     Assembler::JumpList m_descendantBacktrackingFailureCases;
     StackAllocator::StackReference m_adjacentBacktrackingStart;
@@ -611,6 +620,23 @@
     return BacktrackingAction::JumpToDescendantTail;
 }
 
+static inline BacktrackingAction solveAdjacentBacktrackingActionForDirectAdjacent(const SelectorFragment& fragment, unsigned backtrackingStartWidthFromIndirectAdjacent)
+{
+    // If width is invalid (e.g. There's no tag name).
+    if (backtrackingStartWidthFromIndirectAdjacent == invalidWidth)
+        return BacktrackingAction::NoBacktracking;
+
+    // Start backtracking from the current element.
+    if (backtrackingStartWidthFromIndirectAdjacent == fragment.widthFromIndirectAdjacent)
+        return BacktrackingAction::JumpToIndirectAdjacentEntryPoint;
+
+    // Start backtracking from the previous adjacent of current element.
+    if (backtrackingStartWidthFromIndirectAdjacent == (fragment.widthFromIndirectAdjacent + 1))
+        return BacktrackingAction::JumpToIndirectAdjacentTreeWalkerEntryPoint;
+
+    return BacktrackingAction::JumpToDirectAdjacentTail;
+}
+
 static inline BacktrackingAction solveAdjacentTraversalBacktrackingAction(const SelectorFragment& fragment, bool hasDescendantRelationOnTheRight)
 {
     if (!hasDescendantRelationOnTheRight)
@@ -622,7 +648,7 @@
     return BacktrackingAction::JumpToDescendantTail;
 }
 
-static inline void solveBacktrackingAction(SelectorFragment& fragment, bool hasDescendantRelationOnTheRight, bool hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, unsigned adjacentPositionSinceIndirectAdjacentTreeWalk)
+static inline void solveBacktrackingAction(SelectorFragment& fragment, bool hasDescendantRelationOnTheRight, bool hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain)
 {
     switch (fragment.relationToRightFragment) {
     case FragmentRelation::Rightmost:
@@ -643,13 +669,8 @@
         // If the rightmost relation is a indirect adjacent, matching sould resume from there.
         // Otherwise, we resume from the latest ancestor/descendant if any.
         if (hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain) {
-            if (isFirstAdjacent(adjacentPositionSinceIndirectAdjacentTreeWalk)) {
-                fragment.matchingTagNameBacktrackingAction = BacktrackingAction::JumpToIndirectAdjacentEntryPoint;
-                fragment.matchingPostTagNameBacktrackingAction = BacktrackingAction::JumpToIndirectAdjacentEntryPoint;
-            } else {
-                fragment.matchingTagNameBacktrackingAction = BacktrackingAction::JumpToDirectAdjacentTail;
-                fragment.matchingPostTagNameBacktrackingAction = BacktrackingAction::JumpToDirectAdjacentTail;
-            }
+            fragment.matchingTagNameBacktrackingAction = solveAdjacentBacktrackingActionForDirectAdjacent(fragment, fragment.tagNameNotMatchedBacktrackingStartWidthFromIndirectAdjacent);
+            fragment.matchingPostTagNameBacktrackingAction = solveAdjacentBacktrackingActionForDirectAdjacent(fragment, fragment.tagNameMatchedBacktrackingStartWidthFromIndirectAdjacent);
         } else if (hasDescendantRelationOnTheRight) {
             // Since we resume from the latest ancestor/descendant, the action is the same as the traversal action.
             fragment.matchingTagNameBacktrackingAction = fragment.traversalBacktrackingAction;
@@ -714,8 +735,8 @@
 }
 
 // Find the largest matching prefix from already known tagNames.
-// And by using this, compute an appropriate height of backtracking start element from the closest descendant.
-static inline unsigned computeBacktrackingStartHeightFromDescendant(const TagNameList& tagNames, unsigned maxPrefixSize)
+// And by using this, compute an appropriate height of backtracking start element from the closest base element in the chain.
+static inline unsigned computeBacktrackingStartOffsetInChain(const TagNameList& tagNames, unsigned maxPrefixSize)
 {
     RELEASE_ASSERT(!tagNames.isEmpty());
     RELEASE_ASSERT(maxPrefixSize < tagNames.size());
@@ -738,54 +759,92 @@
     return tagNames.size();
 }
 
-static inline void computeBacktrackingHeightFromDescendant(SelectorFragment& fragment, TagNameList& tagNames, bool hasDescendantRelationOnTheRight, const SelectorFragment*& previousChildFragmentInDescendantBacktrackingChain)
+static inline void computeBacktrackingHeightFromDescendant(SelectorFragment& fragment, TagNameList& tagNamesForChildChain, bool hasDescendantRelationOnTheRight, const SelectorFragment*& previousChildFragmentInChildChain)
 {
     if (!hasDescendantRelationOnTheRight)
         return;
 
     if (fragment.relationToRightFragment == FragmentRelation::Descendant) {
-        tagNames.clear();
+        tagNamesForChildChain.clear();
 
         TagNamePattern pattern;
         pattern.tagName = fragment.tagName;
-        tagNames.append(pattern);
+        tagNamesForChildChain.append(pattern);
         fragment.heightFromDescendant = 0;
-        previousChildFragmentInDescendantBacktrackingChain = nullptr;
+        previousChildFragmentInChildChain = nullptr;
     } else if (fragment.relationToRightFragment == FragmentRelation::Child) {
         TagNamePattern pattern;
         pattern.tagName = fragment.tagName;
-        tagNames.append(pattern);
+        tagNamesForChildChain.append(pattern);
 
-        unsigned maxPrefixSize = tagNames.size() - 1;
-        if (previousChildFragmentInDescendantBacktrackingChain) {
-            RELEASE_ASSERT(tagNames.size() >= previousChildFragmentInDescendantBacktrackingChain->tagNameMatchedBacktrackingStartHeightFromDescendant);
-            maxPrefixSize = tagNames.size() - previousChildFragmentInDescendantBacktrackingChain->tagNameMatchedBacktrackingStartHeightFromDescendant;
+        unsigned maxPrefixSize = tagNamesForChildChain.size() - 1;
+        if (previousChildFragmentInChildChain) {
+            RELEASE_ASSERT(tagNamesForChildChain.size() >= previousChildFragmentInChildChain->tagNameMatchedBacktrackingStartHeightFromDescendant);
+            maxPrefixSize = tagNamesForChildChain.size() - previousChildFragmentInChildChain->tagNameMatchedBacktrackingStartHeightFromDescendant;
         }
 
         if (pattern.tagName) {
             // Compute height from descendant in the case that tagName is not matched.
-            tagNames.last().inverted = true;
-            fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant = computeBacktrackingStartHeightFromDescendant(tagNames, maxPrefixSize);
+            tagNamesForChildChain.last().inverted = true;
+            fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant = computeBacktrackingStartOffsetInChain(tagNamesForChildChain, maxPrefixSize);
         }
 
         // Compute height from descendant in the case that tagName is matched.
-        tagNames.last().inverted = false;
-        fragment.tagNameMatchedBacktrackingStartHeightFromDescendant = computeBacktrackingStartHeightFromDescendant(tagNames, maxPrefixSize);
-        fragment.heightFromDescendant = tagNames.size() - 1;
-        previousChildFragmentInDescendantBacktrackingChain = &fragment;
+        tagNamesForChildChain.last().inverted = false;
+        fragment.tagNameMatchedBacktrackingStartHeightFromDescendant = computeBacktrackingStartOffsetInChain(tagNamesForChildChain, maxPrefixSize);
+        fragment.heightFromDescendant = tagNamesForChildChain.size() - 1;
+        previousChildFragmentInChildChain = &fragment;
     } else {
-        if (previousChildFragmentInDescendantBacktrackingChain) {
-            fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant = previousChildFragmentInDescendantBacktrackingChain->tagNameNotMatchedBacktrackingStartHeightFromDescendant;
-            fragment.tagNameMatchedBacktrackingStartHeightFromDescendant = previousChildFragmentInDescendantBacktrackingChain->tagNameMatchedBacktrackingStartHeightFromDescendant;
-            fragment.heightFromDescendant = previousChildFragmentInDescendantBacktrackingChain->heightFromDescendant;
+        if (previousChildFragmentInChildChain) {
+            fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant = previousChildFragmentInChildChain->tagNameNotMatchedBacktrackingStartHeightFromDescendant;
+            fragment.tagNameMatchedBacktrackingStartHeightFromDescendant = previousChildFragmentInChildChain->tagNameMatchedBacktrackingStartHeightFromDescendant;
+            fragment.heightFromDescendant = previousChildFragmentInChildChain->heightFromDescendant;
         } else {
-            fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant = tagNames.size();
-            fragment.tagNameMatchedBacktrackingStartHeightFromDescendant = tagNames.size();
+            fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant = tagNamesForChildChain.size();
+            fragment.tagNameMatchedBacktrackingStartHeightFromDescendant = tagNamesForChildChain.size();
             fragment.heightFromDescendant = 0;
         }
     }
 }
 
+static inline void computeBacktrackingWidthFromIndirectAdjacent(SelectorFragment& fragment, TagNameList& tagNamesForDirectAdjacentChain, bool hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, const SelectorFragment*& previousDirectAdjacentFragmentInDirectAdjacentChain)
+{
+    if (!hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain)
+        return;
+
+    if (fragment.relationToRightFragment == FragmentRelation::IndirectAdjacent) {
+        tagNamesForDirectAdjacentChain.clear();
+
+        TagNamePattern pattern;
+        pattern.tagName = fragment.tagName;
+        tagNamesForDirectAdjacentChain.append(pattern);
+        fragment.widthFromIndirectAdjacent = 0;
+        previousDirectAdjacentFragmentInDirectAdjacentChain = nullptr;
+    } else if (fragment.relationToRightFragment == FragmentRelation::DirectAdjacent) {
+        TagNamePattern pattern;
+        pattern.tagName = fragment.tagName;
+        tagNamesForDirectAdjacentChain.append(pattern);
+
+        unsigned maxPrefixSize = tagNamesForDirectAdjacentChain.size() - 1;
+        if (previousDirectAdjacentFragmentInDirectAdjacentChain) {
+            RELEASE_ASSERT(tagNamesForDirectAdjacentChain.size() >= previousDirectAdjacentFragmentInDirectAdjacentChain->tagNameMatchedBacktrackingStartWidthFromIndirectAdjacent);
+            maxPrefixSize = tagNamesForDirectAdjacentChain.size() - previousDirectAdjacentFragmentInDirectAdjacentChain->tagNameMatchedBacktrackingStartWidthFromIndirectAdjacent;
+        }
+
+        if (pattern.tagName) {
+            // Compute height from descendant in the case that tagName is not matched.
+            tagNamesForDirectAdjacentChain.last().inverted = true;
+            fragment.tagNameNotMatchedBacktrackingStartWidthFromIndirectAdjacent = computeBacktrackingStartOffsetInChain(tagNamesForDirectAdjacentChain, maxPrefixSize);
+        }
+
+        // Compute height from descendant in the case that tagName is matched.
+        tagNamesForDirectAdjacentChain.last().inverted = false;
+        fragment.tagNameMatchedBacktrackingStartWidthFromIndirectAdjacent = computeBacktrackingStartOffsetInChain(tagNamesForDirectAdjacentChain, maxPrefixSize);
+        fragment.widthFromIndirectAdjacent = tagNamesForDirectAdjacentChain.size() - 1;
+        previousDirectAdjacentFragmentInDirectAdjacentChain = &fragment;
+    }
+}
+
 static bool requiresAdjacentTail(const SelectorFragment& fragment)
 {
     ASSERT(fragment.traversalBacktrackingAction != BacktrackingAction::JumpToDirectAdjacentTail);
@@ -807,29 +866,31 @@
     bool needsAdjacentTail = false;
     bool needsDescendantTail = false;
     unsigned saveDescendantBacktrackingStartFragmentIndex = std::numeric_limits<unsigned>::max();
+    unsigned saveIndirectAdjacentBacktrackingStartFragmentIndex = std::numeric_limits<unsigned>::max();
 
-    TagNameList tagNames;
-    const SelectorFragment* previousChildFragmentInDescendantBacktrackingChain = nullptr;
+    TagNameList tagNamesForChildChain;
+    TagNameList tagNamesForDirectAdjacentChain;
+    const SelectorFragment* previousChildFragmentInChildChain = nullptr;
+    const SelectorFragment* previousDirectAdjacentFragmentInDirectAdjacentChain = nullptr;
 
     for (unsigned i = 0; i < m_selectorFragments.size(); ++i) {
         SelectorFragment& fragment = m_selectorFragments[i];
 
         updateChainStates(fragment, hasDescendantRelationOnTheRight, ancestorPositionSinceDescendantRelation, hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, adjacentPositionSinceIndirectAdjacentTreeWalk);
 
-        computeBacktrackingHeightFromDescendant(fragment, tagNames, hasDescendantRelationOnTheRight, previousChildFragmentInDescendantBacktrackingChain);
+        computeBacktrackingHeightFromDescendant(fragment, tagNamesForChildChain, hasDescendantRelationOnTheRight, previousChildFragmentInChildChain);
 
+        computeBacktrackingWidthFromIndirectAdjacent(fragment, tagNamesForDirectAdjacentChain, hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, previousDirectAdjacentFragmentInDirectAdjacentChain);
+
 #if CSS_SELECTOR_JIT_DEBUGGING
-        dataLogF("Computing fragment[%d] backtracking height %u. NotMatched %u / Matched %u\n", i, fragment.heightFromDescendant, fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant, fragment.tagNameMatchedBacktrackingStartHeightFromDescendant);
+        dataLogF("Computing fragment[%d] backtracking height %u. NotMatched %u / Matched %u | width %u. NotMatched %u / Matched %u\n", i, fragment.heightFromDescendant, fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant, fragment.tagNameMatchedBacktrackingStartHeightFromDescendant, fragment.widthFromIndirectAdjacent, fragment.tagNameNotMatchedBacktrackingStartWidthFromIndirectAdjacent, fragment.tagNameMatchedBacktrackingStartWidthFromIndirectAdjacent);
 #endif
 
-        solveBacktrackingAction(fragment, hasDescendantRelationOnTheRight, hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, adjacentPositionSinceIndirectAdjacentTreeWalk);
+        solveBacktrackingAction(fragment, hasDescendantRelationOnTheRight, hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain);
 
         needsAdjacentTail |= requiresAdjacentTail(fragment);
         needsDescendantTail |= requiresDescendantTail(fragment);
 
-        if (needsDescendantTail)
-            fragment.backtrackingFlags |= BacktrackingFlag::InChainWithDescendantTail;
-
         // Add code generation flags.
         if (fragment.relationToLeftFragment != FragmentRelation::Descendant && fragment.relationToRightFragment == FragmentRelation::Descendant)
             fragment.backtrackingFlags |= BacktrackingFlag::DescendantEntryPoint;
@@ -840,13 +901,19 @@
             saveDescendantBacktrackingStartFragmentIndex = i;
         }
         if (fragment.relationToLeftFragment == FragmentRelation::DirectAdjacent && fragment.relationToRightFragment == FragmentRelation::DirectAdjacent && isFirstAdjacent(adjacentPositionSinceIndirectAdjacentTreeWalk)) {
-            fragment.backtrackingFlags |= BacktrackingFlag::SaveAdjacentBacktrackingStart;
-            m_needsAdjacentBacktrackingStart = true;
+            ASSERT(saveIndirectAdjacentBacktrackingStartFragmentIndex == std::numeric_limits<unsigned>::max());
+            saveIndirectAdjacentBacktrackingStartFragmentIndex = i;
         }
-        if (fragment.relationToLeftFragment != FragmentRelation::DirectAdjacent && needsAdjacentTail) {
-            ASSERT(fragment.relationToRightFragment == FragmentRelation::DirectAdjacent);
-            fragment.backtrackingFlags |= BacktrackingFlag::DirectAdjacentTail;
-            needsAdjacentTail = false;
+        if (fragment.relationToLeftFragment != FragmentRelation::DirectAdjacent) {
+            if (needsAdjacentTail) {
+                ASSERT(fragment.relationToRightFragment == FragmentRelation::DirectAdjacent);
+                ASSERT(saveIndirectAdjacentBacktrackingStartFragmentIndex != std::numeric_limits<unsigned>::max());
+                fragment.backtrackingFlags |= BacktrackingFlag::DirectAdjacentTail;
+                m_selectorFragments[saveIndirectAdjacentBacktrackingStartFragmentIndex].backtrackingFlags |= BacktrackingFlag::SaveAdjacentBacktrackingStart;
+                m_needsAdjacentBacktrackingStart = true;
+                needsAdjacentTail = false;
+            }
+            saveIndirectAdjacentBacktrackingStartFragmentIndex = std::numeric_limits<unsigned>::max();
         }
         if (fragment.relationToLeftFragment == FragmentRelation::Descendant) {
             if (needsDescendantTail) {
@@ -1121,6 +1188,9 @@
 
     Assembler::Label loopStart(m_assembler.label());
 
+    if (fragment.backtrackingFlags & BacktrackingFlag::IndirectAdjacentEntryPoint)
+        m_indirectAdjacentTreeWalkerBacktrackingPoint = m_assembler.label();
+
     generateWalkToPreviousAdjacent(failureCases, fragment);
 
     if (fragment.backtrackingFlags & BacktrackingFlag::IndirectAdjacentEntryPoint)
@@ -1332,6 +1402,9 @@
     case BacktrackingAction::JumpToIndirectAdjacentEntryPoint:
         localFailureCases.linkTo(m_indirectAdjacentEntryPoint, &m_assembler);
         break;
+    case BacktrackingAction::JumpToIndirectAdjacentTreeWalkerEntryPoint:
+        localFailureCases.linkTo(m_indirectAdjacentTreeWalkerBacktrackingPoint, &m_assembler);
+        break;
     case BacktrackingAction::JumpToDirectAdjacentTail:
         m_adjacentBacktrackingFailureCases.append(localFailureCases);
         break;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to