summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2011-06-17 16:40:30 +0200
committerNicholas Clark <nick@ccl4.org>2011-06-23 10:22:13 +0200
commit8ca8a454f60a417f5040d6e3e47673333702f58d (patch)
treeeff5d0d46490c02817e88b95e66f0beaf0a9b2a1 /pp_ctl.c
parent7c4202907c499a6fd1a41da6fdf1d414ecadeb37 (diff)
downloadperl-8ca8a454f60a417f5040d6e3e47673333702f58d.tar.gz
For s///r, avoid copying the source early only to edit it in place.
Instead, take advantage of the "can't edit in place" code path of pp_subst which writes to a new scalar, and that pp_substcont always leaves the original intact, writing to a new scalar.
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c47
1 files changed, 27 insertions, 20 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 9f7c52a1bf..4324253692 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -305,7 +305,7 @@ PP(pp_substcont)
? (REXEC_IGNOREPOS|REXEC_NOT_FIRST)
: (REXEC_COPY_STR|REXEC_IGNOREPOS|REXEC_NOT_FIRST))))
{
- SV * const targ = cx->sb_targ;
+ SV *targ = cx->sb_targ;
assert(cx->sb_strend >= s);
if(cx->sb_strend > s) {
@@ -317,27 +317,32 @@ PP(pp_substcont)
if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */
cx->sb_rxtainted |= SUBST_TAINT_PAT;
+ if (pm->op_pmflags & PMf_NONDESTRUCT) {
+ PUSHs(dstr);
+ /* From here on down we're using the copy, and leaving the
+ original untouched. */
+ targ = dstr;
+ }
+ else {
#ifdef PERL_OLD_COPY_ON_WRITE
- if (SvIsCOW(targ)) {
- sv_force_normal_flags(targ, SV_COW_DROP_PV);
- } else
+ if (SvIsCOW(targ)) {
+ sv_force_normal_flags(targ, SV_COW_DROP_PV);
+ } else
#endif
- {
- SvPV_free(targ);
- }
- SvPV_set(targ, SvPVX(dstr));
- SvCUR_set(targ, SvCUR(dstr));
- SvLEN_set(targ, SvLEN(dstr));
- if (DO_UTF8(dstr))
- SvUTF8_on(targ);
- SvPV_set(dstr, NULL);
-
- if (pm->op_pmflags & PMf_NONDESTRUCT)
- PUSHs(targ);
- else
+ {
+ SvPV_free(targ);
+ }
+ SvPV_set(targ, SvPVX(dstr));
+ SvCUR_set(targ, SvCUR(dstr));
+ SvLEN_set(targ, SvLEN(dstr));
+ if (DO_UTF8(dstr))
+ SvUTF8_on(targ);
+ SvPV_set(dstr, NULL);
+
mPUSHi(saviters - 1);
- (void)SvPOK_only_UTF8(targ);
+ (void)SvPOK_only_UTF8(targ);
+ }
/* update the taint state of various various variables in
* preparation for final exit.
@@ -384,7 +389,8 @@ PP(pp_substcont)
}
cx->sb_s = RX_OFFS(rx)[0].end + orig;
{ /* Update the pos() information. */
- SV * const sv = cx->sb_targ;
+ SV * const sv
+ = (pm->op_pmflags & PMf_NONDESTRUCT) ? cx->sb_dstr : cx->sb_targ;
MAGIC *mg;
SvUPGRADE(sv, SVt_PVMG);
if (!(mg = mg_find(sv, PERL_MAGIC_regex_global))) {
@@ -414,7 +420,8 @@ PP(pp_substcont)
if (cx->sb_iters > 1 && (cx->sb_rxtainted &
(SUBST_TAINT_STR|SUBST_TAINT_PAT|SUBST_TAINT_REPL)))
- SvTAINTED_on(cx->sb_targ);
+ SvTAINTED_on((pm->op_pmflags & PMf_NONDESTRUCT)
+ ? cx->sb_dstr : cx->sb_targ);
TAINT_NOT;
}
rxres_save(&cx->sb_rxres, rx);