Title: [200946] trunk
Revision
200946
Author
[email protected]
Date
2016-05-16 10:40:15 -0700 (Mon, 16 May 2016)

Log Message

RegExp /y flag incorrect handling of mixed-length alternation
https://bugs.webkit.org/show_bug.cgi?id=157723

Reviewed by Filip Pizlo.

Source/_javascript_Core:

Previously for sticky patterns, we were bailing out and exiting when backtracking
alternatives with dissimilar match lengths.  Deleted that code.  Instead, for
sticky patterns we need to process the backtracking except for advancing to the
next input index.

* yarr/YarrJIT.cpp:
(JSC::Yarr::YarrGenerator::backtrack):

LayoutTests:

Added tests for alternatives with shorter to longer lengths.

* js/regexp-sticky-expected.txt:
* js/script-tests/regexp-sticky.js:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (200945 => 200946)


--- trunk/LayoutTests/ChangeLog	2016-05-16 17:35:30 UTC (rev 200945)
+++ trunk/LayoutTests/ChangeLog	2016-05-16 17:40:15 UTC (rev 200946)
@@ -1,3 +1,15 @@
+2016-05-16  Michael Saboff  <[email protected]>
+
+        RegExp /y flag incorrect handling of mixed-length alternation
+        https://bugs.webkit.org/show_bug.cgi?id=157723
+
+        Reviewed by Filip Pizlo.
+
+        Added tests for alternatives with shorter to longer lengths.
+
+        * js/regexp-sticky-expected.txt:
+        * js/script-tests/regexp-sticky.js:
+
 2016-05-16  Brent Fulgham  <[email protected]>
 
         REGRESSION (r192098): Content missing after copy and paste to Notes App on retina displays

Modified: trunk/LayoutTests/js/regexp-sticky-expected.txt (200945 => 200946)


--- trunk/LayoutTests/js/regexp-sticky-expected.txt	2016-05-16 17:35:30 UTC (rev 200945)
+++ trunk/LayoutTests/js/regexp-sticky-expected.txt	2016-05-16 17:40:15 UTC (rev 200946)
@@ -6,7 +6,9 @@
 PASS Repeating Pattern
 PASS Test lastIndex resets
 PASS Ignore Case
-PASS Alternates
+PASS Alternates, differing lengths long to short
+PASS Alternates, differing lengths long to short with mutliple matches 
+PASS Alternates, differing lengths, short to long
 PASS BOL Anchored, starting at 0
 PASS BOL Anchored, starting at 1
 PASS EOL Anchored, not at EOL

Modified: trunk/LayoutTests/js/script-tests/regexp-sticky.js (200945 => 200946)


--- trunk/LayoutTests/js/script-tests/regexp-sticky.js	2016-05-16 17:35:30 UTC (rev 200945)
+++ trunk/LayoutTests/js/script-tests/regexp-sticky.js	2016-05-16 17:40:15 UTC (rev 200946)
@@ -72,7 +72,9 @@
 testStickyExec("Repeating Pattern", new RegExp("abc", "y"), "abcabcabc", 0, ["abc", "abc", "abc", null]);
 testStickyExec("Test lastIndex resets", /\d/y, "12345", 0, ["1", "2", "3", "4", "5", null, "1", "2", "3", "4", "5", null]);
 testStickyExec("Ignore Case", new RegExp("test", "iy"), "TESTtestTest", 0, ["TEST", "test", "Test", null]);
