=cut
*/
+
+/* Macro to avoid repeating the code five times. */
+#define CLEAR_LINEAR(mEta) \
+ 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) { \
+ /* Only the current MRO is stored, so this owns the data. */ \
+ SvREFCNT_dec(mEta->mro_linear_current); \
+ mEta->mro_linear_current = NULL; \
+ }
+
void
Perl_mro_isa_changed_in(pTHX_ HV* 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) {
- /* Only the current MRO is stored, so this owns the data. */
- SvREFCNT_dec(meta->mro_linear_current);
- meta->mro_linear_current = NULL;
- }
+ CLEAR_LINEAR(meta);
if (meta->isa) {
/* Steal it for our own purposes. */
isa = (HV *)sv_2mortal((SV *)meta->isa);
if(!revstash) continue;
revmeta = HvMROMETA(revstash);
- if (revmeta->mro_linear_all) {
- SvREFCNT_dec(MUTABLE_SV(revmeta->mro_linear_all));
- revmeta->mro_linear_all = NULL;
- /* This is just acting as a shortcut pointer. */
- revmeta->mro_linear_current = NULL;
- } else if (revmeta->mro_linear_current) {
- /* Only the current MRO is stored, so this owns the data. */
- SvREFCNT_dec(revmeta->mro_linear_current);
- revmeta->mro_linear_current = NULL;
- }
+ CLEAR_LINEAR(revmeta);
if(!is_universal)
revmeta->cache_gen++;
if(revmeta->mro_nextmethod)
as neither B nor B::B can be updated before the other, since they
will reset caches on foo, which will see either B or B::B with the
wrong name. The names must be set on *all* affected stashes before
- we do anything else.
+ we do anything else. (And linearisations must be cleared, too.)
*/
stashes = (HV *) sv_2mortal((SV *)newHV());
mro_gather_and_rename(
stash, oldstash, newname, newname_len
);
- /* Iterate through the stashes, wiping isa linearisations, but leaving
- the isa hash (which mro_isa_changed_in needs for adjusting the
- isarev hashes belonging to parent classes). */
- hv_iterinit(stashes);
- while((iter = hv_iternext(stashes))) {
- HV * const stash = *(HV **)HEK_KEY(HeKEY_hek(iter));
- if(HvENAME(stash)) {
- struct mro_meta* meta;
- 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) {
- /* Only the current MRO is stored, so this owns the data. */
- SvREFCNT_dec(meta->mro_linear_current);
- meta->mro_linear_current = NULL;
- }
- }
- }
-
/* Once the caches have been wiped on all the classes, call
mro_isa_changed_in on each. */
hv_iterinit(stashes);
: &PL_sv_yes,
0
);
+ CLEAR_LINEAR(meta);
/* Update the effective name. */
if(HvENAME_get(oldstash)) {
: &PL_sv_yes,
0
);
+ CLEAR_LINEAR(meta);
}
}
}
: &PL_sv_yes,
0
);
+ CLEAR_LINEAR(meta);
}
}