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/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;