-testStickyExec("Alternates", new RegExp("Dog |Cat |Mouse ", "y"), "Mouse Dog Cat ", 0, ["Mouse ", "Dog ", "Cat ", null]);
+testStickyExec("Alternates, differing lengths long to short", new RegExp("bb|a", "y"), "a", 0, ["a", null]);
+testStickyExec("Alternates, differing lengths long to short with mutliple matches ", new RegExp("abc|ab|a", "y"), "aababcaabcab", 0, ["a", "ab", "abc", "a", "abc", "ab", null]);
+testStickyExec("Alternates, differing lengths, short to long", new RegExp("Dog |Cat |Mouse ", "y"), "Mouse Dog Cat ", 0, ["Mouse ", "Dog ", "Cat ", null]);
 testStickyExec("BOL Anchored, starting at 0", /^X/y, "XXX", 0, ["X", null]);
 testStickyExec("BOL Anchored, starting at 1", /^X/y, "XXX", 1, [null, "X", null]);
 testStickyExec("EOL Anchored, not at EOL", /#$/y, "##", 0, [null]);

Modified: trunk/Source/_javascript_Core/ChangeLog (200945 => 200946)


--- trunk/Source/_javascript_Core/ChangeLog	2016-05-16 17:35:30 UTC (rev 200945)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-05-16 17:40:15 UTC (rev 200946)
@@ -1,3 +1,18 @@
+2016-05-15  Michael Saboff  <[email protected]>
+
+        RegExp /y flag incorrect handling of mixed-length alternation
+        https://bugs.webkit.org/show_bug.cgi?id=157723
+
+        Reviewed by Filip Pizlo.
+
+        Previously for sticky patterns, we were bailing out and exiting when backtracking
+        alternatives with dissimilar match lengths.  Deleted that code.  Instead, for
+        sticky patterns we need to process the backtracking except for advancing to the
+        next input index.
+
+        * yarr/YarrJIT.cpp:
+        (JSC::Yarr::YarrGenerator::backtrack):
+
 2016-05-15  Filip Pizlo  <[email protected]>
 
         DFG::Plan shouldn't read from its VM once it's been cancelled

Modified: trunk/Source/_javascript_Core/yarr/YarrJIT.cpp (200945 => 200946)


--- trunk/Source/_javascript_Core/yarr/YarrJIT.cpp	2016-05-16 17:35:30 UTC (rev 200945)
+++ trunk/Source/_javascript_Core/yarr/YarrJIT.cpp	2016-05-16 17:40:15 UTC (rev 200946)
@@ -1888,20 +1888,6 @@
                     }
                 }
 
-                if (m_pattern.sticky()) {
-                    // We have failed matching from the initial index and we're a sticky _expression_.
-                    // We are done matching. Link failures for any reason to here.
-                    YarrOp* tempOp = beginOp;
-                    do {
-                        tempOp->m_jumps.link(this);
-                        tempOp = &m_ops[tempOp->m_nextOp];
-                    } while (tempOp->m_op != OpBodyAlternativeEnd);
-
-                    removeCallFrame();
-                    generateFailReturn();
-                    break;
-                }
-
                 // We can reach this point in the code in two ways:
                 //  - Fallthrough from the code above (a repeating alternative backtracked out of its
                 //    last alternative, and did not have sufficent input to run the first).
@@ -1965,52 +1951,53 @@
                     needsToUpdateMatchStart = false;
                 }
 
