[perl #113710] Make __SUB__ work in sort block
authorFather Chrysostomos <sprout@cpan.org>
Sat, 14 Jul 2012 07:07:03 +0000 (00:07 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 14 Jul 2012 07:07:03 +0000 (00:07 -0700)
commitd7ab38e86270ebb461e1e10c7be726e399e19c78
tree32eda6e2e4903ce04833238a109b5ee5a030d8a4
parentac7af3f615eb56bda50bf123662b15779da26826
[perl #113710] Make __SUB__ work in sort block

When the peephole optimiser encounters a __SUB__, it looks to see
whether the current sub is clonable.  If it is not, it inlines the
__SUB__ as a const op.

This works most of the time.  A forward declaration will cause the sub
definition to reuse the existing stub.  When that happens, the sub
visible during compilation in PL_compcv is not the sub that the
op tree will finally be attached to.  But the peephole optimiser
is called after that, with PL_compcv set to the other CV (what
was a stub).

ck_sort was calling the peephole optimiser on the sort block ahead of
time.  So this caused __SUB__ to point to the wrong subroutine.

By removing the CALL_PEEP call from ck_sort and adding logic to the
peephole optimiser itself to traverse the sort block (it is not in the
usual op_next chain), this bug is eliminated.

I modified the DEFER macro to work as a single statement.  You don’t
want to know how much time I spent debugging the bus errors that were
occurring because if(foo) DEFER; didn’t do what I though.

It turns out that grepstart and mapstart, which also use ck_sort,
had their blocks go through the peephole optimiser twice, because
grepwhile already has special-casing in the peephole optimiser.

This also has the side-effect of making map and grep slightly more
efficient, in that they no longer execute a scope op (which is just
pp_null).  By temporarily disconnecting the subtree before running the
optimiser, ck_sort was hiding a possible optimisation (skipping the
scope op).
ext/B/t/f_map.t
ext/B/t/f_sort.t
op.c
t/op/current_sub.t