diff options
author | David Mitchell <davem@iabyn.com> | 2012-10-30 15:10:06 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2012-11-10 13:39:32 +0000 |
commit | d5524600caf9e8c470e731c4f5a924868154645a (patch) | |
tree | abed2ab4c1c8d698b7fe2c5efdeaec392b680e57 /pp_hot.c | |
parent | 528ad060d8dbad9e971c22550cece80330a23dd3 (diff) | |
download | perl-d5524600caf9e8c470e731c4f5a924868154645a.tar.gz |
padrange: handle @_ directly
In a construct like
my ($x,$y) = @_
the pushmark/padsv/padsv is already optimised into a single padrange
op. This commit makes the OPf_SPECIAL flag on the padrange op indicate
that in addition, @_ should be pushed onto the stack, skipping an
additional pushmark/gv[*_]/rv2sv combination.
So in total (including the earlier padrange work), the above construct
goes from being
3 <0> pushmark s
4 <$> gv(*_) s
5 <1> rv2av[t3] lK/1
6 <0> pushmark sRM*/128
7 <0> padsv[$x:1,2] lRM*/LVINTRO
8 <0> padsv[$y:1,2] lRM*/LVINTRO
9 <2> aassign[t4] vKS
to
3 <0> padrange[$x:1,2; $y:1,2] l*/LVINTRO,2 ->4
4 <2> aassign[t4] vKS
Diffstat (limited to 'pp_hot.c')
-rw-r--r-- | pp_hot.c | 57 |
1 files changed, 40 insertions, 17 deletions
@@ -306,6 +306,35 @@ PP(pp_concat) } } +/* push the elements of av onto the stack. + * XXX Note that padav has similar code but without the mg_get(). + * I suspect that the mg_get is no longer needed, but while padav + * differs, it can't share this function */ + +void +S_pushav(pTHX_ AV* const av) +{ + dSP; + const I32 maxarg = AvFILL(av) + 1; + EXTEND(SP, maxarg); + if (SvRMAGICAL(av)) { + U32 i; + for (i=0; i < (U32)maxarg; i++) { + SV ** const svp = av_fetch(av, i, FALSE); + /* See note in pp_helem, and bug id #27839 */ + SP[i+1] = svp + ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp + : &PL_sv_undef; + } + } + else { + Copy(AvARRAY(av), SP+1, maxarg, SV*); + } + SP += maxarg; + PUTBACK; +} + + /* ($lex1,@lex2,...) or my ($lex1,@lex2,...) */ PP(pp_padrange) @@ -314,6 +343,13 @@ PP(pp_padrange) PADOFFSET base = PL_op->op_targ; int count = (int)(PL_op->op_private) & OPpPADRANGE_COUNTMASK; int i; + if (PL_op->op_flags & OPf_SPECIAL) { + /* fake the RHS of my ($x,$y,..) = @_ */ + PUSHMARK(SP); + S_pushav(aTHX_ GvAVn(PL_defgv)); + SPAGAIN; + } + /* note, this is only skipped for compile-time-known void cxt */ if ((PL_op->op_flags & OPf_WANT) != OPf_WANT_VOID) { EXTEND(SP, count); @@ -850,23 +886,10 @@ PP(pp_rv2av) (until such time as we get tools that can do blame annotation across whitespace changes. */ if (gimme == G_ARRAY) { - const I32 maxarg = AvFILL(av) + 1; - (void)POPs; /* XXXX May be optimized away? */ - EXTEND(SP, maxarg); - if (SvRMAGICAL(av)) { - U32 i; - for (i=0; i < (U32)maxarg; i++) { - SV ** const svp = av_fetch(av, i, FALSE); - /* See note in pp_helem, and bug id #27839 */ - SP[i+1] = svp - ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp - : &PL_sv_undef; - } - } - else { - Copy(AvARRAY(av), SP+1, maxarg, SV*); - } - SP += maxarg; + SP--; + PUTBACK; + S_pushav(aTHX_ av); + SPAGAIN; } else if (gimme == G_SCALAR) { dTARGET; |