In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/ef7999f1f1914f1a33743bbfa196e39f7f041445?hp=fd017c00b1282d493d81ce54d392bc0c3a3ae001>

- Log -----------------------------------------------------------------
commit ef7999f1f1914f1a33743bbfa196e39f7f041445
Author: Father Chrysostomos <spr...@cpan.org>
Date:   Sun Oct 12 00:20:26 2014 -0700

    Optimise my(@array)=split
    
    Even though we can’t optimise away the array op for my(@array),
    local(@array), and @{foo()}, we can still optimise away the assign-
    ment.  Just have split pop the array off the stack and Bob’s
    your Uncle.
-----------------------------------------------------------------------

Summary of changes:
 lib/B/Deparse.pm |  7 ++++++-
 lib/B/Deparse.t  |  3 +++
 op.c             | 23 ++++++++++++++++++++++-
 pp.c             |  6 +++---
 4 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm
index 00a9a3c..ce86193 100644
--- a/lib/B/Deparse.pm
+++ b/lib/B/Deparse.pm
@@ -4972,12 +4972,15 @@ sub pp_split {
     # figures out for us which it is.
     my $replroot = $kid->pmreplroot;
     my $gv = 0;
+    my $stacked = $op->flags & OPf_STACKED;
     if (ref($replroot) eq "B::GV") {
        $gv = $replroot;
     } elsif (!ref($replroot) and $replroot > 0) {
        $gv = $self->padval($replroot);
     } elsif ($kid->targ) {
        $ary = $self->padname($kid->targ)
+    } elsif ($stacked) {
+       $ary = $self->deparse($op->last, 7);
     }
     $ary = $self->maybe_local(@_,
                              $self->stash_variable('@',
@@ -4985,7 +4988,9 @@ sub pp_split {
                                                     $cx))
        if $gv;
 
-    for (; !null($kid); $kid = $kid->sibling) {
+    # Skip the last kid when OPf_STACKED is set, since it is the array
+    # on the left.
+    for (; !null($stacked ? $kid->sibling : $kid); $kid = $kid->sibling) {
        push @exprs, $self->deparse($kid, 6);
     }
 
diff --git a/lib/B/Deparse.t b/lib/B/Deparse.t
index 21e6cdc..b51fe28 100644
--- a/lib/B/Deparse.t
+++ b/lib/B/Deparse.t
@@ -535,6 +535,9 @@ our @ary;
 # Split to our array
 our @array = split(//, 'foo', 0);
 ####
+# Split to my array
+my @array  = split(//, 'foo', 0);
+####
 # bug #40055
 do { () }; 
 ####
diff --git a/op.c b/op.c
index 9f2db9c..9a8cfb6 100644
--- a/op.c
+++ b/op.c
@@ -1696,6 +1696,7 @@ Perl_scalarvoid(pTHX_ OP *o)
        kid = cLISTOPo->op_first;
        if (kid && kid->op_type == OP_PUSHRE
                && !kid->op_targ
+               && !(o->op_flags & OPf_STACKED)
 #ifdef USE_ITHREADS
                && !((PMOP*)kid)->op_pmreplrootu.op_pmtargetoff)
 #else
@@ -6123,7 +6124,8 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, 
OP *right)
                o->op_private |= OPpASSIGN_COMMON;
        }
 
-       if (right && right->op_type == OP_SPLIT) {
+       if (right && right->op_type == OP_SPLIT
+        && !(right->op_flags & OPf_STACKED)) {
            OP* tmpop = ((LISTOP*)right)->op_first;
            if (tmpop && (tmpop->op_type == OP_PUSHRE)) {
                PMOP * const pm = (PMOP*)tmpop;
@@ -6157,6 +6159,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, 
OP *right)
                            pm->op_targ = left->op_targ;
                            left->op_targ = 0; /* filch it */
                        }
+                     detach_split:
                        tmpop = cUNOPo->op_first;       /* to list (nulled) */
                        tmpop = ((UNOP*)tmpop)->op_first; /* to pushmark */
                         /* detach rest of siblings from o subtree,
@@ -6167,6 +6170,24 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, 
OP *right)
                                /* "I don't know and I don't care." */
                        return right;
                    }
+                   else if (left->op_type == OP_RV2AV
+                         || left->op_type == OP_PADAV)
+                   {
+                       /* Detach the array.  */
+#ifdef DEBUGGING
+                       OP * const ary =
+#endif
+                       op_sibling_splice(cBINOPo->op_last,
+                                         cUNOPx(cBINOPo->op_last)
+                                               ->op_first, 1, NULL);
+                       assert(ary == left);
+                       /* Attach it to the split.  */
+                       op_sibling_splice(right, cLISTOPx(right)->op_last,
+                                         0, left);
+                       right->op_flags |= OPf_STACKED;
+                       /* Detach split and expunge aassign as above.  */
+                       goto detach_split;
+                   }
                    else if (PL_modcount < RETURN_UNLIMITED_NUMBER &&
                            ((LISTOP*)right)->op_last->op_type == OP_CONST)
                    {
diff --git a/pp.c b/pp.c
index 80dae1e..25e3ac4 100644
--- a/pp.c
+++ b/pp.c
@@ -5528,7 +5528,7 @@ PP(pp_reverse)
 PP(pp_split)
 {
     dSP; dTARG;
-    AV *ary;
+    AV *ary = PL_op->op_flags & OPf_STACKED ? (AV *)POPs : NULL;
     IV limit = POPi;                   /* note, negative is forever */
     SV * const sv = POPs;
     STRLEN len;
@@ -5577,8 +5577,8 @@ PP(pp_split)
        ary = GvAVn(pm->op_pmreplrootu.op_pmtargetgv);
     }
 #endif
-    else
-       ary = pm->op_targ ? (AV *)PAD_SVl(pm->op_targ) : NULL;
+    else if (pm->op_targ)
+       ary = (AV *)PAD_SVl(pm->op_targ);
     if (ary) {
        realarray = 1;
        PUTBACK;

--
Perl5 Master Repository

Reply via email to