This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #114924] Make method calls work with ::SUPER packages
authorFather Chrysostomos <sprout@cpan.org>
Mon, 17 Sep 2012 23:24:40 +0000 (16:24 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Mon, 17 Sep 2012 23:58:27 +0000 (16:58 -0700)
commitaae438050a206a8067e068319ab3ee2348009463
treefb1ed29ecd0d49c069e121c7d5e1b9628ec7641b
parent9c47725a2c7c1a5a17231082af905d106c5467fb
[perl #114924] Make method calls work with ::SUPER packages

Perl caches SUPER methods inside packages named Foo::SUPER.  But this
interferes with actual method calls on those packages (SUPER->foo,
foo::SUPER->foo).

The first time a package is looked up, it is vivified under the name
with which it is looked up.  So *SUPER:: will cause that package
to be called SUPER, and *main::SUPER:: will cause it to be named
main::SUPER.

main->SUPER::isa used to be very sensitive to the name of the
main::FOO package (where the cache is kept).  If it happened to be
called SUPER, that call would fail.

Fixing that bug (commit 3c104e59d83f) caused the CPAN module named
SUPER to fail, because SUPER->foo was now being treated as a
SUPER::method call.  gv_fetchmeth_pvn was using the ::SUPER suffix to
determine where to look for the method.  The package passed to it (the
::SUPER package) was being used to look for cached methods, but the
package with ::SUPER stripped off was being used for the rest of
lookup.  3c104e59d83f made main->SUPER::foo work by treating SUPER
as main::SUPER in that case.  Mentioning *main::SUPER:: or doing a
main->SUPER::foo call before loading SUPER.pm also caused it to fail,
even before 3c104e59d83f.

Instead of using publicly-visible packages for internal caches, we
should be keeping them internal, to avoid such side effects.

This commit adds a new member to the HvAUX struct, where a hash of GVs
is stored, to cache super methods.  I cannot simpy use a hash of CVs,
because I need GvCVGEN.  Using a hash of GVs allows the existing
method cache code to be used.

This new hash of GVs is not actually a stash, as it has no HvAUX
struct (i.e., no name, no mro_meta).  It doesn’t even need an @ISA
entry as before (which was only used to make isa caches reset), as it
shares its owner stash’s mro_meta generation numbers.  In fact, the
GVs inside it have their GvSTASH pointers pointing to the owner stash.

In terms of memory use, it is probably the same as before.  Every
stash and every iterated or weakly-referenced hash is now one pointer
larger than before, but every SUPER cache is smaller (no HvAUX, no
*ISA + @ISA + $ISA[0] + magic).

The code is a lot simpler now and uses fewer stash lookups, so it
should be faster.

This will break any XS code that expects the gv_fetchmeth_pvn to treat
the ::SUPER suffix as magical.  This behaviour was only barely docu-
mented (the suffix was mentioned, but what it did was not), and is
unused on CPAN.
embed.fnc
embed.h
gv.c
gv.h
hv.c
hv.h
proto.h
t/op/method.t