This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Older versions of windres interpret "-I" as the input format,
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index bfc9ee7..6f526b2 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -104,10 +104,6 @@ At the time of very final cleanup, sv_free_arenas() is called from
 perl_destruct() to physically free all the arenas allocated since the
 start of the interpreter.
 
-Manipulation of any of the PL_*root pointers is protected by enclosing
-LOCK_SV_MUTEX; ... UNLOCK_SV_MUTEX calls which should Do the Right Thing
-if threads are enabled.
-
 The function visit() scans the SV arenas list, and calls a specified
 function for each SV it finds which is still live - ie which has an SvTYPE
 other than all 1's, and a non-zero SvREFCNT. visit() is used by the
@@ -157,17 +153,12 @@ Public API:
  * "A time to plant, and a time to uproot what was planted..."
  */
 
-/*
- * nice_chunk and nice_chunk size need to be set
- * and queried under the protection of sv_mutex
- */
 void
 Perl_offer_nice_chunk(pTHX_ void *chunk, U32 chunk_size)
 {
     dVAR;
     void *new_chunk;
     U32 new_chunk_size;
-    LOCK_SV_MUTEX;
     new_chunk = (void *)(chunk);
     new_chunk_size = (chunk_size);
     if (new_chunk_size > PL_nice_chunk_size) {
@@ -177,7 +168,6 @@ Perl_offer_nice_chunk(pTHX_ void *chunk, U32 chunk_size)
     } else {
        Safefree(chunk);
     }
-    UNLOCK_SV_MUTEX;
 }
 
 #ifdef DEBUG_LEAKING_SCALARS
@@ -209,7 +199,6 @@ Perl_offer_nice_chunk(pTHX_ void *chunk, U32 chunk_size)
        --PL_sv_count;                                  \
     } STMT_END
 
