summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2012-10-30 15:10:06 +0000
committerDavid Mitchell <davem@iabyn.com>2012-11-10 13:39:32 +0000
commitd5524600caf9e8c470e731c4f5a924868154645a (patch)
treeabed2ab4c1c8d698b7fe2c5efdeaec392b680e57 /pp_hot.c
parent528ad060d8dbad9e971c22550cece80330a23dd3 (diff)
downloadperl-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.c57
1 files changed, 40 insertions, 17 deletions
diff --git a/pp_hot.c b/pp_hot.c
index 0ef64f313b..b5551bf2de 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -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;