Changeset 167920 in webkit
- Timestamp:
- Apr 28, 2014 6:58:38 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r167915 r167920 1 2014-04-28 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 CSS JIT: backtracking with current / parent element for child 4 https://bugs.webkit.org/show_bug.cgi?id=132057 5 6 Reviewed by Benjamin Poulain. 7 8 Calculate appropriate backtracking start height from the closest 9 descendant. And at first, we use it for a simple optimization. 10 11 1. When backtracking start height equals to current height, we 12 can simply jump to a descendant element check phase. 13 2. When backtracking start height equals to current height + 1, we 14 can simply jump to a descendant element traversing phase. 15 16 We can apply this optimization to fragments with adjacent combinators. 17 But, in the meantime, we start to implement it for a fragment with 18 child combinator. 19 20 * fast/selectors/backtracking-child-combinator-with-tail-expected.txt: Added. 21 * fast/selectors/backtracking-child-combinator-with-tail.html: Added. 22 * fast/selectors/backtracking-child-combinator-without-tail-expected.txt: Added. 23 * fast/selectors/backtracking-child-combinator-without-tail.html: Added. 24 1 25 2014-04-28 Ryuan Choi <ryuan.choi@samsung.com> 2 26 -
trunk/Source/WebCore/ChangeLog
r167916 r167920 1 2014-04-28 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 CSS JIT: backtracking with current / parent element for child 4 https://bugs.webkit.org/show_bug.cgi?id=132057 5 6 Reviewed by Benjamin Poulain. 7 8 Calculate appropriate backtracking start height from the closest 9 descendant. And at first, we use it for a simple optimization. 10 11 1. When backtracking start height equals to current height, we 12 can simply jump to a descendant element check phase. 13 2. When backtracking start height equals to current height + 1, we 14 can simply jump to a descendant element traversing phase. 15 16 We can apply this optimization to fragments with adjacent combinators. 17 But, in the meantime, we start to implement it for a fragment with 18 child combinator. 19 20 * cssjit/SelectorCompiler.cpp: 21 (WebCore::SelectorCompiler::SelectorFragment::SelectorFragment): 22 (WebCore::SelectorCompiler::TagNamePattern::TagNamePattern): 23 (WebCore::SelectorCompiler::solveDescendantBacktrackingActionForChild): 24 (WebCore::SelectorCompiler::solveBacktrackingAction): 25 (WebCore::SelectorCompiler::equalTagNames): 26 (WebCore::SelectorCompiler::equalTagNamePatterns): 27 (WebCore::SelectorCompiler::computeBacktrackingStartHeightFromDescendant): 28 (WebCore::SelectorCompiler::computeBacktrackingHeightFromDescendant): 29 (WebCore::SelectorCompiler::requiresAdjacentTail): 30 (WebCore::SelectorCompiler::requiresDescendantTail): 31 (WebCore::SelectorCompiler::SelectorCodeGenerator::computeBacktrackingInformation): 32 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker): 33 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToParentNode): 34 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToParentElement): 35 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateParentElementTreeWalker): 36 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateAncestorTreeWalker): 37 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateDirectAdjacentTreeWalker): 38 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker): 39 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching): 40 1 41 2014-04-28 Benjamin Poulain <bpoulain@apple.com> 2 42 -
trunk/Source/WebCore/cssjit/SelectorCompiler.cpp
r167585 r167920 1 1 /* 2 2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 * Copyright (C) 2014 Yusuke Suzuki <utatane.tea@gmail.com> 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 48 49 #include <JavaScriptCore/MacroAssembler.h> 49 50 #include <JavaScriptCore/VM.h> 51 #include <limits> 50 52 #include <wtf/HashMap.h> 51 53 #include <wtf/HashSet.h> … … 111 113 }; 112 114 115 static const unsigned invalidHeight = std::numeric_limits<unsigned>::max(); 116 113 117 struct SelectorFragment { 114 118 SelectorFragment() 115 119 : traversalBacktrackingAction(BacktrackingAction::NoBacktracking) 116 , matchingBacktrackingAction(BacktrackingAction::NoBacktracking) 120 , matchingTagNameBacktrackingAction(BacktrackingAction::NoBacktracking) 121 , matchingPostTagNameBacktrackingAction(BacktrackingAction::NoBacktracking) 117 122 , backtrackingFlags(0) 123 , tagNameMatchedBacktrackingStartHeightFromDescendant(invalidHeight) 124 , tagNameNotMatchedBacktrackingStartHeightFromDescendant(invalidHeight) 125 , heightFromDescendant(0) 118 126 , tagName(nullptr) 119 127 , id(nullptr) … … 124 132 125 133 BacktrackingAction traversalBacktrackingAction; 126 BacktrackingAction matchingBacktrackingAction; 134 BacktrackingAction matchingTagNameBacktrackingAction; 135 BacktrackingAction matchingPostTagNameBacktrackingAction; 127 136 unsigned char backtrackingFlags; 137 unsigned tagNameMatchedBacktrackingStartHeightFromDescendant; 138 unsigned tagNameNotMatchedBacktrackingStartHeightFromDescendant; 139 unsigned heightFromDescendant; 128 140 129 141 const QualifiedName* tagName; … … 136 148 }; 137 149 150 struct TagNamePattern { 151 TagNamePattern() 152 : tagName(nullptr) 153 , inverted(false) 154 { 155 } 156 const QualifiedName* tagName; 157 bool inverted; 158 }; 159 138 160 typedef JSC::MacroAssembler Assembler; 139 161 typedef Vector<SelectorFragment, 8> SelectorFragmentList; 162 typedef Vector<TagNamePattern, 8> TagNameList; 140 163 141 164 class SelectorCodeGenerator { … … 153 176 154 177 // Element relations tree walker. 178 void generateWalkToParentNode(Assembler::RegisterID targetRegister); 155 179 void generateWalkToParentElement(Assembler::JumpList& failureCases, Assembler::RegisterID targetRegister); 156 180 void generateParentElementTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment&); … … 171 195 172 196 // Element properties matchers. 173 void generateElementMatching(Assembler::JumpList& failureCases, const SelectorFragment&);197 void generateElementMatching(Assembler::JumpList& matchingTagNameFailureCases, Assembler::JumpList& matchingPostTagNameFailureCases, const SelectorFragment&); 174 198 void generateElementDataMatching(Assembler::JumpList& failureCases, const SelectorFragment&); 175 199 void generateElementFunctionCallTest(Assembler::JumpList& failureCases, JSC::FunctionPtr); … … 574 598 } 575 599 600 static BacktrackingAction solveDescendantBacktrackingActionForChild(const SelectorFragment& fragment, unsigned backtrackingStartHeightFromDescendant) 601 { 602 // If height is invalid (e.g. There's no tag name). 603 if (backtrackingStartHeightFromDescendant == invalidHeight) 604 return BacktrackingAction::NoBacktracking; 605 606 // Start backtracking from the current element. 607 if (backtrackingStartHeightFromDescendant == fragment.heightFromDescendant) 608 return BacktrackingAction::JumpToDescendantEntryPoint; 609 610 // Start backtracking from the parent of current element. 611 if (backtrackingStartHeightFromDescendant == (fragment.heightFromDescendant + 1)) 612 return BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint; 613 614 return BacktrackingAction::JumpToDescendantTail; 615 } 616 576 617 static inline void solveBacktrackingAction(SelectorFragment& fragment, bool hasDescendantRelationOnTheRight, unsigned ancestorPositionSinceDescendantRelation, bool hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, unsigned adjacentPositionSinceIndirectAdjacentTreeWalk) 577 618 { … … 583 624 // Failure to match the element should resume matching at the nearest ancestor/descendant entry point. 584 625 if (hasDescendantRelationOnTheRight) { 585 if (isFirstAncestor(ancestorPositionSinceDescendantRelation)) 586 fragment.matchingBacktrackingAction = BacktrackingAction::JumpToDescendantEntryPoint; 587 else 588 fragment.matchingBacktrackingAction = BacktrackingAction::JumpToDescendantTail; 626 fragment.matchingTagNameBacktrackingAction = solveDescendantBacktrackingActionForChild(fragment, fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant); 627 fragment.matchingPostTagNameBacktrackingAction = solveDescendantBacktrackingActionForChild(fragment, fragment.tagNameMatchedBacktrackingStartHeightFromDescendant); 589 628 } 590 629 break; … … 610 649 // Otherwise, we resume from the latest ancestor/descendant if any. 611 650 if (hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain) { 612 if (isFirstAdjacent(adjacentPositionSinceIndirectAdjacentTreeWalk)) 613 fragment.matchingBacktrackingAction = BacktrackingAction::JumpToIndirectAdjacentEntryPoint; 614 else 615 fragment.matchingBacktrackingAction = BacktrackingAction::JumpToDirectAdjacentTail; 651 if (isFirstAdjacent(adjacentPositionSinceIndirectAdjacentTreeWalk)) { 652 fragment.matchingTagNameBacktrackingAction = BacktrackingAction::JumpToIndirectAdjacentEntryPoint; 653 fragment.matchingPostTagNameBacktrackingAction = BacktrackingAction::JumpToIndirectAdjacentEntryPoint; 654 } else { 655 fragment.matchingTagNameBacktrackingAction = BacktrackingAction::JumpToDirectAdjacentTail; 656 fragment.matchingPostTagNameBacktrackingAction = BacktrackingAction::JumpToDirectAdjacentTail; 657 } 616 658 } else if (hasDescendantRelationOnTheRight) { 617 if (isAfterChildRelation(ancestorPositionSinceDescendantRelation)) 618 fragment.matchingBacktrackingAction = BacktrackingAction::JumpToDescendantTail; 619 else 620 fragment.matchingBacktrackingAction = BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint; 659 if (isAfterChildRelation(ancestorPositionSinceDescendantRelation)) { 660 fragment.matchingTagNameBacktrackingAction = BacktrackingAction::JumpToDescendantTail; 661 fragment.matchingPostTagNameBacktrackingAction = BacktrackingAction::JumpToDescendantTail; 662 } else { 663 fragment.matchingTagNameBacktrackingAction = BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint; 664 fragment.matchingPostTagNameBacktrackingAction = BacktrackingAction::JumpToDescendantTreeWalkerEntryPoint; 665 } 621 666 } 622 667 break; … … 634 679 } 635 680 681 enum class TagNameEquality { 682 StrictlyNotEqual, 683 MaybeEqual, 684 StrictlyEqual 685 }; 686 687 static inline TagNameEquality equalTagNames(const QualifiedName* lhs, const QualifiedName* rhs) 688 { 689 if (!lhs || *lhs == anyQName()) 690 return TagNameEquality::MaybeEqual; 691 692 if (!rhs || *rhs == anyQName()) 693 return TagNameEquality::MaybeEqual; 694 695 ASSERT(lhs && rhs); 696 697 const AtomicString& lhsLocalName = lhs->localName(); 698 const AtomicString& rhsLocalName = rhs->localName(); 699 if (lhsLocalName != starAtom && rhsLocalName != starAtom) { 700 if (lhsLocalName != rhsLocalName) 701 return TagNameEquality::StrictlyNotEqual; 702 return TagNameEquality::StrictlyEqual; 703 } 704 705 const AtomicString& lhsNamespaceURI = lhs->namespaceURI(); 706 const AtomicString& rhsNamespaceURI = rhs->namespaceURI(); 707 if (lhsNamespaceURI != starAtom && rhsNamespaceURI != starAtom) { 708 if (lhsNamespaceURI != rhsNamespaceURI) 709 return TagNameEquality::StrictlyNotEqual; 710 return TagNameEquality::StrictlyEqual; 711 } 712 713 return TagNameEquality::MaybeEqual; 714 } 715 716 static inline bool equalTagNamePatterns(const TagNamePattern& lhs, const QualifiedName* rhs) 717 { 718 TagNameEquality result = equalTagNames(lhs.tagName, rhs); 719 if (result == TagNameEquality::MaybeEqual) 720 return true; 721 722 // If both rhs & lhs have actual localName (or NamespaceURI), 723 // TagNameEquality result becomes StrictlyEqual or StrictlyNotEqual Since inverted lhs never matches on rhs. 724 bool equal = result == TagNameEquality::StrictlyEqual; 725 if (lhs.inverted) 726 return !equal; 727 return equal; 728 } 729 730 // Find the largest matching prefix from already known tagNames. 731 // And by using this, compute an appropriate height of backtracking start element from the closest descendant. 732 static inline unsigned computeBacktrackingStartHeightFromDescendant(const TagNameList& tagNames) 733 { 734 RELEASE_ASSERT(!tagNames.isEmpty()); 735 736 unsigned largestPrefixSize = tagNames.size(); 737 while (--largestPrefixSize) { 738 unsigned offsetToLargestPrefix = tagNames.size() - largestPrefixSize; 739 bool matched = true; 740 // Since TagNamePatterns are pushed to a tagNames, check tagNames with reverse order. 741 for (unsigned i = 0; i < largestPrefixSize; ++i) { 742 unsigned lastIndex = tagNames.size() - 1; 743 unsigned currentIndex = lastIndex - i; 744 if (!equalTagNamePatterns(tagNames[currentIndex], tagNames[currentIndex - offsetToLargestPrefix].tagName)) { 745 matched = false; 746 break; 747 } 748 } 749 if (matched) 750 return offsetToLargestPrefix; 751 } 752 return tagNames.size(); 753 } 754 755 static inline void computeBacktrackingHeightFromDescendant(SelectorFragment& fragment, TagNameList& tagNames, bool hasDescendantRelationOnTheRight, const SelectorFragment*& previousChildFragmentInDescendantBacktrackingChain) 756 { 757 if (!hasDescendantRelationOnTheRight) 758 return; 759 760 if (fragment.relationToRightFragment == FragmentRelation::Descendant) { 761 tagNames.clear(); 762 763 TagNamePattern pattern; 764 pattern.tagName = fragment.tagName; 765 tagNames.append(pattern); 766 fragment.heightFromDescendant = 0; 767 previousChildFragmentInDescendantBacktrackingChain = nullptr; 768 } else if (fragment.relationToRightFragment == FragmentRelation::Child) { 769 TagNamePattern pattern; 770 pattern.tagName = fragment.tagName; 771 tagNames.append(pattern); 772 773 if (pattern.tagName) { 774 // Compute height from descendant in the case that tagName is not matched. 775 tagNames.last().inverted = true; 776 fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant = computeBacktrackingStartHeightFromDescendant(tagNames); 777 } 778 779 // Compute height from descendant in the case that tagName is matched. 780 tagNames.last().inverted = false; 781 fragment.tagNameMatchedBacktrackingStartHeightFromDescendant = computeBacktrackingStartHeightFromDescendant(tagNames); 782 fragment.heightFromDescendant = tagNames.size() - 1; 783 previousChildFragmentInDescendantBacktrackingChain = &fragment; 784 } else { 785 if (previousChildFragmentInDescendantBacktrackingChain) { 786 fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant = previousChildFragmentInDescendantBacktrackingChain->tagNameNotMatchedBacktrackingStartHeightFromDescendant; 787 fragment.tagNameMatchedBacktrackingStartHeightFromDescendant = previousChildFragmentInDescendantBacktrackingChain->tagNameMatchedBacktrackingStartHeightFromDescendant; 788 fragment.heightFromDescendant = previousChildFragmentInDescendantBacktrackingChain->heightFromDescendant; 789 } else { 790 fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant = tagNames.size(); 791 fragment.tagNameMatchedBacktrackingStartHeightFromDescendant = tagNames.size(); 792 fragment.heightFromDescendant = 0; 793 } 794 } 795 } 796 636 797 static bool requiresAdjacentTail(const SelectorFragment& fragment) 637 798 { 638 799 ASSERT(fragment.traversalBacktrackingAction != BacktrackingAction::JumpToDirectAdjacentTail); 639 return fragment.matching BacktrackingAction == BacktrackingAction::JumpToDirectAdjacentTail;800 return fragment.matchingTagNameBacktrackingAction == BacktrackingAction::JumpToDirectAdjacentTail || fragment.matchingPostTagNameBacktrackingAction == BacktrackingAction::JumpToDirectAdjacentTail; 640 801 } 641 802 642 803 static bool requiresDescendantTail(const SelectorFragment& fragment) 643 804 { 644 return fragment.matching BacktrackingAction == BacktrackingAction::JumpToDescendantTail || fragment.traversalBacktrackingAction == BacktrackingAction::JumpToDescendantTail;805 return fragment.matchingTagNameBacktrackingAction == BacktrackingAction::JumpToDescendantTail || fragment.matchingPostTagNameBacktrackingAction == BacktrackingAction::JumpToDescendantTail || fragment.traversalBacktrackingAction == BacktrackingAction::JumpToDescendantTail; 645 806 } 646 807 … … 654 815 bool needsAdjacentTail = false; 655 816 bool needsDescendantTail = false; 817 unsigned saveDescendantBacktrackingStartFragmentIndex = std::numeric_limits<unsigned>::max(); 818 819 TagNameList tagNames; 820 const SelectorFragment* previousChildFragmentInDescendantBacktrackingChain = nullptr; 656 821 657 822 for (unsigned i = 0; i < m_selectorFragments.size(); ++i) { … … 659 824 660 825 updateChainStates(fragment, hasDescendantRelationOnTheRight, ancestorPositionSinceDescendantRelation, hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, adjacentPositionSinceIndirectAdjacentTreeWalk); 826 827 computeBacktrackingHeightFromDescendant(fragment, tagNames, hasDescendantRelationOnTheRight, previousChildFragmentInDescendantBacktrackingChain); 828 829 #if CSS_SELECTOR_JIT_DEBUGGING 830 dataLogF("Computing fragment[%d] backtracking height %u. NotMatched %u / Matched %u\n", i, fragment.heightFromDescendant, fragment.tagNameNotMatchedBacktrackingStartHeightFromDescendant, fragment.tagNameMatchedBacktrackingStartHeightFromDescendant); 831 #endif 661 832 662 833 solveBacktrackingAction(fragment, hasDescendantRelationOnTheRight, ancestorPositionSinceDescendantRelation, hasIndirectAdjacentRelationOnTheRightOfDirectAdjacentChain, adjacentPositionSinceIndirectAdjacentTreeWalk); … … 673 844 if (fragment.relationToLeftFragment == FragmentRelation::DirectAdjacent && fragment.relationToRightFragment == FragmentRelation::IndirectAdjacent) 674 845 fragment.backtrackingFlags |= BacktrackingFlag::IndirectAdjacentEntryPoint; 675 if (fragment.relationToLeftFragment != FragmentRelation::Descendant && fragment.relationToRightFragment == FragmentRelation::Child && isFirstAncestor(ancestorPositionSinceDescendantRelation)) 676 fragment.backtrackingFlags |= BacktrackingFlag::SaveDescendantBacktrackingStart; 846 if (fragment.relationToLeftFragment != FragmentRelation::Descendant && fragment.relationToRightFragment == FragmentRelation::Child && isFirstAncestor(ancestorPositionSinceDescendantRelation)) { 847 ASSERT(saveDescendantBacktrackingStartFragmentIndex == std::numeric_limits<unsigned>::max()); 848 saveDescendantBacktrackingStartFragmentIndex = i; 849 } 677 850 if (fragment.relationToLeftFragment == FragmentRelation::DirectAdjacent && fragment.relationToRightFragment == FragmentRelation::DirectAdjacent && isFirstAdjacent(adjacentPositionSinceIndirectAdjacentTreeWalk)) { 678 851 fragment.backtrackingFlags |= BacktrackingFlag::SaveAdjacentBacktrackingStart; … … 684 857 needsAdjacentTail = false; 685 858 } 686 if (fragment.relationToLeftFragment == FragmentRelation::Descendant && needsDescendantTail) { 687 fragment.backtrackingFlags |= BacktrackingFlag::DescendantTail; 688 needsDescendantTail = false; 859 if (fragment.relationToLeftFragment == FragmentRelation::Descendant) { 860 if (needsDescendantTail) { 861 ASSERT(saveDescendantBacktrackingStartFragmentIndex != std::numeric_limits<unsigned>::max()); 862 fragment.backtrackingFlags |= BacktrackingFlag::DescendantTail; 863 m_selectorFragments[saveDescendantBacktrackingStartFragmentIndex].backtrackingFlags |= BacktrackingFlag::SaveDescendantBacktrackingStart; 864 needsDescendantTail = false; 865 for (unsigned j = saveDescendantBacktrackingStartFragmentIndex; j <= i; ++j) 866 m_selectorFragments[j].backtrackingFlags |= BacktrackingFlag::InChainWithDescendantTail; 867 } 868 saveDescendantBacktrackingStartFragmentIndex = std::numeric_limits<unsigned>::max(); 689 869 } 690 870 } … … 715 895 switch (fragment.relationToRightFragment) { 716 896 case FragmentRelation::Rightmost: 717 generateElementMatching(failureCases, f ragment);897 generateElementMatching(failureCases, failureCases, fragment); 718 898 break; 719 899 case FragmentRelation::Descendant: … … 789 969 } 790 970 971 void SelectorCodeGenerator::generateWalkToParentNode(Assembler::RegisterID targetRegister) 972 { 973 m_assembler.loadPtr(Assembler::Address(elementAddressRegister, Node::parentNodeMemoryOffset()), targetRegister); 974 } 975 791 976 void SelectorCodeGenerator::generateWalkToParentElement(Assembler::JumpList& failureCases, Assembler::RegisterID targetRegister) 792 977 { … … 794 979 // if (!parent || !parent->isElementNode()) 795 980 // failure 796 m_assembler.loadPtr(Assembler::Address(elementAddressRegister, Node::parentNodeMemoryOffset()),targetRegister);981 generateWalkToParentNode(targetRegister); 797 982 failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, targetRegister)); 798 983 failureCases.append(testIsElementFlagOnNode(Assembler::Zero, m_assembler, targetRegister)); … … 805 990 linkFailures(failureCases, fragment.traversalBacktrackingAction, traversalFailureCases); 806 991 807 Assembler::JumpList matchingFailureCases; 808 generateElementMatching(matchingFailureCases, fragment); 809 linkFailures(failureCases, fragment.matchingBacktrackingAction, matchingFailureCases); 992 Assembler::JumpList matchingTagNameFailureCases; 993 Assembler::JumpList matchingPostTagNameFailureCases; 994 generateElementMatching(matchingTagNameFailureCases, matchingPostTagNameFailureCases, fragment); 995 linkFailures(failureCases, fragment.matchingTagNameBacktrackingAction, matchingTagNameFailureCases); 996 linkFailures(failureCases, fragment.matchingPostTagNameBacktrackingAction, matchingPostTagNameFailureCases); 810 997 811 998 if (fragment.backtrackingFlags & BacktrackingFlag::SaveDescendantBacktrackingStart) { … … 828 1015 m_descendantEntryPoint = m_assembler.label(); 829 1016 830 Assembler::JumpList tagMatchingLocalFailureCases;831 generateElementMatching( tagMatchingLocalFailureCases, fragment);832 tagMatchingLocalFailureCases.linkTo(loopStart, &m_assembler);1017 Assembler::JumpList matchingFailureCases; 1018 generateElementMatching(matchingFailureCases, matchingFailureCases, fragment); 1019 matchingFailureCases.linkTo(loopStart, &m_assembler); 833 1020 } 834 1021 … … 885 1072 generateWalkToPreviousAdjacent(failureCases, fragment); 886 1073 887 Assembler::JumpList matchingFailureCases; 888 generateElementMatching(matchingFailureCases, fragment); 889 linkFailures(failureCases, fragment.matchingBacktrackingAction, matchingFailureCases); 1074 Assembler::JumpList matchingTagNameFailureCases; 1075 Assembler::JumpList matchingPostTagNameFailureCases; 1076 generateElementMatching(matchingTagNameFailureCases, matchingPostTagNameFailureCases, fragment); 1077 linkFailures(failureCases, fragment.matchingTagNameBacktrackingAction, matchingTagNameFailureCases); 1078 linkFailures(failureCases, fragment.matchingPostTagNameBacktrackingAction, matchingPostTagNameFailureCases); 890 1079 891 1080 if (fragment.backtrackingFlags & BacktrackingFlag::SaveAdjacentBacktrackingStart) { … … 907 1096 908 1097 Assembler::JumpList localFailureCases; 909 generateElementMatching(localFailureCases, fragment);1098 generateElementMatching(localFailureCases, localFailureCases, fragment); 910 1099 localFailureCases.linkTo(loopStart, &m_assembler); 911 1100 } … … 1162 1351 } 1163 1352 1164 void SelectorCodeGenerator::generateElementMatching(Assembler::JumpList& failureCases, const SelectorFragment& fragment) 1165 { 1353 void SelectorCodeGenerator::generateElementMatching(Assembler::JumpList& matchingTagNameFailureCases, Assembler::JumpList& matchingPostTagNameFailureCases, const SelectorFragment& fragment) 1354 { 1355 if (fragment.tagName) 1356 generateElementHasTagName(matchingTagNameFailureCases, *(fragment.tagName)); 1357 1166 1358 if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassLink)) 1167 generateElementIsLink( failureCases);1359 generateElementIsLink(matchingPostTagNameFailureCases); 1168 1360 1169 1361 if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassRoot)) 1170 generateElementIsRoot( failureCases);1362 generateElementIsRoot(matchingPostTagNameFailureCases); 1171 1363 1172 1364 if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassTarget)) 1173 generateElementIsTarget(failureCases); 1174 1175 if (fragment.tagName) 1176 generateElementHasTagName(failureCases, *(fragment.tagName)); 1365 generateElementIsTarget(matchingPostTagNameFailureCases); 1177 1366 1178 1367 for (unsigned i = 0; i < fragment.unoptimizedPseudoClasses.size(); ++i) 1179 generateElementFunctionCallTest( failureCases, fragment.unoptimizedPseudoClasses[i]);1180 1181 generateElementDataMatching( failureCases, fragment);1368 generateElementFunctionCallTest(matchingPostTagNameFailureCases, fragment.unoptimizedPseudoClasses[i]); 1369 1370 generateElementDataMatching(matchingPostTagNameFailureCases, fragment); 1182 1371 1183 1372 if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassOnlyChild)) 1184 generateElementIsOnlyChild( failureCases, fragment);1373 generateElementIsOnlyChild(matchingPostTagNameFailureCases, fragment); 1185 1374 if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassFirstChild)) 1186 generateElementIsFirstChild( failureCases, fragment);1375 generateElementIsFirstChild(matchingPostTagNameFailureCases, fragment); 1187 1376 if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassLastChild)) 1188 generateElementIsLastChild( failureCases, fragment);1377 generateElementIsLastChild(matchingPostTagNameFailureCases, fragment); 1189 1378 if (!fragment.nthChildfilters.isEmpty()) 1190 generateElementIsNthChild( failureCases, fragment);1379 generateElementIsNthChild(matchingPostTagNameFailureCases, fragment); 1191 1380 } 1192 1381
Note: See TracChangeset
for help on using the changeset viewer.