Bug 679986: Deoptimize unnecessary regexps. (r=cdleary, a=dmandelin)
authorDave Mandelin <dmandelin@mozilla.com>
Mon, 07 Nov 2011 11:42:02 -0800
changeset 79162 a78bbe2376beffc838457ab5c3dd731d76597669
parent 79161 c845d62ee43f88dd9574de1c9fce367e14bdef11
child 79163 15b028ac0dcfb3edf66b1b6c888661f587fb5658
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscdleary, dmandelin
bugs679986
milestone9.0a2
Bug 679986: Deoptimize unnecessary regexps. (r=cdleary, a=dmandelin)
js/src/jit-test/tests/basic/bug679986-1.js
js/src/jit-test/tests/basic/bug679986-2.js
js/src/yarr/YarrJIT.cpp
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;
         }