diff options
author | Father Chrysostomos <sprout@cpan.org> | 2010-10-09 22:29:19 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2010-10-09 23:07:09 -0700 |
commit | 3e79609f389ec31f364ad27e763e7e5f2ebc8d1e (patch) | |
tree | 4790cdc103e047ffaa8031b4a5b03bf7d482015e /sv.c | |
parent | 3e6edce2ec5de0a7a3597d5f5a127bb974b33ca8 (diff) | |
download | perl-3e79609f389ec31f364ad27e763e7e5f2ebc8d1e.tar.gz |
Make more ways to move packages around reset isa caches
This makes string-to-glob assignment and hashref-to-glob assignment
reset isa caches by calling mro_package_moved, if the glob’s name
ends with ::.
Related to [perl #75176].
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 28 |
1 files changed, 27 insertions, 1 deletions
@@ -3772,7 +3772,15 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr) && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) { GvFLAGS(dstr) |= import_flag; } - if (stype == SVt_PVAV && strEQ(GvNAME((GV*)dstr), "ISA")) { + if (stype == SVt_PVHV) { + const char * const name = GvNAME((GV*)dstr); + const STRLEN len = GvNAMELEN(dstr); + if (len > 1 && name[len-2] == ':' && name[len-1] == ':') { + if(HvNAME(dref)) mro_package_moved((HV *)dref); + if(HvNAME(sref)) mro_package_moved((HV *)sref); + } + } + else if (stype == SVt_PVAV && strEQ(GvNAME((GV*)dstr), "ISA")) { sv_magic(sref, dstr, PERL_MAGIC_isa, NULL, 0); mro_isa_changed_in(GvSTASH(dstr)); } @@ -4016,9 +4024,27 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags) else { GV *gv = gv_fetchsv(sstr, GV_ADD, SVt_PVGV); if (dstr != (const SV *)gv) { + const char * const name = GvNAME((const GV *)dstr); + const STRLEN len = GvNAMELEN(dstr); + HV *old_stash = NULL; + bool reset_isa = FALSE; + if (len > 1 && name[len-2] == ':' && name[len-1] == ':') { + /* Set aside the old stash, so we can reset isa caches + on its subclasses. */ + old_stash = GvHV(dstr); + reset_isa = TRUE; + } + if (GvGP(dstr)) gp_free(MUTABLE_GV(dstr)); GvGP(dstr) = gp_ref(GvGP(gv)); + + if (reset_isa) { + const HV * const stash = GvHV(dstr); + if(stash && HvNAME(stash)) mro_package_moved(stash); + if(old_stash && HvNAME(old_stash)) + mro_package_moved(old_stash); + } } } } |