diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-08-17 23:58:47 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-08-17 23:58:47 -0700 |
commit | c716b3beb77406159d18fd52251821fee641f9fc (patch) | |
tree | b3304d82ae5b06d3fb56209a905aaf1554e33599 /sv.c | |
parent | be9260535f65befe9615312821574755a8d04344 (diff) | |
download | perl-c716b3beb77406159d18fd52251821fee641f9fc.tar.gz |
[perl #114864] Make UNIVERSAL::DESTROY changes invalidate caches
Commit 8c34e50d inadvertently caused DESTROY caches not to be
reset when UNIVERSAL::DESTROY changes. Normally, a change to
a method will cause mro_method_changed_in to be called on all
subclasses, but mro.c cheats for UNIVERSAL and just does
++PL_sub_generation. So clearing the DESTROY cache explicitly
in mro_method_changed_in is clearly not enough.
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 9 |
1 files changed, 8 insertions, 1 deletions
@@ -6565,14 +6565,21 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) { assert(SvTYPE(stash) == SVt_PVHV); if (HvNAME(stash)) { CV* destructor = NULL; + assert (SvOOK(stash)); if (!SvOBJECT(stash)) destructor = (CV *)SvSTASH(stash); - if (!destructor) { + if (!destructor || HvMROMETA(stash)->destroy_gen + != PL_sub_generation) + { GV * const gv = gv_fetchmeth_autoload(stash, "DESTROY", 7, 0); if (gv) destructor = GvCV(gv); if (!SvOBJECT(stash)) + { SvSTASH(stash) = destructor ? (HV *)destructor : ((HV *)0)+1; + HvAUX(stash)->xhv_mro_meta->destroy_gen = + PL_sub_generation; + } } assert(!destructor || destructor == ((CV *)0)+1 || SvTYPE(destructor) == SVt_PVCV); |