summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Hay <steve.m.hay@googlemail.com>2016-04-08 22:47:20 +0100
committerSteve Hay <steve.m.hay@googlemail.com>2016-04-08 22:47:20 +0100
commit2ae6b218aa4e7c8d9566ef6a64f131d1b56581c4 (patch)
treed05351efad981032baae8110ca0d5fcc8b3f528b
parent59e4a1347f3bc090b98a30385cf375565b6a924f (diff)
downloadperl-2ae6b218aa4e7c8d9566ef6a64f131d1b56581c4.tar.gz
Revert "[perl #126410] keep the DESTROY cache in mro_meta"
This reverts commit 971809a61a634661b679cfedb722bf989b33d0d5.
-rw-r--r--ext/B/t/sv_stash.t1
-rw-r--r--hv.h1
-rw-r--r--mro_core.c14
-rw-r--r--sv.c34
4 files changed, 20 insertions, 30 deletions
diff --git a/ext/B/t/sv_stash.t b/ext/B/t/sv_stash.t
index e9abf4d55d..eaaabcf8fe 100644
--- a/ext/B/t/sv_stash.t
+++ b/ext/B/t/sv_stash.t
@@ -14,6 +14,7 @@ plan 1;
# RT #126410 = used to coredump when doing SvSTASH on %version::
TODO: {
+ local $TODO = 'Broken since c07f9fb2c7 - revert of a revert: slowed down detruction with no DESTROY';
fresh_perl_is(
'use B; version->new("v5.22.0"); $s = B::svref_2object(\%version::); $s->SvSTASH; print "ok\n"',
"ok\n", { stderr => 1 }, 'RT #126410 - SvSTASH against %version::'
diff --git a/hv.h b/hv.h
index 1d873f4e2e..9533af58f2 100644
--- a/hv.h
+++ b/hv.h
@@ -82,7 +82,6 @@ struct mro_meta {
const struct mro_alg *mro_which; /* which mro alg is in use? */
HV *isa; /* Everything this class @ISA */
HV *super; /* SUPER method cache */
- CV *destroy; /* DESTROY method if destroy_gen non-zero */
U32 destroy_gen; /* Generation number of DESTROY cache */
};
diff --git a/mro_core.c b/mro_core.c
index e15d47fea3..25d30d9067 100644
--- a/mro_core.c
+++ b/mro_core.c
@@ -191,10 +191,6 @@ Perl_mro_meta_dup(pTHX_ struct mro_meta* smeta, CLONE_PARAMS* param)
newmeta->super = NULL;
- /* clear the destructor cache */
- newmeta->destroy = NULL;
- newmeta->destroy_gen = 0;
-
return newmeta;
}
@@ -542,8 +538,8 @@ Perl_mro_isa_changed_in(pTHX_ HV* stash)
/* pessimise derefs for now. Will get recalculated by Gv_AMupdate() */
HvAUX(stash)->xhv_aux_flags &= ~HvAUXf_NO_DEREF;
- /* DESTROY can be cached in meta. */
- meta->destroy_gen = 0;
+ /* DESTROY can be cached in SvSTASH. */
+ if (!SvOBJECT(stash)) SvSTASH(stash) = NULL;
/* Iterate the isarev (classes that are our children),
wiping out their linearization, method and isa caches
@@ -1324,8 +1320,8 @@ Perl_mro_method_changed_in(pTHX_ HV *stash)
/* Inc the package generation, since a local method changed */
HvMROMETA(stash)->pkg_gen++;
- /* DESTROY can be cached in meta */
- HvMROMETA(stash)->destroy_gen = 0;
+ /* DESTROY can be cached in SvSTASH. */
+ if (!SvOBJECT(stash)) SvSTASH(stash) = NULL;
/* If stash is UNIVERSAL, or one of UNIVERSAL's parents,
invalidate all method caches globally */
@@ -1350,7 +1346,7 @@ Perl_mro_method_changed_in(pTHX_ HV *stash)
mrometa->cache_gen++;
if(mrometa->mro_nextmethod)
hv_clear(mrometa->mro_nextmethod);
- mrometa->destroy_gen = 0;
+ if (!SvOBJECT(revstash)) SvSTASH(revstash) = NULL;
}
}
diff --git a/sv.c b/sv.c
index 4d80d6d775..263d27bedc 100644
--- a/sv.c
+++ b/sv.c
@@ -6890,31 +6890,25 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
assert(SvTYPE(stash) == SVt_PVHV);
if (HvNAME(stash)) {
CV* destructor = NULL;
- struct mro_meta *meta;
assert (SvOOK(stash));
-
- DEBUG_o( Perl_deb(aTHX_ "Looking for DESTROY method for %s\n",
- HvNAME(stash)) );
-
- /* don't make this an initialization above the assert, since it needs
- an AUX structure */
- meta = HvMROMETA(stash);
- if (meta->destroy_gen && meta->destroy_gen == PL_sub_generation) {
- destructor = meta->destroy;
- DEBUG_o( Perl_deb(aTHX_ "Using cached DESTROY method %p for %s\n",
- (void *)destructor, HvNAME(stash)) );
- }
- else {
+ if (!SvOBJECT(stash)) destructor = (CV *)SvSTASH(stash);
+ if (!destructor || HvMROMETA(stash)->destroy_gen
+ != PL_sub_generation)
+ {
GV * const gv =
gv_fetchmeth_autoload(stash, "DESTROY", 7, 0);
if (gv) destructor = GvCV(gv);
- meta->destroy_gen = PL_sub_generation;
- meta->destroy = destructor;
- DEBUG_o( Perl_deb(aTHX_ "Set cached DESTROY method %p for %s\n",
- (void *)destructor, HvNAME(stash)) );
+ if (!SvOBJECT(stash))
+ {
+ SvSTASH(stash) =
+ destructor ? (HV *)destructor : ((HV *)0)+1;
+ HvAUX(stash)->xhv_mro_meta->destroy_gen =
+ PL_sub_generation;
+ }
}
- assert(!destructor || SvTYPE(destructor) == SVt_PVCV);
- if (destructor
+ assert(!destructor || destructor == ((CV *)0)+1
+ || SvTYPE(destructor) == SVt_PVCV);
+ if (destructor && destructor != ((CV *)0)+1
/* A constant subroutine can have no side effects, so
don't bother calling it. */
&& !CvCONST(destructor)