summaryrefslogtreecommitdiff
path: root/gv.h
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-09-17 16:24:40 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-09-17 16:58:27 -0700
commitaae438050a206a8067e068319ab3ee2348009463 (patch)
treefb1ed29ecd0d49c069e121c7d5e1b9628ec7641b /gv.h
parent9c47725a2c7c1a5a17231082af905d106c5467fb (diff)
downloadperl-aae438050a206a8067e068319ab3ee2348009463.tar.gz
[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.
Diffstat (limited to 'gv.h')
-rw-r--r--gv.h3
1 files changed, 3 insertions, 0 deletions
diff --git a/gv.h b/gv.h
index 30014b622d..8e09340053 100644
--- a/gv.h
+++ b/gv.h
@@ -235,6 +235,9 @@ Return the CV from the GV.
#define GV_NO_SVGMAGIC 0x800 /* Skip get-magic on an SV argument;
used only by gv_fetchsv(_nomg) */
+/* Flags for gv_fetchmeth_pvn and gv_autoload_pvn*/
+#define GV_SUPER 0x1000 /* SUPER::method */
+
/* Flags for gv_autoload_*/
#define GV_AUTOLOAD_ISMETHOD 1 /* autoloading a method? */