This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Improve void varop optimisation
authorFather Chrysostomos <sprout@cpan.org>
Thu, 16 Oct 2014 23:18:59 +0000 (16:18 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 16 Oct 2014 23:35:26 +0000 (16:35 -0700)
After eliding the varop, the optimisation added in 5afbd733 repro-
cesses the previous op if it is a nextstate op.  But it was doing this
by setting the current op to the one before the nextstate, so that the
o=o->op_next in the loop header would cause it to reprocess the next-
state in the next iteration.  So, if that nextstate op were at the
beginning of a subroutine, the optimisation would be skipped, and this
would still execute two nextstate ops in a row:

sub foo {
    our($a, $b);
    die;
}

So, instead, just use ‘goto’ to reprocess the op, and we can do it
even if there is no op before the nextstate.

lib/B/Deparse.t
op.c
t/op/opt.t

index 52e0084..7a0c4d9 100644 (file)
@@ -1470,9 +1470,9 @@ my($m7, undef, $m8) = (1, 2, 3);
 ($m7, undef, $m8) = (1, 2, 3);
 ####
 # 'our/local' works with padrange op
-no strict;
 our($z, @z);
 our $o1;
+no strict;
 local $o11;
 $o1 = 1;
 local $o1 = 1;
diff --git a/op.c b/op.c
index 9fd1d09..c6d8d25 100644 (file)
--- a/op.c
+++ b/op.c
@@ -11709,6 +11709,7 @@ Perl_rpeep(pTHX_ OP *o)
            break;
        }
 
+      redo:
        /* By default, this op has now been optimised. A couple of cases below
           clear this again.  */
        o->op_opt = 1;
@@ -12238,12 +12239,12 @@ Perl_rpeep(pTHX_ OP *o)
                oldop->op_next = o->op_next->op_next;
                /* Reprocess the previous op if it is a nextstate, to
                   allow double-nextstate optimisation.  */
-               if (oldop->op_type == OP_NEXTSTATE && oldoldop
-                && oldoldop->op_next == oldop) {
+               if (oldop->op_type == OP_NEXTSTATE) {
                    oldop->op_opt = 0;
-                   o = oldop = oldoldop;
+                   o = oldop;
+                   oldop = oldoldop;
                    oldoldop = NULL;
-                   continue;
+                   goto redo;
                }
                o = oldop;
            }
index aa73fd7..50eff6d 100644 (file)
@@ -9,7 +9,7 @@ BEGIN {
     @INC = '../lib';
 }
 
-plan 20;
+plan 21;
 
 use B qw 'svref_2object OPpASSIGN_COMMON';
 
@@ -62,6 +62,13 @@ is svref_2object(sub { 0;0;0;0;0;0;time })->START->next->name, 'time',
   'multiple nextstates become one';
 
 
+# rv2[ahs]v in void context
+
+is svref_2object(sub { our($foo,@fit,%far); our $bar; our($a,$b); time })
+    ->START->next->name, 'time',
+  'rv2[ahs]v in void context';
+
+
 # split to array
 
 for(['@pkgary'      , '@_'       ],