[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 15:28:10 +0000 (08:28 -0700)
commit9cefd268f0a1c07e6746eef1c037efc657387f21
tree52d603e17c7e7bc137c4c910e26ba300f4641426
parent2e9e14ddec173be05687c2df560a22b6721eae37
[perl #118747] Allow in-place s///g when !!PL_sawampersand

This is the more correct version of 1555b325 which was reverted
by 6200d5a0e.

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.

In-place substitution stringifies the rhs at the outset, just after
the first regexp match, but before any substitution.  Then it uses
that string buffer, expecting it not to change.

That clearly cannot work with s/a/$&/g; it will also cause erratic
behaviour in the case of regexp code blocks (which will see the
string being modified, which doesn not happen with unoptimised subst).
That’s why the in-place optimisation has to be skipped when the
REXEC_COPY_STR flag is set.

But we can tweak that logic:

• As long as the rhs is not a magical var, its contents are not going
  to change from one iteration to the next.
• If there are no code blocks, nothing will see the string during the
  substitution.

So this commit adds logic to check those things, enabling this opti-
misation where possible.

Skipping this optimisation for the pre-match copy was originally added
in commit 5d5aaa5e7.
pp_hot.c