Front page | perl.perl5.porters |
Postings from June 2008
Re: [perl #56150] return return
Thread Previous
|
Thread Next
From:
Reini Urban
Date:
June 25, 2008 04:15
Subject:
Re: [perl #56150] return return
Message ID:
48611B82.8060304@x-ray.at
David Nicol schrieb:
> On Mon, Jun 23, 2008 at 10:20 AM, Aristotle Pagaltzis <pagaltzis@gmx.de> wrote:
>
>> And those of us who prefer to use guard clauses and not contort
>> subroutines into nested single expressions cannot avoid `return`
>> at all.
>
> leaving the question, why doesn't the optimizer get rid of return?
>
> tentative answer: because the optimizer authors didn't get around to it,
> seeing once-per-subroutine as not enough savings to justify the effort.
The optimizer does something with the op_type OP_RETURN.
The ck_return() does change all kids to OP_LEAVESUBLV if lvalue'd.
The problem is the tokenizer.
Concise does not help - identical results.
$ perl5.11.0d -MO=Concise,-exec -e'sub foo {return return}; foo'
1 <0> enter
2 <;> nextstate(main 2 -e:1) v:{
3 <0> pushmark s
4 <#> gv[*foo] s
5 <1> entersub[t2] vKS/TARG,1
6 <@> leave[1 ref] vKP/REFC
$ perl5.11.0d -MO=Concise,-exec -e'sub foo {return}; foo'
1 <0> enter
2 <;> nextstate(main 2 -e:1) v:{
3 <0> pushmark s
4 <#> gv[*foo] s
5 <1> entersub[t2] vKS/TARG,1
6 <@> leave[1 ref] vKP/REFC
At least -Dt (and -MO=Bytecode,-S) show something useful:
$ perl5.11.0d -Dt -e'sub foo {return return}; foo'
EXECUTING...
(-e:0) enter
(-e:0) nextstate
(-e:1) pushmark
(-e:1) gv(main::foo)
(-e:1) entersub
(-e:1) nextstate
(-e:1) pushmark
(-e:1) pushmark
(-e:1) return
(-e:1) leave
$ perl5.11.0d -Dt -e'sub foo {return}; foo'
EXECUTING...
(-e:0) enter
(-e:0) nextstate
(-e:1) pushmark
(-e:1) gv(main::foo)
(-e:1) entersub
(-e:1) nextstate
(-e:1) pushmark
(-e:1) return
(-e:1) leave
The disassembler perl -MO=Bytecode,-S -e'sub foo {return return}; foo'
shows the two returns contain op_flags 4 (KIDS) and nothing else.
So I thought ck_return could check if the kid is also a return and warn
then. ck_return is called twice, but it turns out that this op_return
has no next and no sibling pointer at this stage.
So the new warning is never triggered.
diff -u op.c.orig op.c
--- op.c.orig 2008-06-17 11:25:08.000000000 +0000
+++ op.c 2008-06-24 16:00:28.437500000 +0000
@@ -7568,6 +7568,14 @@
OP *kid;
for (kid = cLISTOPo->op_first->op_sibling; kid; kid =
kid->op_sibling)
mod(kid, OP_LEAVESUBLV);
+ } else {
+ OP *kid;
+ kid = cLISTOPo->op_first->op_sibling;
+ if (kid->op_type == OP_RETURN) {
+ Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
+ "Ignored return return");
+ mod(o->op_next, OP_NULL);
+ }
}
return o;
}
Breakpoint 1, Perl_ck_return (my_perl=0x1871fd0, o=0x18728a8) at
opmini.c:7565
7565 PERL_ARGS_ASSERT_CK_RETURN;
(gdb) p *o
$2 = {op_next = 0x0, op_sibling = 0x0, op_ppaddr = 0x5a8f19
<Perl_pp_return>,
op_madprop = 0x0, op_targ = 0, op_type = 190, op_opt = 0, op_latefree
= 0,
op_latefreed = 0, op_attached = 0, op_spare = 0, op_flags = 4 '\004',
op_private = 0 '\0'}
(gdb) c
So it must be done in peep().
--
Reini Urban
http://phpwiki.org/ http://murbreak.at/
Thread Previous
|
Thread Next