This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
In Perl_pad_new(), allocate a 2 element array for padlist.
[perl5.git] / mro.c
diff --git a/mro.c b/mro.c
index 955ef90..1aac225 100644 (file)
--- a/mro.c
+++ b/mro.c
@@ -443,6 +443,20 @@ by the C<setisa> magic, should not need to invoke directly.
 
 =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)
 {
@@ -467,16 +481,7 @@ 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);
@@ -533,16 +538,7 @@ Perl_mro_isa_changed_in(pTHX_ HV* stash)
 
             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)
@@ -748,7 +744,7 @@ Perl_mro_package_moved(pTHX_ HV * const stash, HV * const oldstash,
        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(
@@ -756,28 +752,6 @@ Perl_mro_package_moved(pTHX_ HV * const stash, HV * const oldstash,
      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);
@@ -860,6 +834,7 @@ S_mro_gather_and_rename(pTHX_ HV * const stashes, HV * const seen_stashes,
            : &PL_sv_yes,
           0
          );
+       CLEAR_LINEAR(meta);
 
        /* Update the effective name. */
        if(HvENAME_get(oldstash)) {
@@ -923,6 +898,7 @@ S_mro_gather_and_rename(pTHX_ HV * const stashes, HV * const seen_stashes,
                    : &PL_sv_yes,
                   0
                  );
+               CLEAR_LINEAR(meta);
            }
        }
     }
@@ -957,6 +933,7 @@ S_mro_gather_and_rename(pTHX_ HV * const stashes, HV * const seen_stashes,
                : &PL_sv_yes,
               0
              );
+           CLEAR_LINEAR(meta);
         }
     }