diff --git a/embed.fnc b/embed.fnc index 51e4c35760..2eea441b75 100644 --- a/embed.fnc +++ b/embed.fnc @@ -3114,6 +3114,8 @@ Adp |SV * |sv_bless |NN SV * const sv \ Cdmp |bool |sv_2bool |NN SV * const sv Cdp |bool |sv_2bool_flags |NN SV *sv \ |I32 flags +Cp |bool |sv_can_swipe_pv_buf \ + |NN SV *sv Adp |bool |sv_cat_decode |NN SV *dsv \ |NN SV *encoding \ |NN SV *ssv \ diff --git a/embed.h b/embed.h index b4ec209d8c..f1930a9e09 100644 --- a/embed.h +++ b/embed.h @@ -707,6 +707,7 @@ # define sv_2uv_flags(a,b) Perl_sv_2uv_flags(aTHX_ a,b) # define sv_backoff Perl_sv_backoff # define sv_bless(a,b) Perl_sv_bless(aTHX_ a,b) +# define sv_can_swipe_pv_buf(a) Perl_sv_can_swipe_pv_buf(aTHX_ a) # define sv_cat_decode(a,b,c,d,e,f) Perl_sv_cat_decode(aTHX_ a,b,c,d,e,f) # define sv_catpv(a,b) Perl_sv_catpv(aTHX_ a,b) # define sv_catpv_flags(a,b,c) Perl_sv_catpv_flags(aTHX_ a,b,c) diff --git a/proto.h b/proto.h index 1e4ffe3c66..120cc032cf 100644 --- a/proto.h +++ b/proto.h @@ -4534,6 +4534,11 @@ Perl_sv_bless(pTHX_ SV * const sv, HV * const stash); #define PERL_ARGS_ASSERT_SV_BLESS \ assert(sv); assert(stash) +PERL_CALLCONV bool +Perl_sv_can_swipe_pv_buf(pTHX_ SV *sv); +#define PERL_ARGS_ASSERT_SV_CAN_SWIPE_PV_BUF \ + assert(sv) + PERL_CALLCONV bool Perl_sv_cat_decode(pTHX_ SV *dsv, SV *encoding, SV *ssv, int *offset, char *tstr, int tlen); #define PERL_ARGS_ASSERT_SV_CAT_DECODE \ diff --git a/sv.c b/sv.c index dc3bbdc3fd..935e839f77 100644 --- a/sv.c +++ b/sv.c @@ -4187,6 +4187,33 @@ S_sv_buf_to_rw(pTHX_ SV *sv) # define sv_buf_to_rw(sv) NOOP #endif + +/* The test in this macro was extracted from Perl_sv_setsv_flags so that it + * could be used elsewhere. */ +#define S_SvPV_can_swipe_buf(ssv, sflags, cur, len) \ + (( /* Either ... */ \ + /* slated for free anyway (and not COW)? */ \ + ((sflags & (SVs_TEMP|SVf_IsCOW)) == SVs_TEMP) \ + /* or a swipable TARG */ \ + || ((sflags & \ + (SVs_PADTMP|SVf_READONLY|SVf_PROTECT|SVf_IsCOW))== SVs_PADTMP \ + /* whose buffer is worth stealing */ \ + && CHECK_COWBUF_THRESHOLD(cur,len) \ + ) \ + ) && !(sflags & SVf_OOK) /* and not involved in OOK hack? */ \ + && (SvREFCNT(ssv) == 1) /* and no other references to it? */ \ + && len /* and really is a string */ \ + ) + +/* Perl_sv_can_swipe_pv_buf was originally created for pp_reverse. */ +bool +Perl_sv_can_swipe_pv_buf(pTHX_ SV *sv) +{ + PERL_ARGS_ASSERT_SV_CAN_SWIPE_PV_BUF; + assert(sv); + return S_SvPV_can_swipe_buf(sv, SvFLAGS(sv), SvCUR(sv), SvLEN(sv)) ? true : false; +} + void Perl_sv_setsv_flags(pTHX_ SV *dsv, SV* ssv, const I32 flags) { @@ -4593,23 +4620,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dsv, SV* ssv, const I32 flags) and doing it now facilitates the COW check. */ (void)SvPOK_only(dsv); - if ( - ( /* Either ... */ - /* slated for free anyway (and not COW)? */ - (sflags & (SVs_TEMP|SVf_IsCOW)) == SVs_TEMP - /* or a swipable TARG */ - || ((sflags & - (SVs_PADTMP|SVf_READONLY|SVf_PROTECT|SVf_IsCOW)) - == SVs_PADTMP - /* whose buffer is worth stealing */ - && CHECK_COWBUF_THRESHOLD(cur,len) - ) - ) && - !(sflags & SVf_OOK) && /* and not involved in OOK hack? */ - (!(flags & SV_NOSTEAL)) && - /* and we're allowed to steal temps */ - SvREFCNT(ssv) == 1 && /* and no other references to it? */ - len) /* and really is a string */ + if ( !(flags & SV_NOSTEAL) && S_SvPV_can_swipe_buf(ssv, sflags, cur, len) ) { /* Passes the swipe test. */ if (SvPVX_const(dsv)) /* we know that dtype >= SVt_PV */ SvPV_free(dsv);