This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #118747] Allow in-place s///g when !!PL_sawampersand
authorFather Chrysostomos <sprout@cpan.org>
Thu, 22 Aug 2013 04:59:20 +0000 (21:59 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 22 Aug 2013 05:15:37 +0000 (22:15 -0700)
In pp_subst, there is an initial pattern match against the target
string, followed by logic to determine which of several code paths
will handle the rest of the substitution, depending on which shortcuts
can be taken.

There is one path specifically for doing a global sort (/g) and modi-
fying the target in place.  This code was skipped if the target was a
copy-on-write scalar or if the pre-match copy was enabled.  The pre-
match copy is always enabled now, so this code is unreachable.

There does not appear to be any reason why this path must be skipped
in the presence of the pre-match copy.  The string gets copied by the
initial regexp match and $& and friends point there afterwards.

This skip was added in commit 5d5aaa5e7 (a jumbo patch, so good luck
figuring it out).  This commit removes the skip, and all tests pass.

This, of course, only affects those cases where copy-on-write does
not kick in; for instance, when the string’s length is one less than
its buffer:

$  ./perl -Ilib -e 'use Devel::Peek; $x = " "; $x .= " "x22; Dump $x; $x =~ s/ /b/g; Dump $x'
SV = PV(0x7ffb0b807098) at 0x7ffb0b82eed8
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x7ffb0b4066b8 "                       "\0
  CUR = 23
  LEN = 24
SV = PV(0x7ffb0b807098) at 0x7ffb0b82eed8
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x7ffb0b4066b8 "bbbbbbbbbbbbbbbbbbbbbbb"\0
  CUR = 23
  LEN = 24

pp_hot.c

index 571cd63..82b2508 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2159,7 +2159,6 @@ PP(pp_subst)
        && !is_cow
 #endif
         && (I32)clen <= RX_MINLENRET(rx)
-        && (once || !(r_flags & REXEC_COPY_STR))
         && !(RX_EXTFLAGS(rx) & RXf_NO_INPLACE_SUBST)
        && (!doutf8 || SvUTF8(TARG))
        && !(rpm->op_pmflags & PMf_NONDESTRUCT))