diff options
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; |