Another faulty padrange assumption
authorFather Chrysostomos <sprout@cpan.org>
Sat, 21 Sep 2013 21:03:38 +0000 (14:03 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 21 Sep 2013 23:20:35 +0000 (16:20 -0700)
Commit 7601007 was not sufficient.  There are two places where the
padrange optimisation tries to combine multiple padranges.

When a padrange op is created in rpeep, the code first checks whether
the previous op is already a padrange, so the two can be combined, as
in this case:

    my ($a,$b,$c);
    my ($d,$e,$f);

Then the code checks whether it can swallow up any singletons follow-
ing it, optimising cases like this:

    my ($v,$w,$x);
    my $y;

Commit 7601007 fixed the latter, which was assuming that $x and $y
would have contiguous pad offsets.

This commit fixes the former code, which assumed $c and $d would have
contiguous offsets.

This was causing assertion failures or crashes for Devel::CallParser
0.001 (0.002 works around it), because Devel::CallParser creates new
pad entries when the second ‘my’ keyword is encountered, causing the
pad offsets not to be contiguous.

op.c

index 922fe61..49de893 100644 (file)
--- a/op.c
+++ b/op.c
@@ -11265,9 +11265,14 @@ Perl_rpeep(pTHX_ OP *o)
 
                         old_count
                             = (oldoldop->op_private & OPpPADRANGE_COUNTMASK);
-                        assert(oldoldop->op_targ + old_count == base);
 
-                        if (old_count < OPpPADRANGE_COUNTMASK - count) {
+                       /* Do not assume pad offsets for $c and $d are con-
+                          tiguous in
+                            my ($a,$b,$c);
+                            my ($d,$e,$f);
+                        */
+                        if (  oldoldop->op_targ + old_count == base
+                           && old_count < OPpPADRANGE_COUNTMASK - count) {
                             base = oldoldop->op_targ;
                             count += old_count;
                             reuse = 1;