diff options
author | Father Chrysostomos <sprout@cpan.org> | 2010-10-11 10:10:06 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2010-10-11 10:10:06 -0700 |
commit | 6f86b615fa775fad6cc0c49f0615f38543ff5c19 (patch) | |
tree | 0e7d5f0d49cec273aac625aa606baf759f4d7a97 /mro.c | |
parent | 29912d932cee5589d4165d5eff62d0cc4f2c5195 (diff) | |
download | perl-6f86b615fa775fad6cc0c49f0615f38543ff5c19.tar.gz |
Allow mro_isa_changed_in to be called on nonexistent packages
This is necessary for an upcoming bug fix.
(For this bug:
@left::ISA = 'outer::inner';
@right::ISA = 'clone::inner';
*clone:: = \%outer::;
print left->isa('clone::inner'),"\n";
print right->isa('outer::inner'),"\n";
)
This commit actually replaces mro_isa_changed_in with
mro_isa_changed_in3. See the docs for it in the diff for mro.c.
Diffstat (limited to 'mro.c')
-rw-r--r-- | mro.c | 53 |
1 files changed, 36 insertions, 17 deletions
@@ -411,10 +411,22 @@ Takes the necessary steps (cache invalidations, mostly) when the @ISA of the given package has changed. Invoked by the C<setisa> magic, should not need to invoke directly. +=for apidoc mro_isa_changed_in3 + +Takes the necessary steps (cache invalidations, mostly) +when the @ISA of the given package has changed. Invoked +by the C<setisa> magic, should not need to invoke directly. + +The stash can be passed as the first argument, or its name and length as +the second and third (or both). If just the name is passed and the stash +does not exist, then only the subclasses' method and isa caches will be +invalidated. + =cut */ void -Perl_mro_isa_changed_in(pTHX_ HV* stash) +Perl_mro_isa_changed_in3(pTHX_ HV* stash, const char *stashname, + STRLEN stashname_len) { dVAR; HV* isarev; @@ -423,35 +435,39 @@ Perl_mro_isa_changed_in(pTHX_ HV* stash) SV** svp; I32 items; bool is_universal; - struct mro_meta * meta; - - const char * const stashname = HvNAME_get(stash); - const STRLEN stashname_len = HvNAMELEN_get(stash); + struct mro_meta * meta = NULL; - PERL_ARGS_ASSERT_MRO_ISA_CHANGED_IN; + if(!stashname && stash) { + stashname = HvNAME_get(stash); + stashname_len = HvNAMELEN_get(stash); + } + else if(!stash) + stash = gv_stashpvn(stashname, stashname_len, 0 /* don't add */); if(!stashname) Perl_croak(aTHX_ "Can't call mro_isa_changed_in() on anonymous symbol table"); - /* wipe out the cached linearizations for this stash */ - meta = HvMROMETA(stash); - if (meta->mro_linear_all) { + if(stash) { + /* wipe out the cached linearizations for this stash */ + meta = HvMROMETA(stash); + if (meta->mro_linear_all) { SvREFCNT_dec(MUTABLE_SV(meta->mro_linear_all)); meta->mro_linear_all = NULL; /* This is just acting as a shortcut pointer. */ meta->mro_linear_current = NULL; - } else if (meta->mro_linear_current) { + } else if (meta->mro_linear_current) { /* Only the current MRO is stored, so this owns the data. */ SvREFCNT_dec(meta->mro_linear_current); meta->mro_linear_current = NULL; - } - if (meta->isa) { + } + if (meta->isa) { SvREFCNT_dec(meta->isa); meta->isa = NULL; - } + } - /* Inc the package generation, since our @ISA changed */ - meta->pkg_gen++; + /* Inc the package generation, since our @ISA changed */ + meta->pkg_gen++; + } /* Wipe the global method cache if this package is UNIVERSAL or one of its parents */ @@ -465,12 +481,12 @@ Perl_mro_isa_changed_in(pTHX_ HV* stash) is_universal = TRUE; } else { /* Wipe the local method cache otherwise */ - meta->cache_gen++; + if(meta) meta->cache_gen++; is_universal = FALSE; } /* wipe next::method cache too */ - if(meta->mro_nextmethod) hv_clear(meta->mro_nextmethod); + if(meta && meta->mro_nextmethod) hv_clear(meta->mro_nextmethod); /* Iterate the isarev (classes that are our children), wiping out their linearization, method and isa caches */ @@ -511,6 +527,9 @@ Perl_mro_isa_changed_in(pTHX_ HV* stash) 3) Add everything from our isarev to their isarev */ + /* This only applies if the stash exists. */ + if(!stash) return; + /* We're starting at the 2nd element, skipping ourselves here */ linear_mro = mro_get_linear_isa(stash); svp = AvARRAY(linear_mro) + 1; |