-/* sv_mutex must be held while calling uproot_SV() */
 #define uproot_SV(p) \
     STMT_START {                                       \
        (p) = PL_sv_root;                               \
@@ -220,7 +209,6 @@ Perl_offer_nice_chunk(pTHX_ void *chunk, U32 chunk_size)
 
 /* make some more SVs by adding another arena */
 
-/* sv_mutex must be held while calling more_sv() */
 STATIC SV*
 S_more_sv(pTHX)
 {
@@ -250,18 +238,16 @@ S_new_SV(pTHX)
 {
     SV* sv;
 
-    LOCK_SV_MUTEX;
     if (PL_sv_root)
        uproot_SV(sv);
     else
        sv = S_more_sv(aTHX);
-    UNLOCK_SV_MUTEX;
     SvANY(sv) = 0;
     SvREFCNT(sv) = 1;
     SvFLAGS(sv) = 0;
     sv->sv_debug_optype = PL_op ? PL_op->op_type : 0;
-    sv->sv_debug_line = (U16) ((PL_copline == NOLINE) ?
-        (PL_curcop ? CopLINE(PL_curcop) : 0) : PL_copline);
+    sv->sv_debug_line = (U16) ((PL_parser && PL_parser->copline == NOLINE) ?
+        (PL_curcop ? CopLINE(PL_curcop) : 0) : PL_parser->copline);
     sv->sv_debug_inpad = 0;
     sv->sv_debug_cloned = 0;
     sv->sv_debug_file = PL_curcop ? savepv(CopFILE(PL_curcop)): NULL;
@@ -273,12 +259,10 @@ S_new_SV(pTHX)
 #else
 #  define new_SV(p) \
     STMT_START {                                       \
-       LOCK_SV_MUTEX;                                  \
        if (PL_sv_root)                                 \
            uproot_SV(p);                               \
        else                                            \
            (p) = S_more_sv(aTHX);                      \
-       UNLOCK_SV_MUTEX;                                \
        SvANY(p) = 0;                                   \
        SvREFCNT(p) = 1;                                \
        SvFLAGS(p) = 0;                                 \
@@ -292,12 +276,10 @@ S_new_SV(pTHX)
 
 #define del_SV(p) \
     STMT_START {                                       \
-       LOCK_SV_MUTEX;                                  \
        if (DEBUG_D_TEST)                               \
            del_sv(p);                                  \
        else                                            \
            plant_SV(p);                                \
-       UNLOCK_SV_MUTEX;                                \
     } STMT_END
 
 STATIC void
@@ -443,7 +425,8 @@ static void
 do_clean_objs(pTHX_ SV *ref)
 {
     dVAR;
-    if (SvROK(ref)) {
+    assert (SvROK(ref));
+    {
        SV * const target = SvRV(ref);
        if (SvOBJECT(target)) {
            DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning object ref:\n "), sv_dump(ref)));
@@ -469,7 +452,9 @@ static void
 do_clean_named_objs(pTHX_ SV *sv)
 {
     dVAR;
-    if (SvTYPE(sv) == SVt_PVGV && isGV_with_GP(sv) && GvGP(sv)) {
+    assert(SvTYPE(sv) == SVt_PVGV);
+    assert(isGV_with_GP(sv));
+    if (GvGP(sv)) {
        if ((
 #ifdef PERL_DONT_CREATE_GVSV
             GvSV(sv) &&
@@ -504,7 +489,7 @@ Perl_sv_clean_objs(pTHX)
     visit(do_clean_objs, SVf_ROK, SVf_ROK);
 #ifndef DISABLE_DESTRUCTOR_KLUDGE
     /* some barnacles may yet remain, clinging to typeglobs */
-    visit(do_clean_named_objs, SVt_PVGV, SVTYPEMASK);
+    visit(do_clean_named_objs, SVt_PVGV|SVpgv_GP, SVTYPEMASK|SVp_POK|SVpgv_GP);
 #endif
     PL_in_clean_objs = FALSE;
 }
@@ -517,10 +502,6 @@ do_clean_all(pTHX_ SV *sv)
     dVAR;
     DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning loops: SV at 0x%"UVxf"\n", PTR2UV(sv)) ));
     SvFLAGS(sv) |= SVf_BREAK;
-    if (PL_comppad == (AV*)sv) {
-       PL_comppad = NULL;
-       PL_curpad = NULL;
-    }
     SvREFCNT_dec(sv);
 }
 
@@ -551,7 +532,7 @@ Perl_sv_clean_all(pTHX)
   arena_descs, each holding info for a single arena.  By separating
   the meta-info from the arena, we recover the 1st slot, formerly
   borrowed for list management.  The arena_set is about the size of an
-  arena, avoiding the needless malloc overhead of a naive linked-list
+  arena, avoiding the needless malloc overhead of a naive linked-list.
 
   The cost is 1 arena-set malloc per ~320 arena-mallocs, + the unused
   memory in the last arena-set (1/2 on average).  In trade, we get
@@ -562,10 +543,7 @@ Perl_sv_clean_all(pTHX)
 struct arena_desc {
     char       *arena;         /* the raw storage, allocated aligned */
     size_t      size;          /* its size ~4k typ */
-    int         unit_type;     /* useful for arena audits */
-    /* info for sv-heads (eventually)
-       int count, flags;
-    */
+    U32                misc;           /* type, and in future other things. */
 };
 
 struct arena_set;
@@ -579,8 +557,8 @@ struct arena_set;
 
 struct arena_set {
     struct arena_set* next;
-    int   set_size;            /* ie ARENAS_PER_SET */
-    int   curr;                        /* index of next available arena-desc */
+    unsigned int   set_size;   /* ie ARENAS_PER_SET */
+    unsigned int   curr;       /* index of next available arena-desc */
     struct arena_desc set[ARENAS_PER_SET];
 };
 
@@ -598,7 +576,7 @@ Perl_sv_free_arenas(pTHX)
     dVAR;
     SV* sva;
     SV* svanext;
-    int i;
+    unsigned int i;
 
     /* Free arenas here, but be careful about fake ones.  (We assume
        contiguity of the fake ones with the corresponding real ones.) */
@@ -613,21 +591,23 @@ Perl_sv_free_arenas(pTHX)
     }
 
     {
-       struct arena_set *next, *aroot = (struct arena_set*) PL_body_arenas;
-       
-       for (; aroot; aroot = next) {
-           const int max = aroot->curr;
-           for (i=0; i<max; i++) {
+       struct arena_set *aroot = (struct arena_set*) PL_body_arenas;
+
+       while (aroot) {
+           struct arena_set *current = aroot;
+           i = aroot->curr;
+           while (i--) {
                assert(aroot->set[i].arena);
                Safefree(aroot->set[i].arena);
            }
-           next = aroot->next;
-           Safefree(aroot);
+           aroot = aroot->next;
+           Safefree(current);
        }
     }
     PL_body_arenas = 0;
 
-    for (i=0; i<PERL_ARENA_ROOTS_SIZE; i++)
+    i = PERL_ARENA_ROOTS_SIZE;
+    while (i--)
        PL_body_roots[i] = 0;
 
     Safefree(PL_nice_chunk);
@@ -676,35 +656,38 @@ Perl_sv_free_arenas(pTHX)
    TBD: export properly for hv.c: S_more_he().
 */
 void*
-Perl_get_arena(pTHX_ int arena_size)
+Perl_get_arena(pTHX_ size_t arena_size, U32 misc)
 {
     dVAR;
     struct arena_desc* adesc;
-    struct arena_set *newroot, **aroot = (struct arena_set**) &PL_body_arenas;
-    int curr;
+    struct arena_set *aroot = (struct arena_set*) PL_body_arenas;
+    unsigned int curr;
 
     /* shouldnt need this
     if (!arena_size)   arena_size = PERL_ARENA_SIZE;
     */
 
     /* may need new arena-set to hold new arena */
-    if (!*aroot || (*aroot)->curr >= (*aroot)->set_size) {
+    if (!aroot || aroot->curr >= aroot->set_size) {
+       struct arena_set *newroot;
        Newxz(newroot, 1, struct arena_set);
        newroot->set_size = ARENAS_PER_SET;
-       newroot->next = *aroot;
-       *aroot = newroot;
-       DEBUG_m(PerlIO_printf(Perl_debug_log, "new arenaset %p\n", (void*)*aroot));
+       newroot->next = aroot;
+       aroot = newroot;
+       PL_body_arenas = (void *) newroot;
+       DEBUG_m(PerlIO_printf(Perl_debug_log, "new arenaset %p\n", (void*)aroot));
     }
 
     /* ok, now have arena-set with at least 1 empty/available arena-desc */
-    curr = (*aroot)->curr++;
-    adesc = &((*aroot)->set[curr]);
+    curr = aroot->curr++;
+    adesc = &(aroot->set[curr]);
     assert(!adesc->arena);
     
-    Newxz(adesc->arena, arena_size, char);
+    Newx(adesc->arena, arena_size, char);
     adesc->size = arena_size;
-    DEBUG_m(PerlIO_printf(Perl_debug_log, "arena %d added: %p size %d\n", 
-                         curr, (void*)adesc->arena, arena_size));
+    adesc->misc = misc;
+    DEBUG_m(PerlIO_printf(Perl_debug_log, "arena %d added: %p size %"UVuf"\n", 
+                         curr, (void*)adesc->arena, (UV)arena_size));
 
     return adesc->arena;
 }
@@ -715,10 +698,8 @@ Perl_get_arena(pTHX_ int arena_size)
 #define del_body(thing, root)                  \
     STMT_START {                               \
        void ** const thing_copy = (void **)thing;\
-       LOCK_SV_MUTEX;                          \
        *thing_copy = *root;                    \
        *root = (void*)thing_copy;              \
-       UNLOCK_SV_MUTEX;                        \
     } STMT_END
 
 /* 
@@ -943,13 +924,13 @@ static const struct body_details bodies_by_type[] = {
       copy_length(XPVAV, xmg_stash)
       - relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
       + relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
-      SVt_PVAV, TRUE, HADNV, HASARENA, FIT_ARENA(0, sizeof(xpvav_allocated)) },
+      SVt_PVAV, TRUE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpvav_allocated)) },
 
     { sizeof(xpvhv_allocated),
       copy_length(XPVHV, xmg_stash)
       - relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
       + relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
-      SVt_PVHV, TRUE, HADNV, HASARENA, FIT_ARENA(0, sizeof(xpvhv_allocated)) },
+      SVt_PVHV, TRUE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpvhv_allocated)) },
 
     /* 56 */
     { sizeof(xpvcv_allocated), sizeof(xpvcv_allocated),
@@ -1033,10 +1014,6 @@ static const struct body_details bodies_by_type[] = {
 #define new_NOARENAZ(details) \
        my_safecalloc((details)->body_size + (details)->offset)
 
-#if defined(DEBUGGING) && !defined(PERL_GLOBAL_STRUCT_PRIVATE)
-static bool done_sanity_check;
-#endif
-
 STATIC void *
 S_more_bodies (pTHX_ svtype sv_type)
 {
@@ -1046,10 +1023,9 @@ S_more_bodies (pTHX_ svtype sv_type)
     const size_t body_size = bdp->body_size;
     char *start;
     const char *end;
-
-    assert(bdp->arena_size);
-
 #if defined(DEBUGGING) && !defined(PERL_GLOBAL_STRUCT_PRIVATE)
+    static bool done_sanity_check;
+
     /* PERL_GLOBAL_STRUCT_PRIVATE cannot coexist with global
      * variables like done_sanity_check. */
     if (!done_sanity_check) {
@@ -1062,7 +1038,9 @@ S_more_bodies (pTHX_ svtype sv_type)
     }
 #endif
 
-    start = (char*) Perl_get_arena(aTHX_ bdp->arena_size);
+    assert(bdp->arena_size);
+
+    start = (char*) Perl_get_arena(aTHX_ bdp->arena_size, sv_type);
 
     end = start + bdp->arena_size - body_size;
 
@@ -1092,11 +1070,9 @@ S_more_bodies (pTHX_ svtype sv_type)
 #define new_body_inline(xpv, sv_type) \
     STMT_START { \
        void ** const r3wt = &PL_body_roots[sv_type]; \
-       LOCK_SV_MUTEX; \
        xpv = (PTR_TBL_ENT_t*) (*((void **)(r3wt))      \
          ? *((void **)(r3wt)) : more_bodies(sv_type)); \
        *(r3wt) = *(void**)(xpv); \
-       UNLOCK_SV_MUTEX; \
     } STMT_END
 
 #ifndef PURIFY
@@ -1340,7 +1316,8 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
         * NV slot, but the new one does, then we need to initialise the
         * freshly created NV slot with whatever the correct bit pattern is
         * for 0.0  */
-       if (old_type_details->zero_nv && !new_type_details->zero_nv)
+       if (old_type_details->zero_nv && !new_type_details->zero_nv
+           && !isGV_with_GP(sv))
            SvNV_set(sv, 0);
 #endif
 
@@ -2829,7 +2806,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
 Copies a stringified representation of the source SV into the
 destination SV.  Automatically performs any necessary mg_get and
 coercion of numeric values into strings.  Guaranteed to preserve
-UTF-8 flag even from overloaded objects.  Similar in nature to
+UTF8 flag even from overloaded objects.  Similar in nature to
 sv_2pv[_flags] but operates directly on an SV instead of just the
 string.  Mostly uses sv_2pv_flags to do its work, except when that
 would lose the UTF-8'ness of the PV.
@@ -3168,18 +3145,19 @@ copy-ish functions and macros use this underneath.
 static void
 S_glob_assign_glob(pTHX_ SV *dstr, SV *sstr, const int dtype)
 {
+    I32 method_changed = 0;
+
     if (dtype != SVt_PVGV) {
        const char * const name = GvNAME(sstr);
        const STRLEN len = GvNAMELEN(sstr);
-       /* don't upgrade SVt_PVLV: it can hold a glob */
-       if (dtype != SVt_PVLV) {
+       {
            if (dtype >= SVt_PV) {
                SvPV_free(dstr);
                SvPV_set(dstr, 0);
                SvLEN_set(dstr, 0);
                SvCUR_set(dstr, 0);
            }
-           sv_upgrade(dstr, SVt_PVGV);
+           SvUPGRADE(dstr, SVt_PVGV);
            (void)SvOK_off(dstr);
            /* FIXME - why are we doing this, then turning it off and on again
               below?  */
@@ -3198,6 +3176,25 @@ S_glob_assign_glob(pTHX_ SV *dstr, SV *sstr, const int dtype)
     }
 #endif
 
+    if(GvGP((GV*)sstr)) {
+        /* If source has method cache entry, clear it */
+        if(GvCVGEN(sstr)) {
+            SvREFCNT_dec(GvCV(sstr));
+            GvCV(sstr) = NULL;
+            GvCVGEN(sstr) = 0;
+        }
+        /* If source has a real method, then a method is
+           going to change */
+        else if(GvCV((GV*)sstr)) {
+            method_changed = 1;
+        }
+    }
+
+    /* If dest already had a real method, that's a change as well */
+    if(!method_changed && GvGP((GV*)dstr) && GvCVu((GV*)dstr)) {
+        method_changed = 1;
+    }
+
     gp_free((GV*)dstr);
     isGV_with_GP_off(dstr);
     (void)SvOK_off(dstr);
@@ -3212,6 +3209,7 @@ S_glob_assign_glob(pTHX_ SV *dstr, SV *sstr, const int dtype)
            GvIMPORTED_on(dstr);
        }
     GvMULTI_on(dstr);
+    if(method_changed) mro_method_changed_in(GvSTASH(dstr));
     return;
 }
 
@@ -3261,18 +3259,18 @@ S_glob_assign_ref(pTHX_ SV *dstr, SV *sstr) {
     common:
        if (intro) {
            if (stype == SVt_PVCV) {
-               if (GvCVGEN(dstr) && GvCV(dstr) != (CV*)sref) {
+               /*if (GvCVGEN(dstr) && (GvCV(dstr) != (CV*)sref || GvCVGEN(dstr))) {*/
+               if (GvCVGEN(dstr)) {
                    SvREFCNT_dec(GvCV(dstr));
                    GvCV(dstr) = NULL;
                    GvCVGEN(dstr) = 0; /* Switch off cacheness. */
-                   PL_sub_generation++;
                }
            }
            SAVEGENERICSV(*location);
        }
        else
            dref = *location;
-       if (stype == SVt_PVCV && *location != sref) {
+       if (stype == SVt_PVCV && (*location != sref || GvCVGEN(dstr))) {
            CV* const cv = (CV*)*location;
            if (cv) {
                if (!GvCVGEN((GV*)dstr) &&
@@ -3311,7 +3309,7 @@ S_glob_assign_ref(pTHX_ SV *dstr, SV *sstr) {
            }
            GvCVGEN(dstr) = 0; /* Switch off cacheness. */
            GvASSUMECV_on(dstr);
-           PL_sub_generation++;
+           if(GvSTASH(dstr)) mro_method_changed_in(GvSTASH(dstr)); /* sub foo { 1 } sub bar { 2 } *bar = \&foo */
        }
        *location = sref;
        if (import_flag && !(GvFLAGS(dstr) & import_flag)
@@ -3351,7 +3349,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
     stype = SvTYPE(sstr);
     dtype = SvTYPE(dstr);
 
-    SvAMAGIC_off(dstr);
+    (void)SvAMAGIC_off(dstr);
     if ( SvVOK(dstr) )
     {
        /* need to nuke the magic */
@@ -3458,6 +3456,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        break;
 
        /* case SVt_BIND: */
+    case SVt_PVLV:
     case SVt_PVGV:
        if (isGV_with_GP(sstr) && dtype <= SVt_PVGV) {
            glob_assign_glob(dstr, sstr, dtype);
@@ -3467,7 +3466,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        /*FALLTHROUGH*/
 
     case SVt_PVMG:
-    case SVt_PVLV:
        if (SvGMAGICAL(sstr) && (flags & SV_GMAGIC)) {
            mg_get(sstr);
            if (SvTYPE(sstr) != stype) {
@@ -3706,7 +3704,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            SvNV_set(dstr, SvNVX(sstr));
        }
        if (sflags & SVp_IOK) {
-           SvRELEASE_IVX(dstr);
+           SvOOK_off(dstr);
            SvIV_set(dstr, SvIVX(sstr));
            /* Must do this otherwise some other overloaded use of 0x80000000
               gets confused. I guess SVpbm_VALID */
@@ -4011,9 +4009,9 @@ Perl_sv_usepvn_flags(pTHX_ SV *sv, char *ptr, STRLEN len, U32 flags)
    (which it can do by means other than releasing copy-on-write Svs)
    or by changing the other copy-on-write SVs in the loop.  */
 STATIC void
-S_sv_release_COW(pTHX_ register SV *sv, const char *pvx, STRLEN len, SV *after)
+S_sv_release_COW(pTHX_ register SV *sv, const char *pvx, SV *after)
 {
-    if (len) { /* this SV was SvIsCOW_normal(sv) */
+    { /* this SV was SvIsCOW_normal(sv) */
          /* we need to find the SV pointing to us.  */
         SV *current = SV_COW_NEXT_SV(after);
 
@@ -4037,19 +4035,8 @@ S_sv_release_COW(pTHX_ register SV *sv, const char *pvx, STRLEN len, SV *after)
             /* Make the SV before us point to the SV after us.  */
             SV_COW_NEXT_SV_SET(current, after);
         }
-    } else {
-        unshare_hek(SvSHARED_HEK_FROM_PV(pvx));
     }
 }
-
-int
-Perl_sv_release_IVX(pTHX_ register SV *sv)
-{
-    if (SvIsCOW(sv))
-        sv_force_normal_flags(sv, 0);
-    SvOOK_off(sv);
-    return 0;
-}
 #endif
 /*
 =for apidoc sv_force_normal_flags
@@ -4078,7 +4065,11 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
            const char * const pvx = SvPVX_const(sv);
            const STRLEN len = SvLEN(sv);
            const STRLEN cur = SvCUR(sv);
-           SV * const next = SV_COW_NEXT_SV(sv);   /* next COW sv in the loop. */
+           /* next COW sv in the loop.  If len is 0 then this is a shared-hash
+              key scalar, so we mustn't attempt to call SV_COW_NEXT_SV(), as
+              we'll fail an assertion.  */
+           SV * const next = len ? SV_COW_NEXT_SV(sv) : 0;
+
             if (DEBUG_C_TEST) {
                 PerlIO_printf(Perl_debug_log,
                               "Copy on write: Force normal %ld\n",
@@ -4099,7 +4090,11 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
                 SvCUR_set(sv, cur);
                 *SvEND(sv) = '\0';
             }
-            sv_release_COW(sv, pvx, len, next);
+           if (len) {
+               sv_release_COW(sv, pvx, next);
+           } else {
+               unshare_hek(SvSHARED_HEK_FROM_PV(pvx));
+           }
             if (DEBUG_C_TEST) {
                 sv_dump(sv);
             }
@@ -4373,9 +4368,7 @@ Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, const MGVTBL *vtable,
     dVAR;
     MAGIC* mg;
 
-    if (SvTYPE(sv) < SVt_PVMG) {
-       SvUPGRADE(sv, SVt_PVMG);
-    }
+    SvUPGRADE(sv, SVt_PVMG);
     Newxz(mg, 1, MAGIC);
     mg->mg_moremagic = SvMAGIC(sv);
     SvMAGIC_set(sv, mg);
@@ -5054,6 +5047,7 @@ Perl_sv_clear(pTHX_ register SV *sv)
     const U32 type = SvTYPE(sv);
     const struct body_details *const sv_type_details
        = bodies_by_type + type;
+    HV *stash;
 
     assert(sv);
     assert(SvREFCNT(sv) == 0);
@@ -5149,6 +5143,10 @@ Perl_sv_clear(pTHX_ register SV *sv)
        hv_undef((HV*)sv);
        break;
     case SVt_PVAV:
+       if (PL_comppad == (AV*)sv) {
+           PL_comppad = NULL;
+           PL_curpad = NULL;
+       }
        av_undef((AV*)sv);
        break;
     case SVt_PVLV:
@@ -5159,17 +5157,23 @@ Perl_sv_clear(pTHX_ register SV *sv)
        }
        else if (LvTYPE(sv) != 't') /* unless tie: unrefcnted fake SV**  */
            SvREFCNT_dec(LvTARG(sv));
-       goto freescalar;
     case SVt_PVGV:
        if (isGV_with_GP(sv)) {
+            if(GvCVu((GV*)sv) && (stash = GvSTASH((GV*)sv)) && HvNAME_get(stash))
+                mro_method_changed_in(stash);
            gp_free((GV*)sv);
            if (GvNAME_HEK(sv))
                unshare_hek(GvNAME_HEK(sv));
-       /* If we're in a stash, we don't own a reference to it. However it does
-          have a back reference to us, which needs to be cleared.  */
-       if (!SvVALID(sv) && GvSTASH(sv))
-               sv_del_backref((SV*)GvSTASH(sv), sv);
-       }
+           /* If we're in a stash, we don't own a reference to it. However it does
+              have a back reference to us, which needs to be cleared.  */
+           if (!SvVALID(sv) && (stash = GvSTASH(sv)))
+                   sv_del_backref((SV*)stash, sv);
+       }
+       /* FIXME. There are probably more unreferenced pointers to SVs in the
+          interpreter struct that we should check and tidy in a similar
+          fashion to this:  */
+       if ((GV*)sv == PL_last_in_gv)
+           PL_last_in_gv = NULL;
     case SVt_PVMG:
     case SVt_PVNV:
     case SVt_PVIV:
@@ -5197,8 +5201,12 @@ Perl_sv_clear(pTHX_ register SV *sv)
                     PerlIO_printf(Perl_debug_log, "Copy on write: clear\n");
                     sv_dump(sv);
                 }
-                sv_release_COW(sv, SvPVX_const(sv), SvLEN(sv),
-                              SV_COW_NEXT_SV(sv));
+               if (SvLEN(sv)) {
+                   sv_release_COW(sv, SvPVX_const(sv), SV_COW_NEXT_SV(sv));
+               } else {
+                   unshare_hek(SvSHARED_HEK_FROM_PV(SvPVX_const(sv)));
+               }
+
                 /* And drop it here.  */
                 SvFAKE_off(sv);
             } else if (SvLEN(sv)) {
@@ -5283,6 +5291,10 @@ Perl_sv_free(pTHX_ SV *sv)
                         pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE);
 #ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
            Perl_dump_sv_child(aTHX_ sv);
+#else
+  #ifdef DEBUG_LEAKING_SCALARS
+       sv_dump(sv);
+  #endif
 #endif
        }
        return;
@@ -7189,6 +7201,25 @@ Perl_newSVuv(pTHX_ UV u)
 }
 
 /*
+=for apidoc newSV_type
+
+Creates a new SV, of the type specificied.  The reference count for the new SV
+is set to 1.
+
+=cut
+*/
+
+SV *
+Perl_newSV_type(pTHX_ svtype type)
+{
+    register SV *sv;
+
+    new_SV(sv);
+    sv_upgrade(sv, type);
+    return sv;
+}
+
+/*
 =for apidoc newRV_noinc
 
 Creates an RV wrapper for an SV.  The reference count for the original
@@ -7201,10 +7232,7 @@ SV *
 Perl_newRV_noinc(pTHX_ SV *tmpRef)
 {
     dVAR;
-    register SV *sv;
-
-    new_SV(sv);
-    sv_upgrade(sv, SVt_RV);
+    register SV *sv = newSV_type(SVt_RV);
     SvTEMP_off(tmpRef);
     SvRV_set(sv, tmpRef);
     SvROK_on(sv);
@@ -7273,10 +7301,17 @@ Perl_sv_reset(pTHX_ register const char *s, HV *stash)
     if (!*s) {         /* reset ?? searches */
        MAGIC * const mg = mg_find((SV *)stash, PERL_MAGIC_symtab);
        if (mg) {
-           PMOP *pm = (PMOP *) mg->mg_obj;
-           while (pm) {
-               pm->op_pmdynflags &= ~PMdf_USED;
-               pm = pm->op_pmnext;
+           const U32 count = mg->mg_len / sizeof(PMOP**);
+           PMOP **pmp = (PMOP**) mg->mg_ptr;
+           PMOP *const *const end = pmp + count;
+
+           while (pmp < end) {
+#ifdef USE_ITHREADS
+                SvREADONLY_off(PL_regex_pad[(*pmp)->op_pmoffset]);
+#else
+               (*pmp)->op_pmflags &= ~PMf_USED;
+#endif
+               ++pmp;
            }
        }
        return;
@@ -7743,7 +7778,7 @@ Perl_newSVrv(pTHX_ SV *rv, const char *classname)
     new_SV(sv);
 
     SV_CHECK_THINKFIRST_COW_DROP(rv);
-    SvAMAGIC_off(rv);
+    (void)SvAMAGIC_off(rv);
 
     if (SvTYPE(rv) >= SVt_PVMG) {
        const U32 refcnt = SvREFCNT(rv);
@@ -7768,7 +7803,7 @@ Perl_newSVrv(pTHX_ SV *rv, const char *classname)
     SvROK_on(rv);
 
     if (classname) {
-       HV* const stash = gv_stashpv(classname, TRUE);
+       HV* const stash = gv_stashpv(classname, GV_ADD);
        (void)sv_bless(rv, stash);
     }
     return sv;
@@ -7920,7 +7955,7 @@ Perl_sv_bless(pTHX_ SV *sv, HV *stash)
     if (Gv_AMG(stash))
        SvAMAGIC_on(sv);
     else
-       SvAMAGIC_off(sv);
+       (void)SvAMAGIC_off(sv);
 
     if(SvSMAGICAL(tmpRef))
         if(mg_find(tmpRef, PERL_MAGIC_ext) || mg_find(tmpRef, PERL_MAGIC_uvar))
@@ -7939,6 +7974,7 @@ S_sv_unglob(pTHX_ SV *sv)
 {
     dVAR;
     void *xpvmg;
+    HV *stash;
     SV * const temp = sv_newmortal();
 
     assert(SvTYPE(sv) == SVt_PVGV);
@@ -7946,6 +7982,8 @@ S_sv_unglob(pTHX_ SV *sv)
     gv_efullname3(temp, (GV *) sv, "*");
 
     if (GvGP(sv)) {
+        if(GvCVu((GV*)sv) && (stash = GvSTASH((GV*)sv)) && HvNAME_get(stash))
+            mro_method_changed_in(stash);
        gp_free((GV*)sv);
     }
     if (GvSTASH(sv)) {
@@ -8568,7 +8606,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                        has_precis = TRUE;
                    }
                    argsv = (SV*)va_arg(*args, void*);
-                   eptr = SvPVx_const(argsv, elen);
+                   eptr = SvPV_const(argsv, elen);
                    if (DO_UTF8(argsv))
                        is_utf8 = TRUE;
                    goto string;
@@ -8700,12 +8738,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                        goto unknown;
                    }
                    vecsv = sv_newmortal();
-                   /* scan_vstring is expected to be called during
-                    * tokenization, so we need to fake up the end
-                    * of the buffer for it
-                    */
-                   PL_bufend = version + veclen;
-                   scan_vstring(version, vecsv);
+                   scan_vstring(version, version + veclen, vecsv);
                    vecstr = (U8*)SvPV_const(vecsv, veclen);
                    vec_utf8 = DO_UTF8(vecsv);
                    Safefree(version);
@@ -8832,7 +8865,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        case 'c':
            if (vectorize)
                goto unknown;
-           uv = (args) ? va_arg(*args, int) : SvIVx(argsv);
+           uv = (args) ? va_arg(*args, int) : SvIV(argsv);
            if ((uv > 255 ||
                 (!UNI_IS_INVARIANT(uv) && SvUTF8(sv)))
                && !IN_BYTES) {
@@ -8866,7 +8899,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                }
            }
            else {
-               eptr = SvPVx_const(argsv, elen);
+               eptr = SvPV_const(argsv, elen);
                if (DO_UTF8(argsv)) {
                    I32 old_precis = precis;
                    if (has_precis && precis < elen) {
@@ -8938,7 +8971,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                }
            }
            else {
-               IV tiv = SvIVx(argsv); /* work around GCC bug #13488 */
+               IV tiv = SvIV(argsv); /* work around GCC bug #13488 */
                switch (intsize) {
                case 'h':       iv = (short)tiv; break;
                case 'l':       iv = (long)tiv; break;
@@ -9023,7 +9056,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                }
            }
            else {
-               UV tuv = SvUVx(argsv); /* work around GCC bug #13488 */
+               UV tuv = SvUV(argsv); /* work around GCC bug #13488 */
                switch (intsize) {
                case 'h':       uv = (unsigned short)tuv; break;
                case 'l':       uv = (unsigned long)tuv; break;
@@ -9145,7 +9178,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 #else
                    va_arg(*args, double)
 #endif
-               : SvNVx(argsv);
+               : SvNV(argsv);
 
            need = 0;
            if (c != 'e' && c != 'E') {
@@ -9538,6 +9571,40 @@ Perl_parser_dup(pTHX_ const yy_parser *proto, CLONE_PARAMS* param)
     parser->pending_ident = proto->pending_ident;
     parser->preambled  = proto->preambled;
     parser->sublex_info        = proto->sublex_info; /* XXX not quite right */
+    parser->linestr    = sv_dup_inc(proto->linestr, param);
+    parser->expect     = proto->expect;
+    parser->copline    = proto->copline;
+    parser->last_lop_op        = proto->last_lop_op;
+    parser->lex_state  = proto->lex_state;
+    parser->rsfp       = fp_dup(proto->rsfp, '<', param);
+    /* rsfp_filters entries have fake IoDIRP() */
+    parser->rsfp_filters= av_dup_inc(proto->rsfp_filters, param);
+    parser->in_my      = proto->in_my;
+    parser->in_my_stash        = hv_dup(proto->in_my_stash, param);
+
+
+    parser->linestr    = sv_dup_inc(proto->linestr, param);
+
+    {
+       char * const ols = SvPVX(proto->linestr);
+       char * const ls  = SvPVX(parser->linestr);
+
+       parser->bufptr      = ls + (proto->bufptr >= ols ?
+                                   proto->bufptr -  ols : 0);
+       parser->oldbufptr   = ls + (proto->oldbufptr >= ols ?
+                                   proto->oldbufptr -  ols : 0);
+       parser->oldoldbufptr= ls + (proto->oldoldbufptr >= ols ?
+                                   proto->oldoldbufptr -  ols : 0);
+       parser->linestart   = ls + (proto->linestart >= ols ?
+                                   proto->linestart -  ols : 0);
+       parser->last_uni    = ls + (proto->last_uni >= ols ?
+                                   proto->last_uni -  ols : 0);
+       parser->last_lop    = ls + (proto->last_lop >= ols ?
+                                   proto->last_lop -  ols : 0);
+
+       parser->bufend      = ls + SvCUR(parser->linestr);
+    }
+
 
 #ifdef PERL_MAD
     parser->endwhite   = proto->endwhite;
@@ -9552,6 +9619,13 @@ Perl_parser_dup(pTHX_ const yy_parser *proto, CLONE_PARAMS* param)
     parser->thisstuff  = proto->thisstuff;
     parser->thistoken  = proto->thistoken;
     parser->thiswhite  = proto->thiswhite;
+
+    Copy(proto->nexttoke, parser->nexttoke, 5, NEXTTOKE);
+    parser->curforce   = proto->curforce;
+#else
+    Copy(proto->nextval, parser->nextval, 5, YYSTYPE);
+    Copy(proto->nexttype, parser->nexttype, 5, I32);
+    parser->nexttoke   = proto->nexttoke;
 #endif
     return parser;
 }
@@ -9658,9 +9732,6 @@ Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS* param)
               1.  */
            nmg->mg_obj = SvREFCNT_inc(av_dup_inc((AV*) mg->mg_obj, param));
        }
-       else if (mg->mg_type == PERL_MAGIC_symtab) {
-           nmg->mg_obj = mg->mg_obj;
-       }
        else {
            nmg->mg_obj = (mg->mg_flags & MGf_REFCOUNTED)
                              ? sv_dup_inc(mg->mg_obj, param)
@@ -10046,20 +10117,16 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                    LvTARG(dstr) = (SV*)he_dup((HE*)LvTARG(dstr), 0, param);
                else
                    LvTARG(dstr) = sv_dup_inc(LvTARG(dstr), param);
-               break;
            case SVt_PVGV:
                if(isGV_with_GP(sstr)) {
                    if (GvNAME_HEK(dstr))
                        GvNAME_HEK(dstr) = hek_dup(GvNAME_HEK(dstr), param);
-               }
-
-               /* Don't call sv_add_backref here as it's going to be created
-                  as part of the magic cloning of the symbol table.  */
-               if(!SvVALID(dstr))
-                   GvSTASH(dstr) = hv_dup(GvSTASH(dstr), param);
-               if(isGV_with_GP(sstr)) {
+                   /* Don't call sv_add_backref here as it's going to be
+                      created as part of the magic cloning of the symbol
+                      table.  */
                    /* Danger Will Robinson - GvGP(dstr) isn't initialised
                       at the point of this comment.  */
+                   GvSTASH(dstr) = hv_dup(GvSTASH(dstr), param);
                    GvGP(dstr)  = gp_dup(GvGP(sstr), param);
                    (void)GpREFCNT_inc(GvGP(dstr));
                } else
@@ -10071,7 +10138,7 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                    IoOFP(dstr) = IoIFP(dstr);
                else
                    IoOFP(dstr) = fp_dup(IoOFP(dstr), IoTYPE(dstr), param);
-               /* PL_rsfp_filters entries have fake IoDIRP() */
+               /* PL_parser->rsfp_filters entries have fake IoDIRP() */
                if(IoFLAGS(dstr) & IOf_FAKE_DIRP) {
                    /* I have no idea why fake dirp (rsfps)
                       should be treated differently but otherwise
@@ -10159,6 +10226,11 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                                ? (AV*) SvREFCNT_inc(
                                        sv_dup((SV*)saux->xhv_backreferences, param))
                                : 0;
+
+                        daux->xhv_mro_meta = saux->xhv_mro_meta
+                            ? mro_meta_dup(saux->xhv_mro_meta, param)
+                            : 0;
+
                        /* Record stashes for possible cloning in Perl_clone(). */
                        if (hvname)
                            av_push(param->stashes, dstr);
@@ -10512,7 +10584,7 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
                    TOPPTR(nss,ix) = ptr;
                    o = (OP*)ptr;
                    OP_REFCNT_LOCK;
-                   OpREFCNT_inc(o);
+                   (void) OpREFCNT_inc(o);
                    OP_REFCNT_UNLOCK;
                    break;
                default:
@@ -10626,10 +10698,9 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
                    = pv_dup(old_state->re_state_reginput);
                new_state->re_state_regeol
                    = pv_dup(old_state->re_state_regeol);
-               new_state->re_state_regstartp
-                   = (I32*) any_dup(old_state->re_state_regstartp, proto_perl);
-               new_state->re_state_regendp
-                   = (I32*) any_dup(old_state->re_state_regendp, proto_perl);
+               new_state->re_state_regoffs
+                   = (regexp_paren_pair*)
+                       any_dup(old_state->re_state_regoffs, proto_perl);
                new_state->re_state_reglastparen
                    = (U32*) any_dup(old_state->re_state_reglastparen, 
                              proto_perl);
@@ -10676,7 +10747,7 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
            break;
        case SAVEt_PARSER:
            ptr = POPPTR(ss,ix);
-           TOPPTR(nss,ix) = parser_dup(ptr, param);
+           TOPPTR(nss,ix) = parser_dup((const yy_parser*)ptr, param);
            break;
        default:
            Perl_croak(aTHX_
@@ -10734,7 +10805,7 @@ without it we only clone the data and zero the stacks,
 with it we copy the stacks and the new perl interpreter is
 ready to run at the exact same point as the previous one.
 The pseudo-fork code uses COPY_STACKS while the
-threads->new doesn't.
+threads->create doesn't.
 
 CLONEf_KEEP_PTR_TABLE
 perl_clone keeps a ptr_table with the pointer of the old
@@ -10939,6 +11010,10 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        HINTS_REFCNT_UNLOCK;
     }
     PL_curcop          = (COP*)any_dup(proto_perl->Tcurcop, proto_perl);
+#ifdef PERL_DEBUG_READONLY_OPS
+    PL_slabs = NULL;
+    PL_slab_count = 0;
+#endif
 
     /* pseudo environmental stuff */
     PL_origargc                = proto_perl->Iorigargc;
@@ -11074,6 +11149,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_initav          = av_dup_inc(proto_perl->Iinitav, param);
 
     PL_sub_generation  = proto_perl->Isub_generation;
+    PL_isarev          = hv_dup_inc(proto_perl->Iisarev, param);
+    PL_delayedisa      = hv_dup_inc(proto_perl->Tdelayedisa, param);
 
     /* funky return mechanisms */
     PL_forkprocess     = proto_perl->Iforkprocess;
@@ -11100,7 +11177,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* runtime control stuff */
     PL_curcopdb                = (COP*)any_dup(proto_perl->Icurcopdb, proto_perl);
-    PL_copline         = proto_perl->Icopline;
 
     PL_filemode                = proto_perl->Ifilemode;
     PL_lastfd          = proto_perl->Ilastfd;
@@ -11129,14 +11205,14 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        Newx(PL_my_cxt_list, PL_my_cxt_size, void *);
        Copy(proto_perl->Imy_cxt_list, PL_my_cxt_list, PL_my_cxt_size, void *);
 #ifdef PERL_GLOBAL_STRUCT_PRIVATE
-       Newx(PL_my_cxt_keys, PL_my_cxt_size, char *);
+       Newx(PL_my_cxt_keys, PL_my_cxt_size, const char *);
        Copy(proto_perl->Imy_cxt_keys, PL_my_cxt_keys, PL_my_cxt_size, char *);
 #endif
     }
     else {
        PL_my_cxt_list  = (void**)NULL;
 #ifdef PERL_GLOBAL_STRUCT_PRIVATE
-       PL_my_cxt_keys  = (void**)NULL;
+       PL_my_cxt_keys  = (const char**)NULL;
 #endif
     }
     PL_modglobal       = hv_dup_inc(proto_perl->Imodglobal, param);
@@ -11144,9 +11220,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_custom_op_descs  = hv_dup_inc(proto_perl->Icustom_op_descs,param);
 
     PL_profiledata     = NULL;
-    PL_rsfp            = fp_dup(proto_perl->Irsfp, '<', param);
-    /* PL_rsfp_filters entries have fake IoDIRP() */
-    PL_rsfp_filters    = av_dup_inc(proto_perl->Irsfp_filters, param);
 
     PL_compcv                  = cv_dup(proto_perl->Icompcv, param);
 
@@ -11189,43 +11262,12 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_parser          = parser_dup(proto_perl->Iparser, param);
 
-    PL_lex_state       = proto_perl->Ilex_state;
-
-#ifdef PERL_MAD
-    Copy(proto_perl->Inexttoke, PL_nexttoke, 5, NEXTTOKE);
-    PL_curforce                = proto_perl->Icurforce;
-#else
-    Copy(proto_perl->Inextval, PL_nextval, 5, YYSTYPE);
-    Copy(proto_perl->Inexttype, PL_nexttype, 5,        I32);
-    PL_nexttoke                = proto_perl->Inexttoke;
-#endif
-
-    PL_linestr         = sv_dup_inc(proto_perl->Ilinestr, param);
-    i = proto_perl->Ibufptr - SvPVX_const(proto_perl->Ilinestr);
-    PL_bufptr          = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    i = proto_perl->Ioldbufptr - SvPVX_const(proto_perl->Ilinestr);
-    PL_oldbufptr       = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    i = proto_perl->Ioldoldbufptr - SvPVX_const(proto_perl->Ilinestr);
-    PL_oldoldbufptr    = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    i = proto_perl->Ilinestart - SvPVX_const(proto_perl->Ilinestr);
-    PL_linestart       = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    PL_bufend          = SvPVX(PL_linestr) + SvCUR(PL_linestr);
-
-    PL_expect          = proto_perl->Iexpect;
-
     PL_multi_end       = proto_perl->Imulti_end;
 
     PL_error_count     = proto_perl->Ierror_count;
     PL_subline         = proto_perl->Isubline;
     PL_subname         = sv_dup_inc(proto_perl->Isubname, param);
 
-    i = proto_perl->Ilast_uni - SvPVX_const(proto_perl->Ilinestr);
-    PL_last_uni                = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    i = proto_perl->Ilast_lop - SvPVX_const(proto_perl->Ilinestr);
-    PL_last_lop                = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    PL_last_lop_op     = proto_perl->Ilast_lop_op;
-    PL_in_my           = proto_perl->Iin_my;
-    PL_in_my_stash     = hv_dup(proto_perl->Iin_my_stash, param);
 #ifdef FCRYPT
     PL_cryptseen       = proto_perl->Icryptseen;
 #endif
@@ -11314,7 +11356,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_glob_index      = proto_perl->Iglob_index;
     PL_srand_called    = proto_perl->Isrand_called;
-    PL_uudmap[(U32) 'M']       = 0;    /* reinits on demand */
     PL_bitcount                = NULL; /* reinits on demand */
 
     if (proto_perl->Ipsig_pend) {
@@ -11461,8 +11502,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_maxscream       = -1;                   /* reinits on demand */
     PL_lastscream      = NULL;
 
-    PL_watchaddr       = NULL;
-    PL_watchok         = NULL;
 
     PL_regdummy                = proto_perl->Tregdummy;
     PL_colorset                = 0;            /* reinits PL_colors[] */
@@ -11475,6 +11514,16 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_stashcache       = newHV();
 
+    PL_watchaddr       = (char **) ptr_table_fetch(PL_ptr_table,
+                                           proto_perl->Twatchaddr);
+    PL_watchok         = PL_watchaddr ? * PL_watchaddr : NULL;
+    if (PL_debug && PL_watchaddr) {
+       PerlIO_printf(Perl_debug_log,
+         "WATCHING: %"UVxf" cloned as %"UVxf" with value %"UVxf"\n",
+         PTR2UV(proto_perl->Twatchaddr), PTR2UV(PL_watchaddr),
+         PTR2UV(PL_watchok));
+    }
+
     if (!(flags & CLONEf_KEEP_PTR_TABLE)) {
         ptr_table_free(PL_ptr_table);
         PL_ptr_table = NULL;
@@ -12007,6 +12056,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
 
     case OP_PRTF:
     case OP_PRINT:
+    case OP_SAY:
        /* skip filehandle as it can't produce 'undef' warning  */
        o = cUNOPx(obase)->op_first;
        if ((obase->op_flags & OPf_STACKED) && o->op_type == OP_PUSHMARK)