develooper Front page | perl.perl5.porters | Postings from January 2018

Re: Captured lexicals stolen from outer scope's pad

Thread Previous | Thread Next
From:
Father Chrysostomos
Date:
January 22, 2018 18:00
Subject:
Re: Captured lexicals stolen from outer scope's pad
Message ID:
20180122180043.2452.qmail@lists-nntp.develooper.com
Paul Evans wrote:
> On Mon, 22 Jan 2018 03:29:26 +0000
> "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
> >  1) Why does perl decide to steal the AV from the outside's pad and
> >     replace it there with an empty stale AV?
> 
> Turns out - there isn't any code for that. The outside's pad got tidied
> up somehow because it was finished, and its SVs replaced by empty
> stale-marked ones. The fact this hadn't turned up in unit testing
> of F::AA until now was that I hadn't thought of trying to capture
> lexicals from inside a scope that I then ended before running the test
> against some named functions from it. I've now added such a test.

I was going to explain just that, but then I saw you had answered your
own question.  Just for clarity (this may be stuff you already know),
in your example:

  my @POWERDOWN_TO_NAME =3D qw( normal 1k 100k 500k );

  ...

  sub read_config
  {
     ...
     sub { ... $POWERDOWN_TO_NAME[$idx] };
  }

there are initially three CVs involved.  The first one, which
declares the array, is a file-scope CV.  Then you have the CV named
read_config, which contains a the third CV, a closure prototype.

At run time, whenever you call read_config, the closure prototype gets
cloned, making yet another CV.

Now, to what is happening with the lexical, which is...complicated:

1. At compile time, the my @POWERBLAH declaration allocates a slot in
   the file-CV's pad, with an initial empty array.
2. When the anonymous sub inside read_config is compiled, it closes
   over the @POWERBLAH array, causing not only its own pad, but also
   read_config's pad to get an entry for the array.  read_config at
   this point gets the value of the parent's pad entry.
3. When the file-CV reaches run time, the 'my' declaration has its
   run-time effect, which is to schedule the lexical (via SAVEFREESV)
   to be cleared on scope exit.
4. When the file-CV finishes running, the code in scope.c that clears
   the entry sees that it is referenced elsewhere (its refcnt is
   high), so it swaps it out and places another one in its place.

When you have named subs closing over lexical variables, since the
named subs only get one chance to capture the variable, you are likely
to get the 'will not stay shared' and 'is not available' messages.
However, knowing that the outer CV in this case is only run once,
Perl makes an exception and suppresses the warnings.  By cloning a
named sub, you have created a situation the code was not written ot
account for.

I hope that explanation is useful to someone. :-)

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About