diff options
author | Nicholas Clark <nick@ccl4.org> | 2011-06-17 16:40:30 +0200 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2011-06-23 10:22:13 +0200 |
commit | 8ca8a454f60a417f5040d6e3e47673333702f58d (patch) | |
tree | eff5d0d46490c02817e88b95e66f0beaf0a9b2a1 /pp_ctl.c | |
parent | 7c4202907c499a6fd1a41da6fdf1d414ecadeb37 (diff) | |
download | perl-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.c | 47 |
1 files changed, 27 insertions, 20 deletions
@@ -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); |