re_intuit_start(): don't decrease other_last
authorDavid Mitchell <davem@iabyn.com>
Fri, 7 Feb 2014 16:43:19 +0000 (16:43 +0000)
committerDavid Mitchell <davem@iabyn.com>
Sat, 8 Feb 2014 14:04:55 +0000 (14:04 +0000)
The /^../m failure code did an unconditional other_last = rx_origin;
if other_last was already high, it could get shrunk and we'd end
up running fbm over the same bit of string repeatedly.

The following code

    $s = "-ab\n" x 500_000;
    $s .= 'abx';
    $s =~ /^ab.*x/m;

(which went quadratic on length) reduces from minutes to millisecs with
this commit.  This is because we'd keep going back to near the beginning
of the string and searching for 'x' again.

regexec.c
t/re/pat.t

index 181afe7..ed6f9fc 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -1121,7 +1121,8 @@ Perl_re_intuit_start(pTHX_
             DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log,
                 "  Found /%s^%s/m, restarting lookup for check-string at offset %ld...\n",
                 PL_colors[0], PL_colors[1], (long)(t + 1 - strpos)));
-            other_last = rx_origin;
+            if (other_last < rx_origin)
+                other_last = rx_origin;
             goto restart;
         }
 
index 486238c..79c7e6a 100644 (file)
@@ -20,7 +20,7 @@ BEGIN {
     require './test.pl';
 }
 
-plan tests => 716;  # Update this when adding/deleting tests.
+plan tests => 717;  # Update this when adding/deleting tests.
 
 run_tests() unless caller;
 
@@ -1534,6 +1534,10 @@ EOP
         utf8::upgrade($s);
         ok($s =~ /\da\d{0,30000}bc/, "\\d{30000}");
 
+        $s = "-ab\n" x 250_000;
+        $s .= "abx";
+        ok($s =~ /^ab.*x/m, "distant float with /m");
+
     }
 
     # These are based on looking at the code in regcomp.c