develooper Front page | perl.perl5.porters | Postings from October 2003

Re: [perl #24250] "return" required in some anonymous closures

Dave Mitchell
October 20, 2003 15:53
Re: [perl #24250] "return" required in some anonymous closures
Message ID:
On Mon, Oct 20, 2003 at 06:20:13PM +0100, Graham Barr wrote:
> On 20 Oct 2003, at 17:48, Dave Mitchell wrote:
> >On Mon, Oct 20, 2003 at 04:59:20PM +0100, Graham Barr wrote:
> >>It is only supposed to generate a constant sub if there are no other
> >>references to the variable. ie there is no way the variable can 
> >>change.
> >
> >But it's easy to create a reference after the event:
> >
> >    sub new_constant_sub {
> >	my $val = shift;
> >	my $s = sub() {$val};	# only one ref, so $s a const sub
> But that is not when its decided that its a constant sub. Or at least 
> originally it was not.
> When constant subs were first introduced it was in the optimizer that 
> the decision was taken if a sub was constant, not when the sab was 
> made. The decision was "does the sub being called have a proto of () 
> and is its body a single scalar with a refcnt of 1", if yes then inline 
> it.
> I am guessing that logic has been pushed back to when the sub is 
> defined, which has resulted in this bug

The 5.6.0 behaviour was that subs (named or anon) were not marked as CONST
at compile time; instead at every compile-time appearance of a sub call,
the sub was checked for having a constant value or a single lexical with
refcount<2, and if so the OP_ENTERSUB was replaced with an OP_CONST.

This meant that C<use constant> cloned a full heavyweight anon sub for
each defined constant.

In 5.8.0, sub f(){1}-style subs were detected at compile time as being
constant, and if so, replaced with CvCONSTs. sub(){$x}'s were detected
as being CONST *candidates* at compile time if the refcnt of $x was < 2.
Then each time they were cloned, the current value of $x was copied to
make a new CvCONST sub. Due to the vagarites of lexical bugs prior to
bleedperl, the compile-time test for the lexical refcnt being < 2 was not
always very DWIM.

In bleedperl, I changed it to a hybrid behaviour. At compile time, the
anon CV prototype is marked as a CONST candidate if it contains a single
outer lexical. At clone time, the cloned CV is converted into a CvCONST if
the lexical has a refcnt < 2.

Thus, the refcnt<2 test is done:

5.6.0: sometime after cloning, when the sub call is being compiled
5.6.0: when the anon sub is compiled
bleed: when the anon sub is cloned

Both the 5.8.0 and bleedperl behaviours have problems, and are very
sensitive to their environments, and will generally do things that people
find unexpected.

Thus, I like Elizabeth's suggestion of using a compile-time attribute
to explicitly turn on this special behaviour, and thus to not suprise the
ordinary user.


O Unicef Clearasil!
Gibberish and Drivel!
                      - "Bored of the Rings" Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About