diff options
author | Father Chrysostomos <sprout@cpan.org> | 2014-11-02 06:02:18 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2014-11-13 04:49:39 -0800 |
commit | 9d391755a062145d74c79dabcfd610dda7e9c441 (patch) | |
tree | ba2f3e0f4b72be5e72d4ce4d9c2f958bc4ad20bc /op.c | |
parent | 3c37c25ad7cb92aee523edcbedcb46950479df92 (diff) | |
download | perl-9d391755a062145d74c79dabcfd610dda7e9c441.tar.gz |
Don’t inline sub(){ 0; return $x }
If return occurs at the end of a sub, it is optimised out of the
execution, chain, so we have to look at the op tree structure to
detect it.
Diffstat (limited to 'op.c')
-rw-r--r-- | op.c | 10 |
1 files changed, 9 insertions, 1 deletions
@@ -8578,7 +8578,15 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, if (CvCLONE(cv)) { assert(!CvCONST(cv)); - if (ps && !*ps && !attrs && op_const_sv(block, cv, NULL)) + if (ps && !*ps && !attrs + /* Check whether this sub is a potentially inlinable closure. + First check for an explicit return at the end of the sub. + Perl_rpeep will have removed it from the execution chain, + yet we promise that it will prevent inlining. */ + && block->op_type == OP_LINESEQ + && cLISTOPx(block)->op_last->op_type != OP_RETURN + /* Then search the op tree for a single lexical. */ + && op_const_sv(block, cv, NULL)) CvCONST_on(cv); } |