mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 813366 - Fix handling of failing to create jit code in yarr, r=till
This commit is contained in:
parent
2645b81c02
commit
0c311ae47a
@ -15,3 +15,6 @@ reportCompare(["B", "B"].toSource(), toSource(/([A-Z])/.exec("fooBar")));
|
||||
reportCompare(/x{2147483648}x/.test('1'), false);
|
||||
reportCompare(/x{2147483648,}x/.test('1'), false);
|
||||
reportCompare(/x{2147483647,2147483648}x/.test('1'), false);
|
||||
// Same for these. See bug 813366
|
||||
reportCompare("".match(/.{2147483647}11/), null);
|
||||
reportCompare("".match(/(?:(?=g)).{2147483648,}/ + ""), null);
|
||||
|
@ -617,7 +617,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
m_backtrackingState.append(op.m_jumps);
|
||||
}
|
||||
|
||||
void generateAssertionBOL(size_t opIndex)
|
||||
bool generateAssertionBOL(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -641,13 +641,14 @@ class YarrGenerator : private MacroAssembler {
|
||||
else
|
||||
op.m_jumps.append(branch32(NotEqual, index, Imm32(m_checked)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void backtrackAssertionBOL(size_t opIndex)
|
||||
{
|
||||
backtrackTermDefault(opIndex);
|
||||
}
|
||||
|
||||
void generateAssertionEOL(size_t opIndex)
|
||||
bool generateAssertionEOL(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -671,6 +672,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
else
|
||||
op.m_jumps.append(jump());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void backtrackAssertionEOL(size_t opIndex)
|
||||
{
|
||||
@ -692,7 +694,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
matchCharacterClass(character, nextIsWordChar, m_pattern.wordcharCharacterClass());
|
||||
}
|
||||
|
||||
void generateAssertionWordBoundary(size_t opIndex)
|
||||
bool generateAssertionWordBoundary(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -736,18 +738,19 @@ class YarrGenerator : private MacroAssembler {
|
||||
|
||||
nonWordCharThenWordChar.link(this);
|
||||
wordCharThenNonWordChar.link(this);
|
||||
return true;
|
||||
}
|
||||
void backtrackAssertionWordBoundary(size_t opIndex)
|
||||
{
|
||||
backtrackTermDefault(opIndex);
|
||||
}
|
||||
|
||||
void generatePatternCharacterOnce(size_t opIndex)
|
||||
bool generatePatternCharacterOnce(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
|
||||
if (op.m_isDeadCode)
|
||||
return;
|
||||
return true;
|
||||
|
||||
// m_ops always ends with a OpBodyAlternativeEnd or OpMatchFailed
|
||||
// node, so there must always be at least one more node.
|
||||
@ -760,7 +763,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
if ((ch > 0xff) && (m_charSize == Char8)) {
|
||||
// Have a 16 bit pattern character and an 8 bit string - short circuit
|
||||
op.m_jumps.append(jump());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const RegisterID character = regT0;
|
||||
@ -807,7 +810,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
if ((currentCharacter > 0xff) && (m_charSize == Char8)) {
|
||||
// Have a 16 bit pattern character and an 8 bit string - short circuit
|
||||
op.m_jumps.append(jump());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// For case-insesitive compares, non-ascii characters that have different
|
||||
@ -824,7 +827,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
switch (numberCharacters) {
|
||||
case 1:
|
||||
op.m_jumps.append(jumpIfCharNotEquals(ch, startTermPosition - m_checked, character));
|
||||
return;
|
||||
return true;
|
||||
case 2: {
|
||||
BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
|
||||
load16Unaligned(address, character);
|
||||
@ -837,7 +840,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
or32(Imm32(ignoreCaseMask), character);
|
||||
op.m_jumps.append(branch32(NotEqual, character, Imm32((allCharacters & 0xffff) | ignoreCaseMask)));
|
||||
op.m_jumps.append(jumpIfCharNotEquals(allCharacters >> 16, startTermPosition + 2 - m_checked, character));
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
case 4: {
|
||||
BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
|
||||
@ -849,7 +852,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
switch (numberCharacters) {
|
||||
case 1:
|
||||
op.m_jumps.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked, character));
|
||||
return;
|
||||
return true;
|
||||
case 2:
|
||||
BaseIndex address(input, index, TimesTwo, (term->inputPosition - m_checked) * sizeof(UChar));
|
||||
load32WithUnalignedHalfWords(address, character);
|
||||
@ -860,14 +863,14 @@ class YarrGenerator : private MacroAssembler {
|
||||
if (ignoreCaseMask)
|
||||
or32(Imm32(ignoreCaseMask), character);
|
||||
op.m_jumps.append(branch32(NotEqual, character, Imm32(allCharacters | ignoreCaseMask)));
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
void backtrackPatternCharacterOnce(size_t opIndex)
|
||||
{
|
||||
backtrackTermDefault(opIndex);
|
||||
}
|
||||
|
||||
void generatePatternCharacterFixed(size_t opIndex)
|
||||
bool generatePatternCharacterFixed(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -898,13 +901,15 @@ class YarrGenerator : private MacroAssembler {
|
||||
op.m_jumps.append(branch32(NotEqual, character, Imm32(ch)));
|
||||
add32(TrustedImm32(1), countRegister);
|
||||
branch32(NotEqual, countRegister, index).linkTo(loop, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
void backtrackPatternCharacterFixed(size_t opIndex)
|
||||
{
|
||||
backtrackTermDefault(opIndex);
|
||||
}
|
||||
|
||||
void generatePatternCharacterGreedy(size_t opIndex)
|
||||
bool generatePatternCharacterGreedy(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -934,6 +939,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
op.m_reentry = label();
|
||||
|
||||
storeToFrame(countRegister, term->frameLocation);
|
||||
return true;
|
||||
}
|
||||
void backtrackPatternCharacterGreedy(size_t opIndex)
|
||||
{
|
||||
@ -951,7 +957,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
jump(op.m_reentry);
|
||||
}
|
||||
|
||||
void generatePatternCharacterNonGreedy(size_t opIndex)
|
||||
bool generatePatternCharacterNonGreedy(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -961,6 +967,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
move(TrustedImm32(0), countRegister);
|
||||
op.m_reentry = label();
|
||||
storeToFrame(countRegister, term->frameLocation);
|
||||
return true;
|
||||
}
|
||||
void backtrackPatternCharacterNonGreedy(size_t opIndex)
|
||||
{
|
||||
@ -994,7 +1001,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
m_backtrackingState.fallthrough();
|
||||
}
|
||||
|
||||
void generateCharacterClassOnce(size_t opIndex)
|
||||
bool generateCharacterClassOnce(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -1011,13 +1018,14 @@ class YarrGenerator : private MacroAssembler {
|
||||
op.m_jumps.append(jump());
|
||||
matchDest.link(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void backtrackCharacterClassOnce(size_t opIndex)
|
||||
{
|
||||
backtrackTermDefault(opIndex);
|
||||
}
|
||||
|
||||
void generateCharacterClassFixed(size_t opIndex)
|
||||
bool generateCharacterClassFixed(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -1045,13 +1053,14 @@ class YarrGenerator : private MacroAssembler {
|
||||
|
||||
add32(TrustedImm32(1), countRegister);
|
||||
branch32(NotEqual, countRegister, index).linkTo(loop, this);
|
||||
return true;
|
||||
}
|
||||
void backtrackCharacterClassFixed(size_t opIndex)
|
||||
{
|
||||
backtrackTermDefault(opIndex);
|
||||
}
|
||||
|
||||
void generateCharacterClassGreedy(size_t opIndex)
|
||||
bool generateCharacterClassGreedy(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -1088,6 +1097,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
op.m_reentry = label();
|
||||
|
||||
storeToFrame(countRegister, term->frameLocation);
|
||||
return true;
|
||||
}
|
||||
void backtrackCharacterClassGreedy(size_t opIndex)
|
||||
{
|
||||
@ -1105,7 +1115,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
jump(op.m_reentry);
|
||||
}
|
||||
|
||||
void generateCharacterClassNonGreedy(size_t opIndex)
|
||||
bool generateCharacterClassNonGreedy(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -1115,6 +1125,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
move(TrustedImm32(0), countRegister);
|
||||
op.m_reentry = label();
|
||||
storeToFrame(countRegister, term->frameLocation);
|
||||
return true;
|
||||
}
|
||||
void backtrackCharacterClassNonGreedy(size_t opIndex)
|
||||
{
|
||||
@ -1154,7 +1165,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
m_backtrackingState.fallthrough();
|
||||
}
|
||||
|
||||
void generateDotStarEnclosure(size_t opIndex)
|
||||
bool generateDotStarEnclosure(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -1208,6 +1219,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
op.m_jumps.append(branch32(NotEqual, matchPos, length));
|
||||
|
||||
move(matchPos, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
void backtrackDotStarEnclosure(size_t opIndex)
|
||||
@ -1218,7 +1230,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
// Code generation/backtracking for simple terms
|
||||
// (pattern characters, character classes, and assertions).
|
||||
// These methods farm out work to the set of functions above.
|
||||
void generateTerm(size_t opIndex)
|
||||
bool generateTerm(size_t opIndex)
|
||||
{
|
||||
YarrOp& op = m_ops[opIndex];
|
||||
PatternTerm* term = op.m_term;
|
||||
@ -1228,16 +1240,14 @@ class YarrGenerator : private MacroAssembler {
|
||||
switch (term->quantityType) {
|
||||
case QuantifierFixedCount:
|
||||
if (term->quantityCount == 1)
|
||||
generatePatternCharacterOnce(opIndex);
|
||||
return generatePatternCharacterOnce(opIndex);
|
||||
else
|
||||
generatePatternCharacterFixed(opIndex);
|
||||
return generatePatternCharacterFixed(opIndex);
|
||||
break;
|
||||
case QuantifierGreedy:
|
||||
generatePatternCharacterGreedy(opIndex);
|
||||
break;
|
||||
return generatePatternCharacterGreedy(opIndex);
|
||||
case QuantifierNonGreedy:
|
||||
generatePatternCharacterNonGreedy(opIndex);
|
||||
break;
|
||||
return generatePatternCharacterNonGreedy(opIndex);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1245,44 +1255,40 @@ class YarrGenerator : private MacroAssembler {
|
||||
switch (term->quantityType) {
|
||||
case QuantifierFixedCount:
|
||||
if (term->quantityCount == 1)
|
||||
generateCharacterClassOnce(opIndex);
|
||||
return generateCharacterClassOnce(opIndex);
|
||||
else
|
||||
generateCharacterClassFixed(opIndex);
|
||||
return generateCharacterClassFixed(opIndex);
|
||||
break;
|
||||
case QuantifierGreedy:
|
||||
generateCharacterClassGreedy(opIndex);
|
||||
break;
|
||||
return generateCharacterClassGreedy(opIndex);
|
||||
case QuantifierNonGreedy:
|
||||
generateCharacterClassNonGreedy(opIndex);
|
||||
break;
|
||||
return generateCharacterClassNonGreedy(opIndex);
|
||||
}
|
||||
break;
|
||||
|
||||
case PatternTerm::TypeAssertionBOL:
|
||||
generateAssertionBOL(opIndex);
|
||||
break;
|
||||
return generateAssertionBOL(opIndex);
|
||||
|
||||
case PatternTerm::TypeAssertionEOL:
|
||||
generateAssertionEOL(opIndex);
|
||||
break;
|
||||
return generateAssertionEOL(opIndex);
|
||||
|
||||
case PatternTerm::TypeAssertionWordBoundary:
|
||||
generateAssertionWordBoundary(opIndex);
|
||||
break;
|
||||
return generateAssertionWordBoundary(opIndex);
|
||||
|
||||
case PatternTerm::TypeForwardReference:
|
||||
break;
|
||||
return true;
|
||||
|
||||
case PatternTerm::TypeParenthesesSubpattern:
|
||||
case PatternTerm::TypeParentheticalAssertion:
|
||||
ASSERT_NOT_REACHED();
|
||||
return false;
|
||||
case PatternTerm::TypeBackReference:
|
||||
m_shouldFallBack = true;
|
||||
break;
|
||||
return false;
|
||||
case PatternTerm::TypeDotStarEnclosure:
|
||||
generateDotStarEnclosure(opIndex);
|
||||
break;
|
||||
return generateDotStarEnclosure(opIndex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
void backtrackTerm(size_t opIndex)
|
||||
{
|
||||
@ -1353,7 +1359,7 @@ class YarrGenerator : private MacroAssembler {
|
||||
}
|
||||
}
|
||||
|
||||
void generate()
|
||||
bool generate()
|
||||
{
|
||||
// Forwards generate the matching code.
|
||||
ASSERT(m_ops.size());
|
||||
@ -1364,7 +1370,8 @@ class YarrGenerator : private MacroAssembler {
|
||||
switch (op.m_op) {
|
||||
|
||||
case OpTerm:
|
||||
generateTerm(opIndex);
|
||||
if (!generateTerm(opIndex))
|
||||
return false;
|
||||
break;
|
||||
|
||||
// OpBodyAlternativeBegin/Next/End
|
||||
@ -1399,7 +1406,9 @@ class YarrGenerator : private MacroAssembler {
|
||||
// set as appropriate to this alternative.
|
||||
op.m_reentry = label();
|
||||
|
||||
m_checked += alternative->m_minimumSize;
|
||||
if (alternative->m_minimumSize > INT_MAX)
|
||||
return false;
|
||||
m_checked = alternative->m_minimumSize;
|
||||
break;
|
||||
}
|
||||
case OpBodyAlternativeNext:
|
||||
@ -1766,6 +1775,8 @@ class YarrGenerator : private MacroAssembler {
|
||||
|
||||
++opIndex;
|
||||
} while (opIndex < m_ops.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void backtrack()
|
||||
@ -2684,7 +2695,10 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
generate();
|
||||
if (!generate()) {
|
||||
jitObject.setFallBack(true);
|
||||
return;
|
||||
}
|
||||
backtrack();
|
||||
|
||||
// Link & finalize the code.
|
||||
|
@ -612,23 +612,12 @@ private:
|
||||
unsigned min;
|
||||
if (!consumeNumber(min))
|
||||
break;
|
||||
// Clamping to INT_MAX is technically a spec deviation. In practice, it's
|
||||
// undetectable, because we can't even allocate strings large enough for
|
||||
// quantifiers this large to ever create different results than smaller ones.
|
||||
if (min > INT_MAX)
|
||||
min = INT_MAX;
|
||||
|
||||
unsigned max = min;
|
||||
if (tryConsume(',')) {
|
||||
if (peekIsDigit()) {
|
||||
if (!consumeNumber(max))
|
||||
break;
|
||||
// Clamping to INT_MAX is technically a spec deviation. In practice,
|
||||
// it's undetectable, because we can't even allocate strings large
|
||||
// enough for quantifiers this large to ever create different results
|
||||
// than smaller ones.
|
||||
if (max > INT_MAX)
|
||||
max = INT_MAX;
|
||||
} else {
|
||||
max = quantifyInfinite;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user