Changeset 210837 in webkit
- Timestamp:
- Jan 17, 2017 5:27:04 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r210775 r210837 1 2017-01-17 Michael Saboff <msaboff@apple.com> 2 3 Nested parenthesized regular expressions with non-zero minimum counts appear to hang and use lots of memory 4 https://bugs.webkit.org/show_bug.cgi?id=167125 5 6 Reviewed by Filip Pizlo. 7 8 * microbenchmarks/regexp-nested-nonzero-min-counted-parens.js: Added. 9 New test with limits that run slow and take a reasonable amount of memory 10 before the change and run fast, using little memory with the change. 11 1 12 2017-01-14 Yusuke Suzuki <utatane.tea@gmail.com> 2 13 -
trunk/Source/JavaScriptCore/ChangeLog
r210832 r210837 1 2017-01-17 Michael Saboff <msaboff@apple.com> 2 3 Nested parenthesized regular expressions with non-zero minimum counts appear to hang and use lots of memory 4 https://bugs.webkit.org/show_bug.cgi?id=167125 5 6 Reviewed by Filip Pizlo. 7 8 Changed Yarr to handle nested parenthesized subexpressions where the minimum count is 9 not 0 directly in the Yarr interpreter. Previously we'd factor an expression like 10 (a|b)+ into (a|b)(a|b)* with special handling for captures. This factoring was done 11 using a deep copy that doubled the size of the resulting expresion for each nested 12 parenthesized subexpression. Now the Yarr interpreter can directly process a regexp 13 like (a|b){2,42}. 14 15 The parser will allow one level of nested, non-zero minimum, counted parenthesis using 16 the old copy method. After one level, it will generate parenthesis terms with a non-zero 17 minimum. Such an expression wasn't handled by the Yarr JIT before the change, so this 18 change isn't a performance regression. 19 20 Added a minimum count to the YarrPattern and ByteTerm classes, and then factored that 21 minimum into the interpreter. A non-zero minimum is only handled by the Yarr interpreter. 22 If the Yarr JIT see such a term, it punts back to the interpreter. 23 24 * yarr/YarrInterpreter.cpp: 25 (JSC::Yarr::Interpreter::backtrackPatternCharacter): 26 (JSC::Yarr::Interpreter::backtrackPatternCasedCharacter): 27 (JSC::Yarr::Interpreter::matchCharacterClass): 28 (JSC::Yarr::Interpreter::backtrackCharacterClass): 29 (JSC::Yarr::Interpreter::matchBackReference): 30 (JSC::Yarr::Interpreter::backtrackBackReference): 31 (JSC::Yarr::Interpreter::matchParenthesesOnceBegin): 32 (JSC::Yarr::Interpreter::matchParenthesesOnceEnd): 33 (JSC::Yarr::Interpreter::backtrackParenthesesOnceBegin): 34 (JSC::Yarr::Interpreter::backtrackParenthesesOnceEnd): 35 (JSC::Yarr::Interpreter::matchParenthesesTerminalBegin): 36 (JSC::Yarr::Interpreter::backtrackParenthesesTerminalBegin): 37 (JSC::Yarr::Interpreter::matchParentheticalAssertionBegin): 38 (JSC::Yarr::Interpreter::matchParentheticalAssertionEnd): 39 (JSC::Yarr::Interpreter::backtrackParentheticalAssertionBegin): 40 (JSC::Yarr::Interpreter::backtrackParentheticalAssertionEnd): 41 (JSC::Yarr::Interpreter::matchParentheses): 42 (JSC::Yarr::Interpreter::backtrackParentheses): 43 (JSC::Yarr::Interpreter::matchDisjunction): 44 (JSC::Yarr::ByteCompiler::atomPatternCharacter): 45 (JSC::Yarr::ByteCompiler::atomCharacterClass): 46 (JSC::Yarr::ByteCompiler::atomBackReference): 47 (JSC::Yarr::ByteCompiler::atomParentheticalAssertionEnd): 48 (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternEnd): 49 (JSC::Yarr::ByteCompiler::atomParenthesesOnceEnd): 50 (JSC::Yarr::ByteCompiler::atomParenthesesTerminalEnd): 51 (JSC::Yarr::ByteCompiler::emitDisjunction): 52 * yarr/YarrInterpreter.h: 53 (JSC::Yarr::ByteTerm::ByteTerm): 54 * yarr/YarrJIT.cpp: 55 (JSC::Yarr::YarrGenerator::generatePatternCharacterOnce): 56 (JSC::Yarr::YarrGenerator::generatePatternCharacterFixed): 57 (JSC::Yarr::YarrGenerator::generatePatternCharacterGreedy): 58 (JSC::Yarr::YarrGenerator::backtrackPatternCharacterNonGreedy): 59 (JSC::Yarr::YarrGenerator::generateCharacterClassFixed): 60 (JSC::Yarr::YarrGenerator::generateCharacterClassGreedy): 61 (JSC::Yarr::YarrGenerator::backtrackCharacterClassNonGreedy): 62 (JSC::Yarr::YarrGenerator::generateTerm): 63 (JSC::Yarr::YarrGenerator::backtrackTerm): 64 (JSC::Yarr::YarrGenerator::generate): 65 (JSC::Yarr::YarrGenerator::backtrack): 66 (JSC::Yarr::YarrGenerator::opCompileParenthesesSubpattern): 67 * yarr/YarrPattern.cpp: 68 (JSC::Yarr::YarrPatternConstructor::copyTerm): 69 (JSC::Yarr::YarrPatternConstructor::quantifyAtom): 70 (JSC::Yarr::YarrPatternConstructor::checkForTerminalParentheses): 71 (JSC::Yarr::YarrPattern::YarrPattern): 72 * yarr/YarrPattern.h: 73 (JSC::Yarr::PatternTerm::PatternTerm): 74 (JSC::Yarr::PatternTerm::quantify): 75 (JSC::Yarr::YarrPattern::reset): 76 1 77 2017-01-17 Joseph Pecoraro <pecoraro@apple.com> 2 78 -
trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp
r210023 r210837 439 439 440 440 case QuantifierNonGreedy: 441 if ((backTrack->matchAmount < term.atom.quantity Count) && input.checkInput(1)) {441 if ((backTrack->matchAmount < term.atom.quantityMaxCount) && input.checkInput(1)) { 442 442 ++backTrack->matchAmount; 443 443 if (checkCharacter(term.atom.patternCharacter, term.inputPosition + 1)) … … 468 468 469 469 case QuantifierNonGreedy: 470 if ((backTrack->matchAmount < term.atom.quantity Count) && input.checkInput(1)) {470 if ((backTrack->matchAmount < term.atom.quantityMaxCount) && input.checkInput(1)) { 471 471 ++backTrack->matchAmount; 472 472 if (checkCasedCharacter(term.atom.casedCharacter.lo, term.atom.casedCharacter.hi, term.inputPosition + 1)) … … 490 490 backTrack->begin = input.getPos(); 491 491 unsigned matchAmount = 0; 492 for (matchAmount = 0; matchAmount < term.atom.quantity Count; ++matchAmount) {492 for (matchAmount = 0; matchAmount < term.atom.quantityMaxCount; ++matchAmount) { 493 493 if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - matchAmount)) { 494 494 input.setPos(backTrack->begin); … … 500 500 } 501 501 502 for (unsigned matchAmount = 0; matchAmount < term.atom.quantity Count; ++matchAmount) {502 for (unsigned matchAmount = 0; matchAmount < term.atom.quantityMaxCount; ++matchAmount) { 503 503 if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - matchAmount)) 504 504 return false; … … 511 511 backTrack->begin = position; 512 512 unsigned matchAmount = 0; 513 while ((matchAmount < term.atom.quantity Count) && input.checkInput(1)) {513 while ((matchAmount < term.atom.quantityMaxCount) && input.checkInput(1)) { 514 514 if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + 1)) { 515 515 input.setPos(position); … … 566 566 567 567 case QuantifierNonGreedy: 568 if ((backTrack->matchAmount < term.atom.quantity Count) && input.checkInput(1)) {568 if ((backTrack->matchAmount < term.atom.quantityMaxCount) && input.checkInput(1)) { 569 569 ++backTrack->matchAmount; 570 570 if (checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + 1)) … … 603 603 case QuantifierFixedCount: { 604 604 backTrack->begin = input.getPos(); 605 for (unsigned matchAmount = 0; matchAmount < term.atom.quantity Count; ++matchAmount) {605 for (unsigned matchAmount = 0; matchAmount < term.atom.quantityMaxCount; ++matchAmount) { 606 606 if (!tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) { 607 607 input.setPos(backTrack->begin); … … 614 614 case QuantifierGreedy: { 615 615 unsigned matchAmount = 0; 616 while ((matchAmount < term.atom.quantity Count) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition))616 while ((matchAmount < term.atom.quantityMaxCount) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) 617 617 ++matchAmount; 618 618 backTrack->matchAmount = matchAmount; … … 648 648 switch (term.atom.quantityType) { 649 649 case QuantifierFixedCount: 650 // for quantity Count == 1, could rewind.650 // for quantityMaxCount == 1, could rewind. 651 651 input.setPos(backTrack->begin); 652 652 break; … … 661 661 662 662 case QuantifierNonGreedy: 663 if ((backTrack->matchAmount < term.atom.quantity Count) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) {663 if ((backTrack->matchAmount < term.atom.quantityMaxCount) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) { 664 664 ++backTrack->matchAmount; 665 665 return true; … … 709 709 { 710 710 ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceBegin); 711 ASSERT(term.atom.quantity Count == 1);711 ASSERT(term.atom.quantityMaxCount == 1); 712 712 713 713 BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation); … … 739 739 { 740 740 ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceEnd); 741 ASSERT(term.atom.quantity Count == 1);741 ASSERT(term.atom.quantityMaxCount == 1); 742 742 743 743 if (term.capture()) { … … 756 756 { 757 757 ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceBegin); 758 ASSERT(term.atom.quantity Count == 1);758 ASSERT(term.atom.quantityMaxCount == 1); 759 759 760 760 BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation); … … 786 786 { 787 787 ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceEnd); 788 ASSERT(term.atom.quantity Count == 1);788 ASSERT(term.atom.quantityMaxCount == 1); 789 789 790 790 BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation); … … 824 824 ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternTerminalBegin); 825 825 ASSERT(term.atom.quantityType == QuantifierGreedy); 826 ASSERT(term.atom.quantity Count == quantifyInfinite);826 ASSERT(term.atom.quantityMaxCount == quantifyInfinite); 827 827 ASSERT(!term.capture()); 828 828 … … 850 850 ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternTerminalBegin); 851 851 ASSERT(term.atom.quantityType == QuantifierGreedy); 852 ASSERT(term.atom.quantity Count == quantifyInfinite);852 ASSERT(term.atom.quantityMaxCount == quantifyInfinite); 853 853 ASSERT(!term.capture()); 854 854 … … 870 870 { 871 871 ASSERT(term.type == ByteTerm::TypeParentheticalAssertionBegin); 872 ASSERT(term.atom.quantity Count == 1);872 ASSERT(term.atom.quantityMaxCount == 1); 873 873 874 874 BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation); … … 881 881 { 882 882 ASSERT(term.type == ByteTerm::TypeParentheticalAssertionEnd); 883 ASSERT(term.atom.quantity Count == 1);883 ASSERT(term.atom.quantityMaxCount == 1); 884 884 885 885 BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation); … … 899 899 { 900 900 ASSERT(term.type == ByteTerm::TypeParentheticalAssertionBegin); 901 ASSERT(term.atom.quantity Count == 1);901 ASSERT(term.atom.quantityMaxCount == 1); 902 902 903 903 // We've failed to match parens; if they are inverted, this is win! … … 913 913 { 914 914 ASSERT(term.type == ByteTerm::TypeParentheticalAssertionEnd); 915 ASSERT(term.atom.quantity Count == 1);915 ASSERT(term.atom.quantityMaxCount == 1); 916 916 917 917 BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation); … … 933 933 backTrack->lastContext = 0; 934 934 935 switch (term.atom.quantityType) { 936 case QuantifierFixedCount: { 935 ASSERT(term.atom.quantityType != QuantifierFixedCount || term.atom.quantityMinCount == term.atom.quantityMaxCount); 936 937 unsigned minimumMatchCount = term.atom.quantityMinCount; 938 JSRegExpResult fixedMatchResult; 939 940 // Handle fixed matches and the minimum part of a variable length match. 941 if (minimumMatchCount) { 937 942 // While we haven't yet reached our fixed limit, 938 while (backTrack->matchAmount < term.atom.quantityCount) {943 while (backTrack->matchAmount < minimumMatchCount) { 939 944 // Try to do a match, and it it succeeds, add it to the list. 940 945 ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term); 941 JSRegExpResult result = matchDisjunction(disjunctionBody, context->getDisjunctionContext(term));942 if ( result == JSRegExpMatch)946 fixedMatchResult = matchDisjunction(disjunctionBody, context->getDisjunctionContext(term)); 947 if (fixedMatchResult == JSRegExpMatch) 943 948 appendParenthesesDisjunctionContext(backTrack, context); 944 949 else { … … 946 951 resetMatches(term, context); 947 952 freeParenthesesDisjunctionContext(context); 948 949 if ( result != JSRegExpNoMatch)950 return result;953 954 if (fixedMatchResult != JSRegExpNoMatch) 955 return fixedMatchResult; 951 956 JSRegExpResult backtrackResult = parenthesesDoBacktrack(term, backTrack); 952 957 if (backtrackResult != JSRegExpMatch) … … 955 960 } 956 961 957 ASSERT(backTrack->matchAmount == term.atom.quantityCount);958 962 ParenthesesDisjunctionContext* context = backTrack->lastContext; 959 963 recordParenthesesMatch(term, context); 964 } 965 966 switch (term.atom.quantityType) { 967 case QuantifierFixedCount: { 968 ASSERT(backTrack->matchAmount == term.atom.quantityMaxCount); 960 969 return JSRegExpMatch; 961 970 } 962 971 963 972 case QuantifierGreedy: { 964 while (backTrack->matchAmount < term.atom.quantity Count) {973 while (backTrack->matchAmount < term.atom.quantityMaxCount) { 965 974 ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term); 966 975 JSRegExpResult result = matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term)); … … 1012 1021 switch (term.atom.quantityType) { 1013 1022 case QuantifierFixedCount: { 1014 ASSERT(backTrack->matchAmount == term.atom.quantity Count);1023 ASSERT(backTrack->matchAmount == term.atom.quantityMaxCount); 1015 1024 1016 1025 ParenthesesDisjunctionContext* context = 0; … … 1021 1030 1022 1031 // While we haven't yet reached our fixed limit, 1023 while (backTrack->matchAmount < term.atom.quantity Count) {1032 while (backTrack->matchAmount < term.atom.quantityMaxCount) { 1024 1033 // Try to do a match, and it it succeeds, add it to the list. 1025 1034 context = allocParenthesesDisjunctionContext(disjunctionBody, output, term); … … 1041 1050 } 1042 1051 1043 ASSERT(backTrack->matchAmount == term.atom.quantity Count);1052 ASSERT(backTrack->matchAmount == term.atom.quantityMaxCount); 1044 1053 context = backTrack->lastContext; 1045 1054 recordParenthesesMatch(term, context); … … 1054 1063 JSRegExpResult result = matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term), true); 1055 1064 if (result == JSRegExpMatch) { 1056 while (backTrack->matchAmount < term.atom.quantity Count) {1065 while (backTrack->matchAmount < term.atom.quantityMaxCount) { 1057 1066 ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term); 1058 1067 JSRegExpResult parenthesesResult = matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term)); … … 1087 1096 case QuantifierNonGreedy: { 1088 1097 // If we've not reached the limit, try to add one more match. 1089 if (backTrack->matchAmount < term.atom.quantity Count) {1098 if (backTrack->matchAmount < term.atom.quantityMaxCount) { 1090 1099 ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term); 1091 1100 JSRegExpResult result = matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term)); … … 1224 1233 if (unicode) { 1225 1234 if (!U_IS_BMP(currentTerm().atom.patternCharacter)) { 1226 for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantity Count; ++matchAmount) {1235 for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityMaxCount; ++matchAmount) { 1227 1236 if (!checkSurrogatePair(currentTerm().atom.patternCharacter, currentTerm().inputPosition - 2 * matchAmount)) { 1228 1237 BACKTRACK(); … … 1234 1243 unsigned position = input.getPos(); // May need to back out reading a surrogate pair. 1235 1244 1236 for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantity Count; ++matchAmount) {1245 for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityMaxCount; ++matchAmount) { 1237 1246 if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition - matchAmount)) { 1238 1247 input.setPos(position); … … 1246 1255 unsigned matchAmount = 0; 1247 1256 unsigned position = input.getPos(); // May need to back out reading a surrogate pair. 1248 while ((matchAmount < currentTerm().atom.quantity Count) && input.checkInput(1)) {1257 while ((matchAmount < currentTerm().atom.quantityMaxCount) && input.checkInput(1)) { 1249 1258 if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition + 1)) { 1250 1259 input.setPos(position); … … 1273 1282 unsigned position = input.getPos(); // May need to back out reading a surrogate pair. 1274 1283 1275 for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantity Count; ++matchAmount) {1284 for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityMaxCount; ++matchAmount) { 1276 1285 if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition - matchAmount)) { 1277 1286 input.setPos(position); … … 1282 1291 } 1283 1292 1284 for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantity Count; ++matchAmount) {1293 for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityMaxCount; ++matchAmount) { 1285 1294 if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition - matchAmount)) 1286 1295 BACKTRACK(); … … 1295 1304 1296 1305 unsigned matchAmount = 0; 1297 while ((matchAmount < currentTerm().atom.quantity Count) && input.checkInput(1)) {1306 while ((matchAmount < currentTerm().atom.quantityMaxCount) && input.checkInput(1)) { 1298 1307 if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition + 1)) { 1299 1308 input.uncheckInput(1); … … 1623 1632 } 1624 1633 1625 void atomPatternCharacter(UChar32 ch, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantity Count, QuantifierType quantityType)1634 void atomPatternCharacter(UChar32 ch, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityMaxCount, QuantifierType quantityType) 1626 1635 { 1627 1636 if (m_pattern.ignoreCase()) { … … 1630 1639 1631 1640 if (lo != hi) { 1632 m_bodyDisjunction->terms.append(ByteTerm(lo, hi, inputPosition, frameLocation, quantity Count, quantityType));1641 m_bodyDisjunction->terms.append(ByteTerm(lo, hi, inputPosition, frameLocation, quantityMaxCount, quantityType)); 1633 1642 return; 1634 1643 } 1635 1644 } 1636 1645 1637 m_bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantity Count, quantityType));1638 } 1639 1640 void atomCharacterClass(CharacterClass* characterClass, bool invert, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantity Count, QuantifierType quantityType)1646 m_bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityMaxCount, quantityType)); 1647 } 1648 1649 void atomCharacterClass(CharacterClass* characterClass, bool invert, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityMaxCount, QuantifierType quantityType) 1641 1650 { 1642 1651 m_bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition)); 1643 1652 1644 m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantity Count = quantityCount.unsafeGet();1653 m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityMaxCount = quantityMaxCount.unsafeGet(); 1645 1654 m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType; 1646 1655 m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation; 1647 1656 } 1648 1657 1649 void atomBackReference(unsigned subpatternId, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantity Count, QuantifierType quantityType)1658 void atomBackReference(unsigned subpatternId, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityMaxCount, QuantifierType quantityType) 1650 1659 { 1651 1660 ASSERT(subpatternId); … … 1653 1662 m_bodyDisjunction->terms.append(ByteTerm::BackReference(subpatternId, inputPosition)); 1654 1663 1655 m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantity Count = quantityCount.unsafeGet();1664 m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityMaxCount = quantityMaxCount.unsafeGet(); 1656 1665 m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType; 1657 1666 m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation; … … 1714 1723 } 1715 1724 1716 void atomParentheticalAssertionEnd(unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantity Count, QuantifierType quantityType)1725 void atomParentheticalAssertionEnd(unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityMaxCount, QuantifierType quantityType) 1717 1726 { 1718 1727 unsigned beginTerm = popParenthesesStack(); … … 1730 1739 m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation; 1731 1740 1732 m_bodyDisjunction->terms[beginTerm].atom.quantity Count = quantityCount.unsafeGet();1741 m_bodyDisjunction->terms[beginTerm].atom.quantityMaxCount = quantityMaxCount.unsafeGet(); 1733 1742 m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType; 1734 m_bodyDisjunction->terms[endTerm].atom.quantity Count = quantityCount.unsafeGet();1743 m_bodyDisjunction->terms[endTerm].atom.quantityMaxCount = quantityMaxCount.unsafeGet(); 1735 1744 m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType; 1736 1745 } … … 1812 1821 } 1813 1822 1814 void atomParenthesesSubpatternEnd(unsigned lastSubpatternId, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantity Count, QuantifierType quantityType, unsigned callFrameSize = 0)1823 void atomParenthesesSubpatternEnd(unsigned lastSubpatternId, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityMinCount, Checked<unsigned> quantityMaxCount, QuantifierType quantityType, unsigned callFrameSize = 0) 1815 1824 { 1816 1825 unsigned beginTerm = popParenthesesStack(); … … 1841 1850 m_allParenthesesInfo.append(WTFMove(parenthesesDisjunction)); 1842 1851 1843 m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount.unsafeGet(); 1852 m_bodyDisjunction->terms[beginTerm].atom.quantityMinCount = quantityMinCount.unsafeGet(); 1853 m_bodyDisjunction->terms[beginTerm].atom.quantityMaxCount = quantityMaxCount.unsafeGet(); 1844 1854 m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType; 1845 1855 m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation; 1846 1856 } 1847 1857 1848 void atomParenthesesOnceEnd(unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantity Count, QuantifierType quantityType)1858 void atomParenthesesOnceEnd(unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityMinCount, Checked<unsigned> quantityMaxCount, QuantifierType quantityType) 1849 1859 { 1850 1860 unsigned beginTerm = popParenthesesStack(); … … 1862 1872 m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation; 1863 1873 1864 m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount.unsafeGet(); 1874 m_bodyDisjunction->terms[beginTerm].atom.quantityMinCount = quantityMinCount.unsafeGet(); 1875 m_bodyDisjunction->terms[beginTerm].atom.quantityMaxCount = quantityMaxCount.unsafeGet(); 1865 1876 m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType; 1866 m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount.unsafeGet(); 1877 m_bodyDisjunction->terms[endTerm].atom.quantityMinCount = quantityMinCount.unsafeGet(); 1878 m_bodyDisjunction->terms[endTerm].atom.quantityMaxCount = quantityMaxCount.unsafeGet(); 1867 1879 m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType; 1868 1880 } 1869 1881 1870 void atomParenthesesTerminalEnd(unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantity Count, QuantifierType quantityType)1882 void atomParenthesesTerminalEnd(unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityMinCount, Checked<unsigned> quantityMaxCount, QuantifierType quantityType) 1871 1883 { 1872 1884 unsigned beginTerm = popParenthesesStack(); … … 1884 1896 m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation; 1885 1897 1886 m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount.unsafeGet(); 1898 m_bodyDisjunction->terms[beginTerm].atom.quantityMinCount = quantityMinCount.unsafeGet(); 1899 m_bodyDisjunction->terms[beginTerm].atom.quantityMaxCount = quantityMaxCount.unsafeGet(); 1887 1900 m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType; 1888 m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount.unsafeGet(); 1901 m_bodyDisjunction->terms[endTerm].atom.quantityMinCount = quantityMinCount.unsafeGet(); 1902 m_bodyDisjunction->terms[endTerm].atom.quantityMaxCount = quantityMaxCount.unsafeGet(); 1889 1903 m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType; 1890 1904 } … … 1959 1973 1960 1974 case PatternTerm::TypePatternCharacter: 1961 atomPatternCharacter(term.patternCharacter, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantity Count, term.quantityType);1975 atomPatternCharacter(term.patternCharacter, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantityMaxCount, term.quantityType); 1962 1976 break; 1963 1977 1964 1978 case PatternTerm::TypeCharacterClass: 1965 atomCharacterClass(term.characterClass, term.invert(), currentCountAlreadyChecked- term.inputPosition, term.frameLocation, term.quantity Count, term.quantityType);1979 atomCharacterClass(term.characterClass, term.invert(), currentCountAlreadyChecked- term.inputPosition, term.frameLocation, term.quantityMaxCount, term.quantityType); 1966 1980 break; 1967 1981 1968 1982 case PatternTerm::TypeBackReference: 1969 atomBackReference(term.backReferenceSubpatternId, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantity Count, term.quantityType);1983 atomBackReference(term.backReferenceSubpatternId, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantityMaxCount, term.quantityType); 1970 1984 break; 1971 1985 … … 1975 1989 case PatternTerm::TypeParenthesesSubpattern: { 1976 1990 unsigned disjunctionAlreadyCheckedCount = 0; 1977 if (term.quantity Count == 1 && !term.parentheses.isCopy) {1991 if (term.quantityMaxCount == 1 && !term.parentheses.isCopy) { 1978 1992 unsigned alternativeFrameLocation = term.frameLocation; 1979 1993 // For QuantifierFixedCount we pre-check the minimum size; for greedy/non-greedy we reserve a slot in the frame. … … 1986 2000 atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount + delegateEndInputOffset, term.frameLocation, alternativeFrameLocation); 1987 2001 emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount); 1988 atomParenthesesOnceEnd(delegateEndInputOffset, term.frameLocation, term.quantity Count, term.quantityType);2002 atomParenthesesOnceEnd(delegateEndInputOffset, term.frameLocation, term.quantityMinCount, term.quantityMaxCount, term.quantityType); 1989 2003 } else if (term.parentheses.isTerminal) { 1990 2004 ASSERT(currentCountAlreadyChecked >= term.inputPosition); … … 1992 2006 atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount + delegateEndInputOffset, term.frameLocation, term.frameLocation + YarrStackSpaceForBackTrackInfoParenthesesOnce); 1993 2007 emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount); 1994 atomParenthesesTerminalEnd(delegateEndInputOffset, term.frameLocation, term.quantity Count, term.quantityType);2008 atomParenthesesTerminalEnd(delegateEndInputOffset, term.frameLocation, term.quantityMinCount, term.quantityMaxCount, term.quantityType); 1995 2009 } else { 1996 2010 ASSERT(currentCountAlreadyChecked >= term.inputPosition); … … 1998 2012 atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount + delegateEndInputOffset, term.frameLocation, 0); 1999 2013 emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0); 2000 atomParenthesesSubpatternEnd(term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantity Count, term.quantityType, term.parentheses.disjunction->m_callFrameSize);2014 atomParenthesesSubpatternEnd(term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityMinCount, term.quantityMaxCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize); 2001 2015 } 2002 2016 break; … … 2017 2031 atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invert(), term.frameLocation, alternativeFrameLocation); 2018 2032 emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, positiveInputOffset - uncheckAmount); 2019 atomParentheticalAssertionEnd(0, term.frameLocation, term.quantity Count, term.quantityType);2033 atomParentheticalAssertionEnd(0, term.frameLocation, term.quantityMaxCount, term.quantityType); 2020 2034 if (uncheckAmount) { 2021 2035 checkInput(uncheckAmount); -
trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h
r208761 r210837 88 88 }; 89 89 QuantifierType quantityType; 90 unsigned quantityCount; 90 unsigned quantityMinCount; 91 unsigned quantityMaxCount; 91 92 } atom; 92 93 struct { … … 111 112 , m_invert(false) 112 113 { 114 atom.patternCharacter = ch; 115 atom.quantityType = quantityType; 116 atom.quantityMinCount = quantityCount.unsafeGet(); 117 atom.quantityMaxCount = quantityCount.unsafeGet(); 118 inputPosition = inputPos; 119 113 120 switch (quantityType) { 114 121 case QuantifierFixedCount: … … 122 129 break; 123 130 } 124 125 atom.patternCharacter = ch;126 atom.quantityType = quantityType;127 atom.quantityCount = quantityCount.unsafeGet();128 inputPosition = inputPos;129 131 } 130 132 … … 149 151 atom.casedCharacter.hi = hi; 150 152 atom.quantityType = quantityType; 151 atom.quantityCount = quantityCount.unsafeGet(); 153 atom.quantityMinCount = quantityCount.unsafeGet(); 154 atom.quantityMaxCount = quantityCount.unsafeGet(); 152 155 inputPosition = inputPos; 153 156 } … … 160 163 atom.characterClass = characterClass; 161 164 atom.quantityType = QuantifierFixedCount; 162 atom.quantityCount = 1; 165 atom.quantityMinCount = 1; 166 atom.quantityMaxCount = 1; 163 167 inputPosition = inputPos; 164 168 } … … 172 176 atom.parenthesesDisjunction = parenthesesInfo; 173 177 atom.quantityType = QuantifierFixedCount; 174 atom.quantityCount = 1; 178 atom.quantityMinCount = 1; 179 atom.quantityMaxCount = 1; 175 180 inputPosition = inputPos; 176 181 } … … 182 187 { 183 188 atom.quantityType = QuantifierFixedCount; 184 atom.quantityCount = 1; 189 atom.quantityMinCount = 1; 190 atom.quantityMaxCount = 1; 185 191 } 186 192 … … 192 198 atom.subpatternId = subpatternId; 193 199 atom.quantityType = QuantifierFixedCount; 194 atom.quantityCount = 1; 200 atom.quantityMinCount = 1; 201 atom.quantityMaxCount = 1; 195 202 inputPosition = inputPos; 196 203 } -
trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp
r210232 r210837 454 454 OpSimpleNestedAlternativeNext, 455 455 OpSimpleNestedAlternativeEnd, 456 // Used to wrap 'Once' subpattern matches (quantity Count == 1).456 // Used to wrap 'Once' subpattern matches (quantityMaxCount == 1). 457 457 OpParenthesesSubpatternOnceBegin, 458 458 OpParenthesesSubpatternOnceEnd, … … 831 831 if (nextTerm->type != PatternTerm::TypePatternCharacter 832 832 || nextTerm->quantityType != QuantifierFixedCount 833 || nextTerm->quantity Count != 1833 || nextTerm->quantityMaxCount != 1 834 834 || nextTerm->inputPosition != (startTermPosition + numberCharacters)) 835 835 break; … … 914 914 915 915 move(index, countRegister); 916 sub32(Imm32(term->quantity Count.unsafeGet()), countRegister);916 sub32(Imm32(term->quantityMaxCount.unsafeGet()), countRegister); 917 917 918 918 Label loop(this); 919 readCharacter(m_checkedOffset - term->inputPosition - term->quantity Count, character, countRegister);919 readCharacter(m_checkedOffset - term->inputPosition - term->quantityMaxCount, character, countRegister); 920 920 // For case-insesitive compares, non-ascii characters that have different 921 921 // upper & lower case representations are converted to a character class. … … 955 955 add32(TrustedImm32(1), countRegister); 956 956 add32(TrustedImm32(1), index); 957 if (term->quantity Count == quantifyInfinite)957 if (term->quantityMaxCount == quantifyInfinite) 958 958 jump(loop); 959 959 else 960 branch32(NotEqual, countRegister, Imm32(term->quantity Count.unsafeGet())).linkTo(loop, this);960 branch32(NotEqual, countRegister, Imm32(term->quantityMaxCount.unsafeGet())).linkTo(loop, this); 961 961 962 962 failures.link(this); … … 1010 1010 JumpList nonGreedyFailures; 1011 1011 nonGreedyFailures.append(atEndOfInput()); 1012 if (term->quantity Count != quantifyInfinite)1013 nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantity Count.unsafeGet())));1012 if (term->quantityMaxCount != quantifyInfinite) 1013 nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityMaxCount.unsafeGet()))); 1014 1014 nonGreedyFailures.append(jumpIfCharNotEquals(ch, m_checkedOffset - term->inputPosition, character)); 1015 1015 … … 1057 1057 1058 1058 move(index, countRegister); 1059 sub32(Imm32(term->quantity Count.unsafeGet()), countRegister);1059 sub32(Imm32(term->quantityMaxCount.unsafeGet()), countRegister); 1060 1060 1061 1061 Label loop(this); 1062 1062 JumpList matchDest; 1063 readCharacter(m_checkedOffset - term->inputPosition - term->quantity Count, character, countRegister);1063 readCharacter(m_checkedOffset - term->inputPosition - term->quantityMaxCount, character, countRegister); 1064 1064 matchCharacterClass(character, matchDest, term->characterClass); 1065 1065 … … 1106 1106 add32(TrustedImm32(1), countRegister); 1107 1107 add32(TrustedImm32(1), index); 1108 if (term->quantity Count != quantifyInfinite) {1109 branch32(NotEqual, countRegister, Imm32(term->quantity Count.unsafeGet())).linkTo(loop, this);1108 if (term->quantityMaxCount != quantifyInfinite) { 1109 branch32(NotEqual, countRegister, Imm32(term->quantityMaxCount.unsafeGet())).linkTo(loop, this); 1110 1110 failures.append(jump()); 1111 1111 } else … … 1159 1159 1160 1160 nonGreedyFailures.append(atEndOfInput()); 1161 nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantity Count.unsafeGet())));1161 nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityMaxCount.unsafeGet()))); 1162 1162 1163 1163 JumpList matchDest; … … 1255 1255 switch (term->quantityType) { 1256 1256 case QuantifierFixedCount: 1257 if (term->quantity Count == 1)1257 if (term->quantityMaxCount == 1) 1258 1258 generatePatternCharacterOnce(opIndex); 1259 1259 else … … 1272 1272 switch (term->quantityType) { 1273 1273 case QuantifierFixedCount: 1274 if (term->quantity Count == 1)1274 if (term->quantityMaxCount == 1) 1275 1275 generateCharacterClassOnce(opIndex); 1276 1276 else … … 1321 1321 switch (term->quantityType) { 1322 1322 case QuantifierFixedCount: 1323 if (term->quantity Count == 1)1323 if (term->quantityMaxCount == 1) 1324 1324 backtrackPatternCharacterOnce(opIndex); 1325 1325 else … … 1338 1338 switch (term->quantityType) { 1339 1339 case QuantifierFixedCount: 1340 if (term->quantity Count == 1)1340 if (term->quantityMaxCount == 1) 1341 1341 backtrackCharacterClassOnce(opIndex); 1342 1342 else … … 1607 1607 unsigned parenthesesFrameLocation = term->frameLocation; 1608 1608 const RegisterID indexTemporary = regT0; 1609 ASSERT(term->quantity Count == 1);1609 ASSERT(term->quantityMaxCount == 1); 1610 1610 1611 1611 // Upon entry to a Greedy quantified set of parenthese store the index. … … 1654 1654 PatternTerm* term = op.m_term; 1655 1655 const RegisterID indexTemporary = regT0; 1656 ASSERT(term->quantity Count == 1);1656 ASSERT(term->quantityMaxCount == 1); 1657 1657 1658 1658 // Runtime ASSERT to make sure that the nested alternative handled the … … 1697 1697 PatternTerm* term = op.m_term; 1698 1698 ASSERT(term->quantityType == QuantifierGreedy); 1699 ASSERT(term->quantity Count == quantifyInfinite);1699 ASSERT(term->quantityMaxCount == quantifyInfinite); 1700 1700 ASSERT(!term->capture()); 1701 1701 … … 2181 2181 case OpParenthesesSubpatternOnceBegin: { 2182 2182 PatternTerm* term = op.m_term; 2183 ASSERT(term->quantity Count == 1);2183 ASSERT(term->quantityMaxCount == 1); 2184 2184 2185 2185 // We only need to backtrack to thispoint if capturing or greedy. … … 2320 2320 // of a set of alternatives wrapped in an outer set of nodes for 2321 2321 // the parentheses. 2322 // Supported types of parentheses are 'Once' (quantity Count == 1)2322 // Supported types of parentheses are 'Once' (quantityMaxCount == 1) 2323 2323 // and 'Terminal' (non-capturing parentheses quantified as greedy 2324 2324 // and infinite). … … 2341 2341 // need to restore the capture from the first subpattern upon a 2342 2342 // failure in the second. 2343 if (term->quantityCount == 1 && !term->parentheses.isCopy) { 2343 if (term->quantityMinCount && term->quantityMinCount != term->quantityMaxCount) { 2344 m_shouldFallBack = true; 2345 return; 2346 } if (term->quantityMaxCount == 1 && !term->parentheses.isCopy) { 2344 2347 // Select the 'Once' nodes. 2345 2348 parenthesesBeginOpCode = OpParenthesesSubpatternOnceBegin; -
trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp
r205937 r210837 523 523 PatternTerm termCopy = term; 524 524 termCopy.parentheses.disjunction = copyDisjunction(termCopy.parentheses.disjunction, filterStartsWithBOL); 525 m_pattern.m_hasCopiedParenSubexpressions = true; 525 526 return termCopy; 526 527 } … … 538 539 PatternTerm& term = m_alternative->lastTerm(); 539 540 ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary); 540 ASSERT( (term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount));541 ASSERT(term.quantityMinCount == 1 && term.quantityMaxCount == 1 && term.quantityType == QuantifierFixedCount); 541 542 542 543 if (term.type == PatternTerm::TypeParentheticalAssertion) { … … 560 561 } 561 562 562 if (min == 0)563 term.quantify(m ax, greedy ? QuantifierGreedy : QuantifierNonGreedy);564 else if ( min == max)565 term.quantify(min, QuantifierFixedCount);563 if (min == max) 564 term.quantify(min, max, QuantifierFixedCount); 565 else if (!min || (term.type == PatternTerm::TypeParenthesesSubpattern && m_pattern.m_hasCopiedParenSubexpressions)) 566 term.quantify(min, max, greedy ? QuantifierGreedy : QuantifierNonGreedy); 566 567 else { 567 term.quantify(min, QuantifierFixedCount);568 term.quantify(min, min, QuantifierFixedCount); 568 569 m_alternative->m_terms.append(copyTerm(term)); 569 570 // NOTE: this term is interesting from an analysis perspective, in that it can be ignored..... … … 615 616 alternative->m_hasFixedSize = false; 616 617 } else if (m_pattern.unicode()) { 617 currentInputPosition += U16_LENGTH(term.patternCharacter) * term.quantity Count;618 currentInputPosition += U16_LENGTH(term.patternCharacter) * term.quantityMaxCount; 618 619 } else 619 currentInputPosition += term.quantity Count;620 currentInputPosition += term.quantityMaxCount; 620 621 break; 621 622 … … 629 630 term.frameLocation = currentCallFrameSize; 630 631 currentCallFrameSize += YarrStackSpaceForBackTrackInfoCharacterClass; 631 currentInputPosition += term.quantity Count;632 currentInputPosition += term.quantityMaxCount; 632 633 alternative->m_hasFixedSize = false; 633 634 } else 634 currentInputPosition += term.quantity Count;635 currentInputPosition += term.quantityMaxCount; 635 636 break; 636 637 … … 638 639 // Note: for fixed once parentheses we will ensure at least the minimum is available; others are on their own. 639 640 term.frameLocation = currentCallFrameSize; 640 if (term.quantity Count == 1 && !term.parentheses.isCopy) {641 if (term.quantityMaxCount == 1 && !term.parentheses.isCopy) { 641 642 if (term.quantityType != QuantifierFixedCount) 642 643 currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesOnce; … … 755 756 if (term.type == PatternTerm::TypeParenthesesSubpattern 756 757 && term.quantityType == QuantifierGreedy 757 && term.quantityCount == quantifyInfinite 758 && term.quantityMinCount == 0 759 && term.quantityMaxCount == quantifyInfinite 758 760 && !term.capture()) 759 761 term.parentheses.isTerminal = true; … … 956 958 , m_containsBOL(false) 957 959 , m_containsUnsignedLengthPattern(false) 960 , m_hasCopiedParenSubexpressions(false) 958 961 , m_flags(flags) 959 962 , m_numSubpatterns(0) -
trunk/Source/JavaScriptCore/yarr/YarrPattern.h
r206525 r210837 109 109 }; 110 110 QuantifierType quantityType; 111 Checked<unsigned> quantityCount; 111 Checked<unsigned> quantityMinCount; 112 Checked<unsigned> quantityMaxCount; 112 113 unsigned inputPosition; 113 114 unsigned frameLocation; … … 120 121 patternCharacter = ch; 121 122 quantityType = QuantifierFixedCount; 122 quantity Count = 1;123 quantityMinCount = quantityMaxCount = 1; 123 124 } 124 125 … … 130 131 characterClass = charClass; 131 132 quantityType = QuantifierFixedCount; 132 quantity Count = 1;133 quantityMinCount = quantityMaxCount = 1; 133 134 } 134 135 … … 143 144 parentheses.isTerminal = false; 144 145 quantityType = QuantifierFixedCount; 145 quantity Count = 1;146 quantityMinCount = quantityMaxCount = 1; 146 147 } 147 148 … … 152 153 { 153 154 quantityType = QuantifierFixedCount; 154 quantity Count = 1;155 quantityMinCount = quantityMaxCount = 1; 155 156 } 156 157 … … 162 163 backReferenceSubpatternId = spatternId; 163 164 quantityType = QuantifierFixedCount; 164 quantity Count = 1;165 quantityMinCount = quantityMaxCount = 1; 165 166 } 166 167 … … 173 174 anchors.eolAnchor = eolAnchor; 174 175 quantityType = QuantifierFixedCount; 175 quantity Count = 1;176 quantityMinCount = quantityMaxCount = 1; 176 177 } 177 178 … … 208 209 void quantify(unsigned count, QuantifierType type) 209 210 { 210 quantityCount = count; 211 quantityMinCount = 0; 212 quantityMaxCount = count; 213 quantityType = type; 214 } 215 216 void quantify(unsigned minCount, unsigned maxCount, QuantifierType type) 217 { 218 // Currently only Parentheses can specify a non-zero min with a different max. 219 ASSERT(this->type == TypeParenthesesSubpattern || !minCount || minCount == maxCount); 220 ASSERT(minCount <= maxCount); 221 quantityMinCount = minCount; 222 quantityMaxCount = maxCount; 211 223 quantityType = type; 212 224 } … … 335 347 m_containsBOL = false; 336 348 m_containsUnsignedLengthPattern = false; 349 m_hasCopiedParenSubexpressions = false; 337 350 338 351 newlineCached = 0; … … 440 453 bool m_containsBackreferences : 1; 441 454 bool m_containsBOL : 1; 442 bool m_containsUnsignedLengthPattern : 1; 455 bool m_containsUnsignedLengthPattern : 1; 456 bool m_hasCopiedParenSubexpressions : 1; 443 457 RegExpFlags m_flags; 444 458 unsigned m_numSubpatterns;
Note: See TracChangeset
for help on using the changeset viewer.