summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-10-09 22:29:19 -0700
committerFather Chrysostomos <sprout@cpan.org>2010-10-09 23:07:09 -0700
commit3e79609f389ec31f364ad27e763e7e5f2ebc8d1e (patch)
tree4790cdc103e047ffaa8031b4a5b03bf7d482015e /sv.c
parent3e6edce2ec5de0a7a3597d5f5a127bb974b33ca8 (diff)
downloadperl-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.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/sv.c b/sv.c
index c651eb0c24..abb4f32b0a 100644
--- a/sv.c
+++ b/sv.c
@@ -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);
+ }
}
}
}