diff options
author | Father Chrysostomos <sprout@cpan.org> | 2014-11-01 22:17:39 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2014-11-13 04:49:39 -0800 |
commit | 3c37c25ad7cb92aee523edcbedcb46950479df92 (patch) | |
tree | 1fe1a4952ba0cd928755bfc7fa373f93b9a914bd /op.c | |
parent | cb12c7ef455562eb196a81a76e8968794ce8f455 (diff) | |
download | perl-3c37c25ad7cb92aee523edcbedcb46950479df92.tar.gz |
Don’t inline sub(){ 0; return $x; ... }
We document that explicit return prevents subs from being inlined.
But if that explicit return comes after a statement optimised away,
then it does not prevent inlining.
Originally, explicit return did not prevent inlining, and the way
constant subs were detected was to search through the op chain in
execution order, looking for padsv followed by return or leavesub.
Later, things were accidentally changed, such that the search began,
not at the beginning of the execution chain, but at the outer-
most op of the first statement’s contents. That means that, with
sub () { $a + $b }, we begin the search at the + (add), even though
the execution order is nextstate, gvsv, gvsv, add, leavesub. So for
sub () { return $x } we begin the search at return, and miss the padsv
that precedes it.
Even though it was accidental that ‘return’ inlining was broken, it
ended up becoming a documented feature, and has been so for over a
decade. So I am just making things consistent with that.
This commit only affects those cases where the return is not at the
end of the sub. At the end of the sub, the return is optimised out of
the execution chain, so it requires a little more work, which the next
commit will do.
Diffstat (limited to 'op.c')
-rw-r--r-- | op.c | 2 |
1 files changed, 1 insertions, 1 deletions
@@ -7719,7 +7719,7 @@ Perl_op_const_sv(pTHX_ const OP *o, CV *cv, CV *outcv) if (type == OP_DBSTATE) continue; } - if (type == OP_LEAVESUB || type == OP_RETURN) + if (type == OP_LEAVESUB) break; if (sv) return NULL; |