From: Matthew Horsfall Date: Thu, 9 Jan 2014 02:09:11 +0000 (-0500) Subject: Optimisation for 'my $x; my $y;' -> 'my ($x, $y)'. X-Git-Tag: upstream/5.20.0~575 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c23547d5c65c3ac8b509e78a43d7edc7120604d9;p=platform%2Fupstream%2Fperl.git Optimisation for 'my $x; my $y;' -> 'my ($x, $y)'. Brings: sub { my $x; my $y; return 1; } Up to speed with: sub { my ($x, $y); return 1; } --- diff --git a/ext/B/t/optree_samples.t b/ext/B/t/optree_samples.t index bc682e4..0e93405 100644 --- a/ext/B/t/optree_samples.t +++ b/ext/B/t/optree_samples.t @@ -14,7 +14,7 @@ BEGIN { } use OptreeCheck; use Config; -plan tests => 43; +plan tests => 46; pass("GENERAL OPTREE EXAMPLES"); @@ -707,6 +707,25 @@ EOT_EOT # 9 <1> leavesub[1 ref] K/REFC,1 EONT_EONT +pass("rpeep - my $a; my @b; my %c; print 'f'"); + +checkOptree ( name => 'my $a; my @b; my %c; return 1', + code => 'my $a; my @b; my %c; return 1', + bcopts => '-exec', + expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); +# 1 <;> nextstate(main 991 (eval 17):1) v +# 2 <0> padrange[$a:991,994; @b:992,994; %c:993,994] vM/LVINTRO,3 +# 3 <;> nextstate(main 994 (eval 17):1) v:{ +# 4 <$> const[IV 1] s +# 5 <1> leavesub[1 ref] K/REFC,1 +EOT_EOT +# 1 <;> nextstate(main 991 (eval 17):1) v +# 2 <0> padrange[$a:991,994; @b:992,994; %c:993,994] vM/LVINTRO,3 +# 3 <;> nextstate(main 994 (eval 17):1) v:{ +# 4 <$> const(IV 1) s +# 5 <1> leavesub[1 ref] K/REFC,1 +EONT_EONT + __END__ ####################################################################### diff --git a/op.c b/op.c index dd43323..60aef44 100644 --- a/op.c +++ b/op.c @@ -11200,6 +11200,71 @@ Perl_rpeep(pTHX_ OP *o) } } + /* Optimise 'my $x; my $y;' into 'my ($x, $y);' + * + * This latter form is then suitable for conversion into padrange + * later on. Convert: + * + * nextstate1 -> padop1 -> nextstate2 -> padop2 -> nextstate3 + * + * into: + * + * nextstate1 -> listop -> nextstate3 + * / \ + * pushmark -> padop1 -> padop2 + */ + if (o->op_next && ( + o->op_next->op_type == OP_PADSV + || o->op_next->op_type == OP_PADAV + || o->op_next->op_type == OP_PADHV + ) + && !(o->op_next->op_private & ~OPpLVAL_INTRO) + && o->op_next->op_next && o->op_next->op_next->op_type == OP_NEXTSTATE + && o->op_next->op_next->op_next && ( + o->op_next->op_next->op_next->op_type == OP_PADSV + || o->op_next->op_next->op_next->op_type == OP_PADAV + || o->op_next->op_next->op_next->op_type == OP_PADHV + ) + && !(o->op_next->op_next->op_next->op_private & ~OPpLVAL_INTRO) + && o->op_next->op_next->op_next->op_next && o->op_next->op_next->op_next->op_next->op_type == OP_NEXTSTATE + && (!CopLABEL((COP*)o)) /* Don't mess with labels */ + && (!CopLABEL((COP*)o->op_next->op_next)) /* ... */ + ) { + OP *first; + OP *last; + OP *newop; + + first = o->op_next; + last = o->op_next->op_next->op_next; + + newop = newLISTOP(OP_LIST, 0, first, last); + newop->op_flags |= OPf_PARENS; + newop->op_flags = (newop->op_flags & ~OPf_WANT) | OPf_WANT_VOID; + + /* Kill nextstate2 between padop1/padop2 */ + op_free(first->op_next); + + first->op_next = last; /* padop2 */ + first->op_sibling = last; /* ... */ + o->op_next = cUNOPx(newop)->op_first; /* pushmark */ + o->op_next->op_next = first; /* padop1 */ + o->op_next->op_sibling = first; /* ... */ + newop->op_next = last->op_next; /* nextstate3 */ + newop->op_sibling = last->op_sibling; + last->op_next = newop; /* listop */ + last->op_sibling = NULL; + o->op_sibling = newop; /* ... */ + + newop->op_flags = (newop->op_flags & ~OPf_WANT) | OPf_WANT_VOID; + + /* Ensure pushmark has this flag if padops do */ + if (first->op_flags & OPf_MOD && last->op_flags & OPf_MOD) { + o->op_next->op_flags |= OPf_MOD; + } + + break; + } + /* Two NEXTSTATEs in a row serve no purpose. Except if they happen to carry two labels. For now, take the easier option, and skip this optimisation if the first NEXTSTATE has a label. */