summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2014-11-01 22:17:39 -0700
committerFather Chrysostomos <sprout@cpan.org>2014-11-13 04:49:39 -0800
commit3c37c25ad7cb92aee523edcbedcb46950479df92 (patch)
tree1fe1a4952ba0cd928755bfc7fa373f93b9a914bd /op.c
parentcb12c7ef455562eb196a81a76e8968794ce8f455 (diff)
downloadperl-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.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/op.c b/op.c
index ee2890f10e..1ec729ee3b 100644
--- a/op.c
+++ b/op.c
@@ -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;