summaryrefslogtreecommitdiff
path: root/mro.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-10-09 18:42:01 -0700
committerFather Chrysostomos <sprout@cpan.org>2010-10-09 18:42:40 -0700
commitc8bbf675c3e9277e1dd4b1185d91c1aef2cd2594 (patch)
treeac43f29d32d5dce5d6a0e58a2ce6bf91454604ce /mro.c
parent314655b3bf3a78f53857298857fbdc053e783117 (diff)
downloadperl-c8bbf675c3e9277e1dd4b1185d91c1aef2cd2594.tar.gz
Reset isa on stash manipulation
This only applies to glob-to-glob assignments and deletions of stash elements. Other types of stash manipulation are dealt with by subse- quent patches. It adds mro_package_moved, a private function that iterates through subpackages, calling mro_isa_changed_in on each. This is related to [perl #75176], but is not the same bug. It simply got in the way of fixing [perl #75176].
Diffstat (limited to 'mro.c')
-rw-r--r--mro.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/mro.c b/mro.c
index 488e564684..bd59465eb3 100644
--- a/mro.c
+++ b/mro.c
@@ -549,6 +549,56 @@ Perl_mro_isa_changed_in(pTHX_ HV* stash)
}
/*
+=for apidoc mro_package_moved
+
+Invalidates isa caches on this stash, on all subpackages nested inside it,
+and on the subclasses of all those.
+
+=cut
+*/
+void
+Perl_mro_package_moved(pTHX_ const HV *stash)
+{
+ register XPVHV* xhv;
+ register HE *entry;
+ I32 riter = -1;
+
+ PERL_ARGS_ASSERT_MRO_PACKAGE_MOVED;
+
+ mro_isa_changed_in((HV *)stash);
+
+ if(!HvARRAY(stash)) return;
+
+ /* This is partly based on code in hv_iternext_flags. We are not call-
+ ing that here, as we want to avoid resetting the hash iterator. */
+
+ xhv = (XPVHV*)SvANY(stash);
+
+ /* Skip the entire loop if the hash is empty. */
+ if (HvUSEDKEYS(stash)) {
+ while (++riter <= (I32)xhv->xhv_max) {
+ entry = (HvARRAY(stash))[riter];
+
+ /* Iterate through the entries in this list */
+ for(; entry; entry = HeNEXT(entry)) {
+ const char* key;
+ I32 len;
+
+ /* If this entry is not a glob, ignore it.
+ Try the next. */
+ if (!isGV(HeVAL(entry))) continue;
+
+ key = hv_iterkey(entry, &len);
+ if(len > 1 && key[len-2] == ':' && key[len-1] == ':') {
+ const HV * const stash = GvHV(HeVAL(entry));
+ if(stash && HvNAME(stash)) mro_package_moved(stash);
+ }
+ }
+ }
+ }
+}
+
+/*
=for apidoc mro_method_changed_in
Invalidates method caching on any child classes