skip creating new capture COW SV if possible
authorDavid Mitchell <davem@iabyn.com>
Wed, 19 Jun 2013 11:44:41 +0000 (12:44 +0100)
committerDavid Mitchell <davem@iabyn.com>
Sun, 28 Jul 2013 09:33:36 +0000 (10:33 +0100)
Each time we do a match, we currently (where possible) make a COW copy of
the just-matched string. This involves creating a new SV that shares the
same PVX buffer with the string. In a repeated match like while (/.../g),
that means the each time round we free the old capture SV and create a new
one.

As as optimisation, skip the free/create if the old capture SV is already
a COW clone of the match string.

regexec.c

index 376a4a9..776f8f0 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -2071,10 +2071,19 @@ S_reg_set_capture_string(pTHX_ REGEXP * const rx,
                               "Copy on write: regexp capture, type %d\n",
                               (int) SvTYPE(sv));
             }
-            RX_MATCH_COPY_FREE(rx);
-            prog->saved_copy = sv_setsv_cow(prog->saved_copy, sv);
-            prog->subbeg = (char *)SvPVX_const(prog->saved_copy);
-            assert (SvPOKp(prog->saved_copy));
+            /* skip creating new COW SV if a valid one already exists */
+            if (! (    prog->saved_copy
+                    && SvIsCOW(sv)
+                    && SvPOKp(sv)
+                    && SvIsCOW(prog->saved_copy)
+                    && SvPOKp(prog->saved_copy)
+                    && SvPVX(sv) == SvPVX(prog->saved_copy)))
+            {
+                RX_MATCH_COPY_FREE(rx);
+                prog->saved_copy = sv_setsv_cow(prog->saved_copy, sv);
+                prog->subbeg = (char *)SvPVX_const(prog->saved_copy);
+                assert (SvPOKp(prog->saved_copy));
+            }
             prog->sublen  = strend - strbeg;
             prog->suboffset = 0;
             prog->subcoffset = 0;