Bug 679986: Deoptimize unnecessary regexps. (r=cdleary, a=dmandelin)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug679986-1.js
@@ -0,0 +1,2 @@
+// don't assert
+var m = "aaaa".match(/(?:|a)*/);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug679986-2.js
@@ -0,0 +1,2 @@
+// don't hang
+var m = "aaaa".match(/(?:a?)*/);
--- a/js/src/yarr/YarrJIT.cpp
+++ b/js/src/yarr/YarrJIT.cpp
@@ -2078,16 +2078,32 @@ class YarrGenerator : private MacroAssem
// If there is more than one alternative we cannot use the 'simple' nodes.
if (term->parentheses.disjunction->m_alternatives.size() != 1) {
alternativeBeginOpCode = OpNestedAlternativeBegin;
alternativeNextOpCode = OpNestedAlternativeNext;
alternativeEndOpCode = OpNestedAlternativeEnd;
}
} else if (term->parentheses.isTerminal) {
+ // Terminal groups are optimized on the assumption that matching will never
+ // backtrack into the terminal group. But this is false if there is more
+ // than one alternative and one of the alternatives can match empty. In that
+ // case, the empty match is counted as a failure, so we would need to backtrack.
+ // The backtracking code doesn't handle this case correctly, so we fall back
+ // to the interpreter.
+ Vector<PatternAlternative*>& alternatives = term->parentheses.disjunction->m_alternatives;
+ if (alternatives.size() != 1) {
+ for (unsigned i = 0; i < alternatives.size(); ++i) {
+ if (alternatives[i]->m_minimumSize == 0) {
+ m_shouldFallBack = true;
+ return;
+ }
+ }
+ }
+
// Select the 'Terminal' nodes.
parenthesesBeginOpCode = OpParenthesesSubpatternTerminalBegin;
parenthesesEndOpCode = OpParenthesesSubpatternTerminalEnd;
} else {
// This subpattern is not supported by the JIT.
m_shouldFallBack = true;
return;
}