📄 wrecgenerator.cpp
字号:
if (m_parser.ignoreCase() && hasUpper) { // for unicode case insensitive matches, branch here if upper matches. isUpper.link(this); } // on success consume the char add32(Imm32(1), index);}void Generator::generateCharacterClassInvertedRange(JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount){ do { // pick which range we're going to generate int which = count >> 1; char lo = ranges[which].begin; char hi = ranges[which].end; // check if there are any ranges or matches below lo. If not, just jl to failure - // if there is anything else to check, check that first, if it falls through jmp to failure. if ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) { Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo)); // generate code for all ranges before this one if (which) generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount); while ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) { matchDest.append(branch32(Equal, character, Imm32((unsigned short)matches[*matchIndex]))); ++*matchIndex; } failures.append(jump()); loOrAbove.link(this); } else if (which) { Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo)); generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount); failures.append(jump()); loOrAbove.link(this); } else failures.append(branch32(LessThan, character, Imm32((unsigned short)lo))); while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi)) ++*matchIndex; matchDest.append(branch32(LessThanOrEqual, character, Imm32((unsigned short)hi))); // fall through to here, the value is above hi. // shuffle along & loop around if there are any more matches to handle. unsigned next = which + 1; ranges += next; count -= next; } while (count);}void Generator::generateCharacterClassInverted(JumpList& matchDest, const CharacterClass& charClass){ Jump unicodeFail; if (charClass.numMatchesUnicode || charClass.numRangesUnicode) { Jump isAscii = branch32(LessThanOrEqual, character, Imm32(0x7f)); if (charClass.numMatchesUnicode) { for (unsigned i = 0; i < charClass.numMatchesUnicode; ++i) { UChar ch = charClass.matchesUnicode[i]; matchDest.append(branch32(Equal, character, Imm32(ch))); } } if (charClass.numRangesUnicode) { for (unsigned i = 0; i < charClass.numRangesUnicode; ++i) { UChar lo = charClass.rangesUnicode[i].begin; UChar hi = charClass.rangesUnicode[i].end; Jump below = branch32(LessThan, character, Imm32(lo)); matchDest.append(branch32(LessThanOrEqual, character, Imm32(hi))); below.link(this); } } unicodeFail = jump(); isAscii.link(this); } if (charClass.numRanges) { unsigned matchIndex = 0; JumpList failures; generateCharacterClassInvertedRange(failures, matchDest, charClass.ranges, charClass.numRanges, &matchIndex, charClass.matches, charClass.numMatches); while (matchIndex < charClass.numMatches) matchDest.append(branch32(Equal, character, Imm32((unsigned short)charClass.matches[matchIndex++]))); failures.link(this); } else if (charClass.numMatches) { // optimization: gather 'a','A' etc back together, can mask & test once. Vector<char> matchesAZaz; for (unsigned i = 0; i < charClass.numMatches; ++i) { char ch = charClass.matches[i]; if (m_parser.ignoreCase()) { if (isASCIILower(ch)) { matchesAZaz.append(ch); continue; } if (isASCIIUpper(ch)) continue; } matchDest.append(branch32(Equal, character, Imm32((unsigned short)ch))); } if (unsigned countAZaz = matchesAZaz.size()) { or32(Imm32(32), character); for (unsigned i = 0; i < countAZaz; ++i) matchDest.append(branch32(Equal, character, Imm32(matchesAZaz[i]))); } } if (charClass.numMatchesUnicode || charClass.numRangesUnicode) unicodeFail.link(this);}void Generator::generateCharacterClass(JumpList& failures, const CharacterClass& charClass, bool invert){ generateLoadCharacter(failures); if (invert) generateCharacterClassInverted(failures, charClass); else { JumpList successes; generateCharacterClassInverted(successes, charClass); failures.append(jump()); successes.link(this); } add32(Imm32(1), index);}void Generator::generateParenthesesAssertion(JumpList& failures){ JumpList disjunctionFailed; push(index); m_parser.parseDisjunction(disjunctionFailed); Jump success = jump(); disjunctionFailed.link(this); pop(index); failures.append(jump()); success.link(this); pop(index);}void Generator::generateParenthesesInvertedAssertion(JumpList& failures){ JumpList disjunctionFailed; push(index); m_parser.parseDisjunction(disjunctionFailed); // If the disjunction succeeded, the inverted assertion failed. pop(index); failures.append(jump()); // If the disjunction failed, the inverted assertion succeeded. disjunctionFailed.link(this); pop(index);}void Generator::generateParenthesesNonGreedy(JumpList& failures, Label start, Jump success, Jump fail){ jump(start); success.link(this); failures.append(fail);}Generator::Jump Generator::generateParenthesesResetTrampoline(JumpList& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter){ Jump skip = jump(); newFailures.link(this); for (unsigned i = subpatternIdBefore + 1; i <= subpatternIdAfter; ++i) { store32(Imm32(-1), Address(output, (2 * i) * sizeof(int))); store32(Imm32(-1), Address(output, (2 * i + 1) * sizeof(int))); } Jump newFailJump = jump(); skip.link(this); return newFailJump;}void Generator::generateAssertionBOL(JumpList& failures){ if (m_parser.multiline()) { JumpList previousIsNewline; // begin of input == success previousIsNewline.append(branch32(Equal, index, Imm32(0))); // now check prev char against newline characters. load16(BaseIndex(input, index, TimesTwo, -2), character); generateCharacterClassInverted(previousIsNewline, CharacterClass::newline()); failures.append(jump()); previousIsNewline.link(this); } else failures.append(branch32(NotEqual, index, Imm32(0)));}void Generator::generateAssertionEOL(JumpList& failures){ if (m_parser.multiline()) { JumpList nextIsNewline; generateLoadCharacter(nextIsNewline); // end of input == success generateCharacterClassInverted(nextIsNewline, CharacterClass::newline()); failures.append(jump()); nextIsNewline.link(this); } else { failures.append(branch32(NotEqual, length, index)); }}void Generator::generateAssertionWordBoundary(JumpList& failures, bool invert){ JumpList wordBoundary; JumpList notWordBoundary; // (1) Check if the previous value was a word char // (1.1) check for begin of input Jump atBegin = branch32(Equal, index, Imm32(0)); // (1.2) load the last char, and chck if is word character load16(BaseIndex(input, index, TimesTwo, -2), character); JumpList previousIsWord; generateCharacterClassInverted(previousIsWord, CharacterClass::wordchar()); // (1.3) if we get here, previous is not a word char atBegin.link(this); // (2) Handle situation where previous was NOT a \w generateLoadCharacter(notWordBoundary); generateCharacterClassInverted(wordBoundary, CharacterClass::wordchar()); // (2.1) If we get here, neither chars are word chars notWordBoundary.append(jump()); // (3) Handle situation where previous was a \w // (3.0) link success in first match to here previousIsWord.link(this); generateLoadCharacter(wordBoundary); generateCharacterClassInverted(notWordBoundary, CharacterClass::wordchar()); // (3.1) If we get here, this is an end of a word, within the input. // (4) Link everything up if (invert) { // handle the fall through case wordBoundary.append(jump()); // looking for non word boundaries, so link boundary fails to here. notWordBoundary.link(this); failures.append(wordBoundary); } else { // looking for word boundaries, so link successes here. wordBoundary.link(this); failures.append(notWordBoundary); }}void Generator::generateBackreference(JumpList& failures, unsigned subpatternId){ push(index); push(repeatCount); // get the start pos of the backref into repeatCount (multipurpose!) load32(Address(output, (2 * subpatternId) * sizeof(int)), repeatCount); Jump skipIncrement = jump(); Label topOfLoop(this); add32(Imm32(1), index); add32(Imm32(1), repeatCount); skipIncrement.link(this); // check if we're at the end of backref (if we are, success!) Jump endOfBackRef = branch32(Equal, Address(output, ((2 * subpatternId) + 1) * sizeof(int)), repeatCount); load16(BaseIndex(input, repeatCount, MacroAssembler::TimesTwo), character); // check if we've run out of input (this would be a can o'fail) Jump endOfInput = branch32(Equal, length, index); branch16(Equal, BaseIndex(input, index, TimesTwo), character, topOfLoop); endOfInput.link(this); // Failure pop(repeatCount); pop(index); failures.append(jump()); // Success endOfBackRef.link(this); pop(repeatCount); pop();}void Generator::terminateAlternative(JumpList& successes, JumpList& failures){ successes.append(jump()); failures.link(this); peek(index);}void Generator::terminateDisjunction(JumpList& successes){ successes.link(this);}} } // namespace JSC::WREC#endif // ENABLE(WREC)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -