Bug 813366 - Fix handling of failing to create jit code in yarr, r=till

This commit is contained in:
Hannes Verschore 2014-04-01 13:30:08 +02:00
Родитель 2cb6cbefea
Коммит d6941b3645
3 изменённых файлов: 64 добавлений и 58 удалений

Просмотреть файл

@ -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{2147483648,}x/.test('1'), false); reportCompare(/x{2147483648,}x/.test('1'), false);
reportCompare(/x{2147483647,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); m_backtrackingState.append(op.m_jumps);
} }
void generateAssertionBOL(size_t opIndex) bool generateAssertionBOL(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -641,13 +641,14 @@ class YarrGenerator : private MacroAssembler {
else else
op.m_jumps.append(branch32(NotEqual, index, Imm32(m_checked))); op.m_jumps.append(branch32(NotEqual, index, Imm32(m_checked)));
} }
return true;
} }
void backtrackAssertionBOL(size_t opIndex) void backtrackAssertionBOL(size_t opIndex)
{ {
backtrackTermDefault(opIndex); backtrackTermDefault(opIndex);
} }
void generateAssertionEOL(size_t opIndex) bool generateAssertionEOL(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -671,6 +672,7 @@ class YarrGenerator : private MacroAssembler {
else else
op.m_jumps.append(jump()); op.m_jumps.append(jump());
} }
return true;
} }
void backtrackAssertionEOL(size_t opIndex) void backtrackAssertionEOL(size_t opIndex)
{ {
@ -692,7 +694,7 @@ class YarrGenerator : private MacroAssembler {
matchCharacterClass(character, nextIsWordChar, m_pattern.wordcharCharacterClass()); matchCharacterClass(character, nextIsWordChar, m_pattern.wordcharCharacterClass());
} }
void generateAssertionWordBoundary(size_t opIndex) bool generateAssertionWordBoundary(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -736,18 +738,19 @@ class YarrGenerator : private MacroAssembler {
nonWordCharThenWordChar.link(this); nonWordCharThenWordChar.link(this);
wordCharThenNonWordChar.link(this); wordCharThenNonWordChar.link(this);
return true;
} }
void backtrackAssertionWordBoundary(size_t opIndex) void backtrackAssertionWordBoundary(size_t opIndex)
{ {
backtrackTermDefault(opIndex); backtrackTermDefault(opIndex);
} }
void generatePatternCharacterOnce(size_t opIndex) bool generatePatternCharacterOnce(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
if (op.m_isDeadCode) if (op.m_isDeadCode)
return; return true;
// m_ops always ends with a OpBodyAlternativeEnd or OpMatchFailed // m_ops always ends with a OpBodyAlternativeEnd or OpMatchFailed
// node, so there must always be at least one more node. // 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)) { if ((ch > 0xff) && (m_charSize == Char8)) {
// Have a 16 bit pattern character and an 8 bit string - short circuit // Have a 16 bit pattern character and an 8 bit string - short circuit
op.m_jumps.append(jump()); op.m_jumps.append(jump());
return; return true;
} }
const RegisterID character = regT0; const RegisterID character = regT0;
@ -807,7 +810,7 @@ class YarrGenerator : private MacroAssembler {
if ((currentCharacter > 0xff) && (m_charSize == Char8)) { if ((currentCharacter > 0xff) && (m_charSize == Char8)) {
// Have a 16 bit pattern character and an 8 bit string - short circuit // Have a 16 bit pattern character and an 8 bit string - short circuit
op.m_jumps.append(jump()); op.m_jumps.append(jump());
return; return true;
} }
// For case-insesitive compares, non-ascii characters that have different // For case-insesitive compares, non-ascii characters that have different
@ -824,7 +827,7 @@ class YarrGenerator : private MacroAssembler {
switch (numberCharacters) { switch (numberCharacters) {
case 1: case 1:
op.m_jumps.append(jumpIfCharNotEquals(ch, startTermPosition - m_checked, character)); op.m_jumps.append(jumpIfCharNotEquals(ch, startTermPosition - m_checked, character));
return; return true;
case 2: { case 2: {
BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar)); BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
load16Unaligned(address, character); load16Unaligned(address, character);
@ -837,7 +840,7 @@ class YarrGenerator : private MacroAssembler {
or32(Imm32(ignoreCaseMask), character); or32(Imm32(ignoreCaseMask), character);
op.m_jumps.append(branch32(NotEqual, character, Imm32((allCharacters & 0xffff) | ignoreCaseMask))); op.m_jumps.append(branch32(NotEqual, character, Imm32((allCharacters & 0xffff) | ignoreCaseMask)));
op.m_jumps.append(jumpIfCharNotEquals(allCharacters >> 16, startTermPosition + 2 - m_checked, character)); op.m_jumps.append(jumpIfCharNotEquals(allCharacters >> 16, startTermPosition + 2 - m_checked, character));
return; return true;
} }
case 4: { case 4: {
BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar)); BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
@ -849,7 +852,7 @@ class YarrGenerator : private MacroAssembler {
switch (numberCharacters) { switch (numberCharacters) {
case 1: case 1:
op.m_jumps.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked, character)); op.m_jumps.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked, character));
return; return true;
case 2: case 2:
BaseIndex address(input, index, TimesTwo, (term->inputPosition - m_checked) * sizeof(UChar)); BaseIndex address(input, index, TimesTwo, (term->inputPosition - m_checked) * sizeof(UChar));
load32WithUnalignedHalfWords(address, character); load32WithUnalignedHalfWords(address, character);
@ -860,14 +863,14 @@ class YarrGenerator : private MacroAssembler {
if (ignoreCaseMask) if (ignoreCaseMask)
or32(Imm32(ignoreCaseMask), character); or32(Imm32(ignoreCaseMask), character);
op.m_jumps.append(branch32(NotEqual, character, Imm32(allCharacters | ignoreCaseMask))); op.m_jumps.append(branch32(NotEqual, character, Imm32(allCharacters | ignoreCaseMask)));
return; return true;
} }
void backtrackPatternCharacterOnce(size_t opIndex) void backtrackPatternCharacterOnce(size_t opIndex)
{ {
backtrackTermDefault(opIndex); backtrackTermDefault(opIndex);
} }
void generatePatternCharacterFixed(size_t opIndex) bool generatePatternCharacterFixed(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -898,13 +901,15 @@ class YarrGenerator : private MacroAssembler {
op.m_jumps.append(branch32(NotEqual, character, Imm32(ch))); op.m_jumps.append(branch32(NotEqual, character, Imm32(ch)));
add32(TrustedImm32(1), countRegister); add32(TrustedImm32(1), countRegister);
branch32(NotEqual, countRegister, index).linkTo(loop, this); branch32(NotEqual, countRegister, index).linkTo(loop, this);
return true;
} }
void backtrackPatternCharacterFixed(size_t opIndex) void backtrackPatternCharacterFixed(size_t opIndex)
{ {
backtrackTermDefault(opIndex); backtrackTermDefault(opIndex);
} }
void generatePatternCharacterGreedy(size_t opIndex) bool generatePatternCharacterGreedy(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -934,6 +939,7 @@ class YarrGenerator : private MacroAssembler {
op.m_reentry = label(); op.m_reentry = label();
storeToFrame(countRegister, term->frameLocation); storeToFrame(countRegister, term->frameLocation);
return true;
} }
void backtrackPatternCharacterGreedy(size_t opIndex) void backtrackPatternCharacterGreedy(size_t opIndex)
{ {
@ -951,7 +957,7 @@ class YarrGenerator : private MacroAssembler {
jump(op.m_reentry); jump(op.m_reentry);
} }
void generatePatternCharacterNonGreedy(size_t opIndex) bool generatePatternCharacterNonGreedy(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -961,6 +967,7 @@ class YarrGenerator : private MacroAssembler {
move(TrustedImm32(0), countRegister); move(TrustedImm32(0), countRegister);
op.m_reentry = label(); op.m_reentry = label();
storeToFrame(countRegister, term->frameLocation); storeToFrame(countRegister, term->frameLocation);
return true;
} }
void backtrackPatternCharacterNonGreedy(size_t opIndex) void backtrackPatternCharacterNonGreedy(size_t opIndex)
{ {
@ -994,7 +1001,7 @@ class YarrGenerator : private MacroAssembler {
m_backtrackingState.fallthrough(); m_backtrackingState.fallthrough();
} }
void generateCharacterClassOnce(size_t opIndex) bool generateCharacterClassOnce(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -1011,13 +1018,14 @@ class YarrGenerator : private MacroAssembler {
op.m_jumps.append(jump()); op.m_jumps.append(jump());
matchDest.link(this); matchDest.link(this);
} }
return true;
} }
void backtrackCharacterClassOnce(size_t opIndex) void backtrackCharacterClassOnce(size_t opIndex)
{ {
backtrackTermDefault(opIndex); backtrackTermDefault(opIndex);
} }
void generateCharacterClassFixed(size_t opIndex) bool generateCharacterClassFixed(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -1045,13 +1053,14 @@ class YarrGenerator : private MacroAssembler {
add32(TrustedImm32(1), countRegister); add32(TrustedImm32(1), countRegister);
branch32(NotEqual, countRegister, index).linkTo(loop, this); branch32(NotEqual, countRegister, index).linkTo(loop, this);
return true;
} }
void backtrackCharacterClassFixed(size_t opIndex) void backtrackCharacterClassFixed(size_t opIndex)
{ {
backtrackTermDefault(opIndex); backtrackTermDefault(opIndex);
} }
void generateCharacterClassGreedy(size_t opIndex) bool generateCharacterClassGreedy(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -1088,6 +1097,7 @@ class YarrGenerator : private MacroAssembler {
op.m_reentry = label(); op.m_reentry = label();
storeToFrame(countRegister, term->frameLocation); storeToFrame(countRegister, term->frameLocation);
return true;
} }
void backtrackCharacterClassGreedy(size_t opIndex) void backtrackCharacterClassGreedy(size_t opIndex)
{ {
@ -1105,7 +1115,7 @@ class YarrGenerator : private MacroAssembler {
jump(op.m_reentry); jump(op.m_reentry);
} }
void generateCharacterClassNonGreedy(size_t opIndex) bool generateCharacterClassNonGreedy(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -1115,6 +1125,7 @@ class YarrGenerator : private MacroAssembler {
move(TrustedImm32(0), countRegister); move(TrustedImm32(0), countRegister);
op.m_reentry = label(); op.m_reentry = label();
storeToFrame(countRegister, term->frameLocation); storeToFrame(countRegister, term->frameLocation);
return true;
} }
void backtrackCharacterClassNonGreedy(size_t opIndex) void backtrackCharacterClassNonGreedy(size_t opIndex)
{ {
@ -1154,7 +1165,7 @@ class YarrGenerator : private MacroAssembler {
m_backtrackingState.fallthrough(); m_backtrackingState.fallthrough();
} }
void generateDotStarEnclosure(size_t opIndex) bool generateDotStarEnclosure(size_t opIndex)
{ {
YarrOp& op = m_ops[opIndex]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -1208,6 +1219,7 @@ class YarrGenerator : private MacroAssembler {
op.m_jumps.append(branch32(NotEqual, matchPos, length)); op.m_jumps.append(branch32(NotEqual, matchPos, length));
move(matchPos, index); move(matchPos, index);
return true;
} }
void backtrackDotStarEnclosure(size_t opIndex) void backtrackDotStarEnclosure(size_t opIndex)
@ -1218,7 +1230,7 @@ class YarrGenerator : private MacroAssembler {
// Code generation/backtracking for simple terms // Code generation/backtracking for simple terms
// (pattern characters, character classes, and assertions). // (pattern characters, character classes, and assertions).
// These methods farm out work to the set of functions above. // 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]; YarrOp& op = m_ops[opIndex];
PatternTerm* term = op.m_term; PatternTerm* term = op.m_term;
@ -1228,16 +1240,14 @@ class YarrGenerator : private MacroAssembler {
switch (term->quantityType) { switch (term->quantityType) {
case QuantifierFixedCount: case QuantifierFixedCount:
if (term->quantityCount == 1) if (term->quantityCount == 1)
generatePatternCharacterOnce(opIndex); return generatePatternCharacterOnce(opIndex);
else else
generatePatternCharacterFixed(opIndex); return generatePatternCharacterFixed(opIndex);
break; break;
case QuantifierGreedy: case QuantifierGreedy:
generatePatternCharacterGreedy(opIndex); return generatePatternCharacterGreedy(opIndex);
break;
case QuantifierNonGreedy: case QuantifierNonGreedy:
generatePatternCharacterNonGreedy(opIndex); return generatePatternCharacterNonGreedy(opIndex);
break;
} }
break; break;
@ -1245,44 +1255,40 @@ class YarrGenerator : private MacroAssembler {
switch (term->quantityType) { switch (term->quantityType) {
case QuantifierFixedCount: case QuantifierFixedCount:
if (term->quantityCount == 1) if (term->quantityCount == 1)
generateCharacterClassOnce(opIndex); return generateCharacterClassOnce(opIndex);
else else
generateCharacterClassFixed(opIndex); return generateCharacterClassFixed(opIndex);
break; break;
case QuantifierGreedy: case QuantifierGreedy:
generateCharacterClassGreedy(opIndex); return generateCharacterClassGreedy(opIndex);
break;
case QuantifierNonGreedy: case QuantifierNonGreedy:
generateCharacterClassNonGreedy(opIndex); return generateCharacterClassNonGreedy(opIndex);
break;
} }
break; break;
case PatternTerm::TypeAssertionBOL: case PatternTerm::TypeAssertionBOL:
generateAssertionBOL(opIndex); return generateAssertionBOL(opIndex);
break;
case PatternTerm::TypeAssertionEOL: case PatternTerm::TypeAssertionEOL:
generateAssertionEOL(opIndex); return generateAssertionEOL(opIndex);
break;
case PatternTerm::TypeAssertionWordBoundary: case PatternTerm::TypeAssertionWordBoundary:
generateAssertionWordBoundary(opIndex); return generateAssertionWordBoundary(opIndex);
break;
case PatternTerm::TypeForwardReference: case PatternTerm::TypeForwardReference:
break; return true;
case PatternTerm::TypeParenthesesSubpattern: case PatternTerm::TypeParenthesesSubpattern:
case PatternTerm::TypeParentheticalAssertion: case PatternTerm::TypeParentheticalAssertion:
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
return false;
case PatternTerm::TypeBackReference: case PatternTerm::TypeBackReference:
m_shouldFallBack = true; return false;
break;
case PatternTerm::TypeDotStarEnclosure: case PatternTerm::TypeDotStarEnclosure:
generateDotStarEnclosure(opIndex); return generateDotStarEnclosure(opIndex);
break;
} }
return false;
} }
void backtrackTerm(size_t opIndex) void backtrackTerm(size_t opIndex)
{ {
@ -1353,7 +1359,7 @@ class YarrGenerator : private MacroAssembler {
} }
} }
void generate() bool generate()
{ {
// Forwards generate the matching code. // Forwards generate the matching code.
ASSERT(m_ops.size()); ASSERT(m_ops.size());
@ -1364,7 +1370,8 @@ class YarrGenerator : private MacroAssembler {
switch (op.m_op) { switch (op.m_op) {
case OpTerm: case OpTerm:
generateTerm(opIndex); if (!generateTerm(opIndex))
return false;
break; break;
// OpBodyAlternativeBegin/Next/End // OpBodyAlternativeBegin/Next/End
@ -1399,7 +1406,9 @@ class YarrGenerator : private MacroAssembler {
// set as appropriate to this alternative. // set as appropriate to this alternative.
op.m_reentry = label(); op.m_reentry = label();
m_checked += alternative->m_minimumSize; if (alternative->m_minimumSize > INT_MAX)
return false;
m_checked = alternative->m_minimumSize;
break; break;
} }
case OpBodyAlternativeNext: case OpBodyAlternativeNext:
@ -1766,6 +1775,8 @@ class YarrGenerator : private MacroAssembler {
++opIndex; ++opIndex;
} while (opIndex < m_ops.size()); } while (opIndex < m_ops.size());
return true;
} }
void backtrack() void backtrack()
@ -2684,7 +2695,10 @@ public:
return; return;
} }
generate(); if (!generate()) {
jitObject.setFallBack(true);
return;
}
backtrack(); backtrack();
// Link & finalize the code. // Link & finalize the code.

Просмотреть файл

@ -612,23 +612,12 @@ private:
unsigned min; unsigned min;
if (!consumeNumber(min)) if (!consumeNumber(min))
break; 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; unsigned max = min;
if (tryConsume(',')) { if (tryConsume(',')) {
if (peekIsDigit()) { if (peekIsDigit()) {
if (!consumeNumber(max)) if (!consumeNumber(max))
break; 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 { } else {
max = quantifyInfinite; max = quantifyInfinite;
} }