develooper Front page | perl.perl5.porters | Postings from July 2009

%^H (was Re: Coring Variable::Magic / autodie fights with string eval in Perl 5.10.x)

Thread Previous | Thread Next
Nicholas Clark
July 7, 2009 07:02
%^H (was Re: Coring Variable::Magic / autodie fights with string eval in Perl 5.10.x)
Message ID:
On Mon, Jul 06, 2009 at 01:01:42AM +1000, Paul Fenwick wrote:

>    1) Upon string eval, we shallow copy %^H.  We already do this.
>    2) Immediately stringify the values in the copied %^H and store them.
>       We currently appear to do this much later (just before run-time?)

Mostly from memory, the actual implementation is as follows:

Until 5.9.something:

%^H points to PL_hintgv, which is a HV
At various times, %^H is copied.
I believe that this is when a compiling scope nests. There is a macro
SAVEHINTS(), which maps to Perl_save_hints(), which makes a shallow copy
of %^H, so that it can restore PL_hintgv (and this %^H) at scope stack

So that's 1 cause of copying already.

%^H manipulation happens entirely at compile time, dynamically, which is why,
by the time a string eval runs, %^H likely bears no resemblance to the %^H
present at compile time of the enclosing scope.

Two things happened in 5.9.something

Firstly, as part of smartmatch, Robin Houston added the ability to pass the
*correct* %^H into string evals. He did this by changing the implementation.
He arranged for a shallow copy of PL_hintgv at compile time, stored that
copy in the optree, and changed the OP for eval to pick it up.

So that's the copy that has become visible.

I considered merging this to maint-5.8. After all, it fixes one set of bugs -
core pragmata implemented via %^H would now correctly propagate into string
evals. However, my gut feeling was that this could create more trouble than
it was worth - code likely would be relying on the bug, and likely evals
would silently fail and weird stuff happen.

(This is based on the experience of fixing a bug with the propagation of
strict in 5.8.7, which I know exposed a bug in one CPAN module, and the
fun of "Bring the joy of strict to Attribute::Handlers."

I added strict to Attribute::Handlers. All tests passed. I'd actually also
added one or two bugs. Other people detected and fixed these.)

Secondly, I added the code to store the state of %^H in the optree, to allow
proper user defined pragmata. That's the work that caused the documentation
of %^H to change from "internal use only" to "use like this".

It doesn't actually stringify at end of scope. %^H is actually (effectively)
tied - as soon as something is written to PL_hintgv, a hook via magic is used
to also write the state out to the optree.

I looked into removing Robin's PL_hintgv copying. After all, we were already
storing the information elsewhere. So I tried it. But some charnames tests
failed. It turns out that it is storing references in %^H, and relying on
the copy to get them into eval. I thought about changing it to be "clean",
but on balance, decided

1: I have finite time
2: It *is* internal use, so we control both ends, so we can use undocumented
3: We have tests for it.

So, right now, the destruction time rules for %^H are wooly at best.
One doesn't know for sure when it's going to go away.
So trying to give well defined semantics for when %^H gets destroyed,
so that an end of scope hook can piggy back off it, is way way more pain
than directly providing an end of scope hook.

(Have you tried changing the troublesome tests to use more than one set of
{}s? Do different things break? Given the description above of the scoping
of copies of %^H, I suspect that there are more complex constructions with
blocks and string evals which can also trigger other bugs.)

No, I don't have any real idea of Perl-space syntax for an end of scope
hook. Or how to meaningfully encode a "restart of scope" hook, which a
string eval would need. [After all, a pragma is in force for the compilation
of the string eval, and on completing the compilation of that string eval,
it goes out of scope, doesn't it? :-)]

But I think it's reasonable to assume that the current implementation,
and quirks thereof, will remain for the duration of the 5.10.x branch,
unless and until an end of scope hook is provide.d

Nicholas Clark

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About