-                // Check whether there is sufficient input to loop. Increment the input position by
-                // one, and check. Also add in the minimum disjunction size before checking - there
-                // is no point in looping if we're just going to fail all the input checks around
-                // the next iteration.
-                ASSERT(alternative->m_minimumSize >= m_pattern.m_body->m_minimumSize);
-                if (alternative->m_minimumSize == m_pattern.m_body->m_minimumSize) {
-                    // If the last alternative had the same minimum size as the disjunction,
-                    // just simply increment input pos by 1, no adjustment based on minimum size.
-                    add32(TrustedImm32(1), index);
-                } else {
-                    // If the minumum for the last alternative was one greater than than that
-                    // for the disjunction, we're already progressed by 1, nothing to do!
-                    unsigned delta = (alternative->m_minimumSize - m_pattern.m_body->m_minimumSize) - 1;
-                    if (delta)
-                        sub32(Imm32(delta), index);
-                }
-                Jump matchFailed = jumpIfNoAvailableInput();
+                if (!m_pattern.sticky()) {
+                    // Check whether there is sufficient input to loop. Increment the input position by
+                    // one, and check. Also add in the minimum disjunction size before checking - there
+                    // is no point in looping if we're just going to fail all the input checks around
+                    // the next iteration.
+                    ASSERT(alternative->m_minimumSize >= m_pattern.m_body->m_minimumSize);
+                    if (alternative->m_minimumSize == m_pattern.m_body->m_minimumSize) {
+                        // If the last alternative had the same minimum size as the disjunction,
+                        // just simply increment input pos by 1, no adjustment based on minimum size.
+                        add32(TrustedImm32(1), index);
+                    } else {
+                        // If the minumum for the last alternative was one greater than than that
+                        // for the disjunction, we're already progressed by 1, nothing to do!
+                        unsigned delta = (alternative->m_minimumSize - m_pattern.m_body->m_minimumSize) - 1;
+                        if (delta)
+                            sub32(Imm32(delta), index);
+                    }
+                    Jump matchFailed = jumpIfNoAvailableInput();
 
-                if (needsToUpdateMatchStart) {
-                    if (!m_pattern.m_body->m_minimumSize)
-                        setMatchStart(index);
+                    if (needsToUpdateMatchStart) {
+                        if (!m_pattern.m_body->m_minimumSize)
+                            setMatchStart(index);
+                        else {
+                            move(index, regT0);
+                            sub32(Imm32(m_pattern.m_body->m_minimumSize), regT0);
+                            setMatchStart(regT0);
+                        }
+                    }
+
+                    // Calculate how much more input the first alternative requires than the minimum
+                    // for the body as a whole. If no more is needed then we dont need an additional
+                    // input check here - jump straight back up to the start of the first alternative.
+                    if (beginOp->m_alternative->m_minimumSize == m_pattern.m_body->m_minimumSize)
+                        jump(beginOp->m_reentry);
                     else {
-                        move(index, regT0);
-                        sub32(Imm32(m_pattern.m_body->m_minimumSize), regT0);
-                        setMatchStart(regT0);
+                        if (beginOp->m_alternative->m_minimumSize > m_pattern.m_body->m_minimumSize)
+                            add32(Imm32(beginOp->m_alternative->m_minimumSize - m_pattern.m_body->m_minimumSize), index);
+                        else
+                            sub32(Imm32(m_pattern.m_body->m_minimumSize - beginOp->m_alternative->m_minimumSize), index);
+                        checkInput().linkTo(beginOp->m_reentry, this);
+                        jump(firstInputCheckFailed);
                     }
-                }
 
-                // Calculate how much more input the first alternative requires than the minimum
-                // for the body as a whole. If no more is needed then we dont need an additional
-                // input check here - jump straight back up to the start of the first alternative.
-                if (beginOp->m_alternative->m_minimumSize == m_pattern.m_body->m_minimumSize)
-                    jump(beginOp->m_reentry);
-                else {
-                    if (beginOp->m_alternative->m_minimumSize > m_pattern.m_body->m_minimumSize)
-                        add32(Imm32(beginOp->m_alternative->m_minimumSize - m_pattern.m_body->m_minimumSize), index);
-                    else
-                        sub32(Imm32(m_pattern.m_body->m_minimumSize - beginOp->m_alternative->m_minimumSize), index);
-                    checkInput().linkTo(beginOp->m_reentry, this);
-                    jump(firstInputCheckFailed);
+                    // We jump to here if we iterate to the point that there is insufficient input to
+                    // run any matches, and need to return a failure state from JIT code.
+                    matchFailed.link(this);
                 }
-
-                // We jump to here if we iterate to the point that there is insufficient input to
-                // run any matches, and need to return a failure state from JIT code.
-                matchFailed.link(this);
-
                 removeCallFrame();
                 generateFailReturn();
                 break;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to