diff options
author | Richard Leach <richardleach@users.noreply.github.com> | 2021-06-12 01:28:25 +0100 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2022-06-08 14:26:35 +1000 |
commit | 2ebf8a2046483a8d79ad2050abd76cc78e70dd3c (patch) | |
tree | 4b499a7f71f236d3f0b5bc358c0cb89cadd3e0bd /pp.c | |
parent | dd834db38c17eed742a7adc0c4baad02341dcd03 (diff) | |
download | perl-2ebf8a2046483a8d79ad2050abd76cc78e70dd3c.tar.gz |
pp_unshift: av_store is often unnecessary
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 27 |
1 files changed, 24 insertions, 3 deletions
@@ -5859,10 +5859,31 @@ PP(pp_unshift) av_unshift(ary, SP - MARK); PL_delaymagic = DM_DELAY; - while (MARK < SP) { - SV * const sv = newSVsv(*++MARK); - (void)av_store(ary, i++, sv); + + if (!SvMAGICAL(ary)) { + /* The av_unshift above means that many of the checks inside + * av_store are unnecessary. If ary does not have magic attached + * then a simple direct assignment is possible here. */ + while (MARK < SP) { + SV * const sv = newSVsv(*++MARK); + assert( !SvTIED_mg((const SV *)ary, PERL_MAGIC_tied) ); + assert( i >= 0 ); + assert( !SvREADONLY(ary) ); + assert( AvREAL(ary) || !AvREIFY(ary) ); + assert( i <= AvMAX(ary) ); + assert( i <= AvFILLp(ary) ); + if (AvREAL(ary)) + SvREFCNT_dec(AvARRAY(ary)[i]); + AvARRAY(ary)[i] = sv; + i++; + } + } else { + while (MARK < SP) { + SV * const sv = newSVsv(*++MARK); + (void)av_store(ary, i++, sv); + } } + if (PL_delaymagic & DM_ARRAY_ISA) mg_set(MUTABLE_SV(ary)); PL_delaymagic = old_delaymagic; |