In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/8717a761ed4c6bc51add235060c04edd152bcdb6?hp=5afbd73327c66567d331236ae7c1ad047efd945a>
- Log ----------------------------------------------------------------- commit 8717a761ed4c6bc51add235060c04edd152bcdb6 Author: Father Chrysostomos <[email protected]> Date: Wed Oct 15 20:37:30 2014 -0700 op.c: Null list and pushmark in void cx See 7d3c8a6837 for the explanation. âour($foo,$bar);â is one example of the legitimate use of list+push- mark in void context. Here, we can null them and remove them from the execution order, since they are not necessary. We only do this if this is an op sequence that padrange would not optimise, since padrange needs a pushmark, and we donât want to disable it. This combined with other recent optimisations makes code like this: our ($foo,@bar,%baz); our $a; our ($b,$c); die; skip straight over all those variable declarations at run time, going straight to the âdieâ. ----------------------------------------------------------------------- Summary of changes: op.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/op.c b/op.c index cfb57e4..9fd1d09 100644 --- a/op.c +++ b/op.c @@ -11662,7 +11662,7 @@ S_null_listop_in_list_context(pTHX_ OP *o) PERL_ARGS_ASSERT_NULL_LISTOP_IN_LIST_CONTEXT; - /* This is an OP_LIST in list context. That means we + /* This is an OP_LIST in list (or void) context. That means we * can ditch the OP_LIST and the OP_PUSHMARK within. */ kid = cLISTOPo->op_first; @@ -11716,7 +11716,8 @@ Perl_rpeep(pTHX_ OP *o) /* The following will have the OP_LIST and OP_PUSHMARK - * patched out later IF the OP_LIST is in list context. + * patched out later IF the OP_LIST is in list context, or + * if it is in void context and padrange is not possible. * So in that case, we can set the this OP's op_next * to skip to after the OP_PUSHMARK: * a THIS -> b @@ -11734,17 +11735,28 @@ Perl_rpeep(pTHX_ OP *o) { OP *sibling; OP *other_pushmark; + OP *pushsib; if (OP_TYPE_IS(o->op_next, OP_PUSHMARK) && (sibling = OP_SIBLING(o)) && sibling->op_type == OP_LIST /* This KIDS check is likely superfluous since OP_LIST * would otherwise be an OP_STUB. */ && sibling->op_flags & OPf_KIDS - && (sibling->op_flags & OPf_WANT) == OPf_WANT_LIST && (other_pushmark = cLISTOPx(sibling)->op_first) /* Pointer equality also effectively checks that it's a * pushmark. */ - && other_pushmark == o->op_next) + && other_pushmark == o->op_next + /* List context */ + && ( (sibling->op_flags & OPf_WANT) == OPf_WANT_LIST + /* ... or void context... */ + || ( (sibling->op_flags & OPf_WANT) == OPf_WANT_VOID + /* ...and something padrange would reject */ + && ( !(pushsib = OP_SIBLING(other_pushmark)) + || ( pushsib->op_type != OP_PADSV + && pushsib->op_type != OP_PADAV + && pushsib->op_type != OP_PADHV) + || pushsib->op_private & ~OPpLVAL_INTRO)) + )) { o->op_next = other_pushmark->op_next; null_listop_in_list_context(sibling); -- Perl5 Master Repository
