This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Enhance PERL_TRACK_MEMPOOL so that it also emulates the PerlHost
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index b2a2fef..a915dd9 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1,7 +1,7 @@
 /*    sv.c
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -125,7 +125,7 @@ following functions (specified as [function that calls visit()] / [function
 called by visit() for each SV]):
 
     sv_report_used() / do_report_used()
-                       dump all remaining SVs (debugging aid)
+                       dump all remaining SVs (debugging aid)
 
     sv_clean_objs() / do_clean_objs(),do_clean_named_objs()
                        Attempt to free all objects pointed to by RVs,
@@ -177,6 +177,7 @@ Public API:
 void
 Perl_offer_nice_chunk(pTHX_ void *chunk, U32 chunk_size)
 {
+    dVAR;
     void *new_chunk;
     U32 new_chunk_size;
     LOCK_SV_MUTEX;
@@ -236,11 +237,12 @@ Perl_offer_nice_chunk(pTHX_ void *chunk, U32 chunk_size)
 STATIC SV*
 S_more_sv(pTHX)
 {
+    dVAR;
     SV* sv;
 
     if (PL_nice_chunk) {
        sv_add_arena(PL_nice_chunk, PL_nice_chunk_size, 0);
-       PL_nice_chunk = Nullch;
+       PL_nice_chunk = NULL;
         PL_nice_chunk_size = 0;
     }
     else {
@@ -314,6 +316,7 @@ S_new_SV(pTHX)
 STATIC void
 S_del_sv(pTHX_ SV *p)
 {
+    dVAR;
     if (DEBUG_D_TEST) {
        SV* sva;
        bool ok = 0;
@@ -357,6 +360,7 @@ and split it into a list of free SVs.
 void
 Perl_sv_add_arena(pTHX_ char *ptr, U32 size, U32 flags)
 {
+    dVAR;
     SV* const sva = (SV*)ptr;
     register SV* sv;
     register SV* svend;
@@ -394,6 +398,7 @@ Perl_sv_add_arena(pTHX_ char *ptr, U32 size, U32 flags)
 STATIC I32
 S_visit(pTHX_ SVFUNC_t f, U32 flags, U32 mask)
 {
+    dVAR;
     SV* sva;
     I32 visited = 0;
 
@@ -448,6 +453,7 @@ Perl_sv_report_used(pTHX)
 static void
 do_clean_objs(pTHX_ SV *ref)
 {
+    dVAR;
     if (SvROK(ref)) {
        SV * const target = SvRV(ref);
        if (SvOBJECT(target)) {
@@ -473,6 +479,7 @@ do_clean_objs(pTHX_ SV *ref)
 static void
 do_clean_named_objs(pTHX_ SV *sv)
 {
+    dVAR;
     if (SvTYPE(sv) == SVt_PVGV && GvGP(sv)) {
        if ((
 #ifdef PERL_DONT_CREATE_GVSV
@@ -503,6 +510,7 @@ Attempt to destroy all objects not yet freed
 void
 Perl_sv_clean_objs(pTHX)
 {
+    dVAR;
     PL_in_clean_objs = TRUE;
     visit(do_clean_objs, SVf_ROK, SVf_ROK);
 #ifndef DISABLE_DESTRUCTOR_KLUDGE
@@ -517,10 +525,11 @@ Perl_sv_clean_objs(pTHX)
 static void
 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 = Nullav;
+       PL_comppad = NULL;
        PL_curpad = Null(SV**);
     }
     SvREFCNT_dec(sv);
@@ -539,6 +548,7 @@ SVs which are in complex self-referential hierarchies.
 I32
 Perl_sv_clean_all(pTHX)
 {
+    dVAR;
     I32 cleaned;
     PL_in_clean_all = TRUE;
     cleaned = visit(do_clean_all, 0,0);
@@ -546,6 +556,52 @@ Perl_sv_clean_all(pTHX)
     return cleaned;
 }
 
+/*
+  ARENASETS: a meta-arena implementation which separates arena-info
+  into struct arena_set, which contains an array of struct
+  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
+
+  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
+  back the 1st slot in each arena (ie 1.7% of a CV-arena, less for
+  others)
+
+  union arena is declared with a fixed size, but is intended to vary
+  by type, allowing their use for big, rare body-types where theres
+  currently too much wastage (unused arena slots)
+*/
+#define ARENASETS 1
+
+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;
+    */
+};
+
+struct arena_set;
+
+/* Get the maximum number of elements in set[] such that struct arena_set
+   will fit within PERL_ARENA_SIZE, which is probabably just under 4K, and
+   therefore likely to be 1 aligned memory page.  */
+
+#define ARENAS_PER_SET  ((PERL_ARENA_SIZE - sizeof(struct arena_set*) \
+                         - 2 * sizeof(int)) / sizeof (struct arena_desc))
+
+struct arena_set {
+    struct arena_set* next;
+    int   set_size;            /* ie ARENAS_PER_SET */
+    int   curr;                        /* index of next available arena-desc */
+    struct arena_desc set[ARENAS_PER_SET];
+};
+
+#if !ARENASETS
+
 static void 
 S_free_arena(pTHX_ void **root) {
     while (root) {
@@ -554,7 +610,8 @@ S_free_arena(pTHX_ void **root) {
        root = next;
     }
 }
-    
+#endif
+
 /*
 =for apidoc sv_free_arenas
 
@@ -563,16 +620,10 @@ heads and bodies within the arenas must already have been freed.
 
 =cut
 */
-#define free_arena(name)                                       \
-    STMT_START {                                               \
-       S_free_arena(aTHX_ (void**) PL_ ## name ## _arenaroot); \
-       PL_ ## name ## _arenaroot = 0;                          \
-       PL_ ## name ## _root = 0;                               \
-    } STMT_END
-
 void
 Perl_sv_free_arenas(pTHX)
 {
+    dVAR;
     SV* sva;
     SV* svanext;
     int i;
@@ -589,14 +640,29 @@ Perl_sv_free_arenas(pTHX)
            Safefree(sva);
     }
 
-    for (i=0; i<SVt_LAST; i++) {
-       S_free_arena(aTHX_ (void**) PL_body_arenaroots[i]);
-       PL_body_arenaroots[i] = 0;
-       PL_body_roots[i] = 0;
+#if ARENASETS
+    {
+       struct arena_set *next, *aroot = (struct arena_set*) PL_body_arenas;
+       
+       for (; aroot; aroot = next) {
+           int max = aroot->curr;
+           for (i=0; i<max; i++) {
+               assert(aroot->set[i].arena);
+               Safefree(aroot->set[i].arena);
+           }
+           next = aroot->next;
+           Safefree(aroot);
+       }
     }
+#else
+    S_free_arena(aTHX_ (void**) PL_body_arenas);
+#endif
+
+    for (i=0; i<SVt_LAST; i++)
+       PL_body_roots[i] = 0;
 
     Safefree(PL_nice_chunk);
-    PL_nice_chunk = Nullch;
+    PL_nice_chunk = NULL;
     PL_nice_chunk_size = 0;
     PL_sv_arenaroot = 0;
     PL_sv_root = 0;
@@ -637,25 +703,79 @@ Perl_sv_free_arenas(pTHX)
   contexts below (line ~10k)
 */
 
+/* get_arena(size): when ARENASETS is enabled, this creates
+   custom-sized arenas, otherwize it uses PERL_ARENA_SIZE, as
+   previously done.
+   TBD: export properly for hv.c: S_more_he().
+*/
+void*
+Perl_get_arena(pTHX_ int arena_size)
+{
+#if !ARENASETS
+    union arena* arp;
+
+    /* allocate and attach arena */
+    Newx(arp, PERL_ARENA_SIZE, char);
+    arp->next = PL_body_arenas;
+    PL_body_arenas = arp;
+    return arp;
+
+#else
+    struct arena_desc* adesc;
+    struct arena_set *newroot, *aroot = (struct arena_set*) PL_body_arenas;
+    int curr;
+
+    if (!arena_size)
+       arena_size = PERL_ARENA_SIZE;
+
+    /* may need new arena-set to hold new arena */
+    if (!aroot || aroot->curr >= aroot->set_size) {
+       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", aroot));
+    }
+
+    /* ok, now have arena-set with at least 1 empty/available arena-desc */
+    curr = aroot->curr++;
+    adesc = &aroot->set[curr];
+    assert(!adesc->arena);
+    
+    /* old fixed-size way
+       Newxz(adesc->arena, 1, union arena);
+       adesc->size = sizeof(union arena);
+    */
+    /* new buggy way    */
+    Newxz(adesc->arena, arena_size, char);
+    adesc->size = arena_size;
+
+    /* adesc->count = sizeof(struct arena)/size; */
+    
+    DEBUG_m(PerlIO_printf(Perl_debug_log, "arena %d added: %p\n", curr, aroot));
+
+    return adesc->arena;
+#endif
+}
+
 STATIC void *
 S_more_bodies (pTHX_ size_t size, svtype sv_type)
 {
-    void ** const arena_root   = &PL_body_arenaroots[sv_type];
-    void ** const root         = &PL_body_roots[sv_type];
+    dVAR;
+    void ** const root = &PL_body_roots[sv_type];
     char *start;
     const char *end;
     const size_t count = PERL_ARENA_SIZE / size;
 
-    Newx(start, count*size, char);
-    *((void **) start) = *arena_root;
-    *arena_root = (void *)start;
+    start = (char*) Perl_get_arena(aTHX_ PERL_ARENA_SIZE); /* get a raw arena */
 
     end = start + (count-1) * size;
 
+#if !ARENASETS
     /* The initial slot is used to link the arenas together, so it isn't to be
        linked into the list of ready-to-use bodies.  */
-
     start += size;
+#endif
 
     *root = (void *)start;
 
@@ -693,6 +813,7 @@ S_more_bodies (pTHX_ size_t size, svtype sv_type)
 STATIC void *
 S_new_body(pTHX_ size_t size, svtype sv_type)
 {
+    dVAR;
     void *xpv;
     new_body_inline(xpv, size, sv_type);
     return xpv;
@@ -809,14 +930,14 @@ static const struct body_details bodies_by_type[] = {
     /* 8 bytes on most ILP32 with IEEE doubles */
     {sizeof(xpv_allocated),
      copy_length(XPV, xpv_len)
-     + relative_STRUCT_OFFSET(XPV, xpv_allocated, xpv_cur),
-     - relative_STRUCT_OFFSET(XPV, xpv_allocated, xpv_cur),
+     - relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
+     + relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
      FALSE, NONV, HASARENA},
     /* 12 */
     {sizeof(xpviv_allocated),
      copy_length(XPVIV, xiv_u)
-     + relative_STRUCT_OFFSET(XPVIV, xpviv_allocated, xpv_cur),
-     - relative_STRUCT_OFFSET(XPVIV, xpviv_allocated, xpv_cur),
+     - relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
+     + relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
      FALSE, NONV, HASARENA},
     /* 20 */
     {sizeof(XPVNV), copy_length(XPVNV, xiv_u), 0, FALSE, HADNV, HASARENA},
@@ -831,14 +952,14 @@ static const struct body_details bodies_by_type[] = {
     /* 20 */
     {sizeof(xpvav_allocated),
      copy_length(XPVAV, xmg_stash)
-     + relative_STRUCT_OFFSET(XPVAV, xpvav_allocated, xav_fill),
-     - relative_STRUCT_OFFSET(XPVAV, xpvav_allocated, xav_fill),
+     - relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
+     + relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
      TRUE, HADNV, HASARENA},
     /* 20 */
     {sizeof(xpvhv_allocated),
      copy_length(XPVHV, xmg_stash)
-     + relative_STRUCT_OFFSET(XPVHV, xpvhv_allocated, xhv_fill),
-     - relative_STRUCT_OFFSET(XPVHV, xpvhv_allocated, xhv_fill),
+     - relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
+     + relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
      TRUE, HADNV, HASARENA},
     /* 76 */
     {sizeof(XPVCV), sizeof(XPVCV), 0, TRUE, HADNV, HASARENA},
@@ -930,6 +1051,7 @@ You generally want to use the C<SvUPGRADE> macro wrapper. See also C<svtype>.
 void
 Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
 {
+    dVAR;
     void*      old_body;
     void*      new_body;
     const U32  old_type = SvTYPE(sv);
@@ -1076,14 +1198,14 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
 
        /* Could put this in the else clause below, as PVMG must have SvPVX
           0 already (the assertion above)  */
-       SvPV_set(sv, (char*)0);
+       SvPV_set(sv, NULL);
 
        if (old_type >= SVt_PVMG) {
            SvMAGIC_set(sv, ((XPVMG*)old_body)->xmg_magic);
            SvSTASH_set(sv, ((XPVMG*)old_body)->xmg_stash);
        } else {
-           SvMAGIC_set(sv, 0);
-           SvSTASH_set(sv, 0);
+           SvMAGIC_set(sv, NULL);
+           SvSTASH_set(sv, NULL);
        }
        break;
 
@@ -1123,19 +1245,23 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
        }
 
 #ifndef NV_ZERO_IS_ALLBITS_ZERO
-    /* If NV 0.0 is store as all bits 0 then Zero() already creates a correct
-       0.0 for us.  */
-       if (old_type_details->zero_nv)
+       /* If NV 0.0 is stores as all bits 0 then Zero() already creates a
+        * correct 0.0 for us.  Otherwise, if the old body didn't have an
+        * 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)
            SvNV_set(sv, 0);
 #endif
 
        if (new_type == SVt_PVIO)
-           IoPAGE_LEN(sv)      = 60;
+           IoPAGE_LEN(sv) = 60;
        if (old_type < SVt_RV)
-           SvPV_set(sv, 0);
+           SvPV_set(sv, NULL);
        break;
     default:
-       Perl_croak(aTHX_ "panic: sv_upgrade to unknown type %lu", new_type);
+       Perl_croak(aTHX_ "panic: sv_upgrade to unknown type %lu",
+                  (unsigned long)new_type);
     }
 
     if (old_type_details->size) {
@@ -1252,6 +1378,7 @@ Does not handle 'set' magic.  See also C<sv_setiv_mg>.
 void
 Perl_sv_setiv(pTHX_ register SV *sv, IV i)
 {
+    dVAR;
     SV_CHECK_THINKFIRST_COW_DROP(sv);
     switch (SvTYPE(sv)) {
     case SVt_NULL:
@@ -1352,6 +1479,7 @@ Does not handle 'set' magic.  See also C<sv_setnv_mg>.
 void
 Perl_sv_setnv(pTHX_ register SV *sv, NV num)
 {
+    dVAR;
     SV_CHECK_THINKFIRST_COW_DROP(sv);
     switch (SvTYPE(sv)) {
     case SVt_NULL:
@@ -1400,12 +1528,13 @@ Perl_sv_setnv_mg(pTHX_ register SV *sv, NV num)
 STATIC void
 S_not_a_number(pTHX_ SV *sv)
 {
+     dVAR;
      SV *dsv;
      char tmpbuf[64];
      const char *pv;
 
      if (DO_UTF8(sv)) {
-          dsv = sv_2mortal(newSVpvn("", 0));
+          dsv = sv_2mortal(newSVpvs(""));
           pv = sv_uni_display(dsv, sv, 10, 0);
      } else {
          char *d = tmpbuf;
@@ -1581,6 +1710,7 @@ Perl_looks_like_number(pTHX_ SV *sv)
 STATIC int
 S_sv_2iuv_non_preserve(pTHX_ register SV *sv, I32 numtype)
 {
+    dVAR;
     DEBUG_c(PerlIO_printf(Perl_debug_log,"sv_2iuv_non '%s', IV=0x%"UVxf" NV=%"NVgf" inttype=%"UVXf"\n", SvPVX_const(sv), SvIVX(sv), SvNVX(sv), (UV)numtype));
     if (SvNVX(sv) < (NV)IV_MIN) {
        (void)SvIOKp_on(sv);
@@ -1627,6 +1757,7 @@ S_sv_2iuv_non_preserve(pTHX_ register SV *sv, I32 numtype)
 
 STATIC bool
 S_sv_2iuv_common(pTHX_ SV *sv) {
+    dVAR;
     if (SvNOKp(sv)) {
        /* erm. not sure. *should* never get NOKp (without NOK) from sv_2nv
         * without also getting a cached IV/UV from it at the same time
@@ -1727,7 +1858,7 @@ S_sv_2iuv_common(pTHX_ SV *sv) {
        } else if (SvTYPE(sv) < SVt_PVNV)
            sv_upgrade(sv, SVt_PVNV);
 
-       /* If NV preserves UV then we only use the UV value if we know that
+       /* If NVs preserve UVs then we only use the UV value if we know that
           we aren't going to call atof() below. If NVs don't preserve UVs
           then the value returned may have more precision than atof() will
           return, even though value isn't perfectly accurate.  */
@@ -1878,6 +2009,7 @@ Normally used via the C<SvIV(sv)> and C<SvIVx(sv)> macros.
 IV
 Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
 {
+    dVAR;
     if (!sv)
        return 0;
     if (SvGMAGICAL(sv)) {
@@ -1915,8 +2047,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
        }
        assert(SvTYPE(sv) >= SVt_PVMG);
        /* This falls through to the report_uninit inside S_sv_2iuv_common.  */
-    }
-    if (SvTHINKFIRST(sv)) {
+    } else if (SvTHINKFIRST(sv)) {
        if (SvROK(sv)) {
        return_rok:
            if (SvAMAGIC(sv)) {
@@ -1958,6 +2089,7 @@ Normally used via the C<SvUV(sv)> and C<SvUVx(sv)> macros.
 UV
 Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
 {
+    dVAR;
     if (!sv)
        return 0;
     if (SvGMAGICAL(sv)) {
@@ -1989,8 +2121,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
        }
        assert(SvTYPE(sv) >= SVt_PVMG);
        /* This falls through to the report_uninit inside S_sv_2iuv_common.  */
-    }
-    if (SvTHINKFIRST(sv)) {
+    } else if (SvTHINKFIRST(sv)) {
        if (SvROK(sv)) {
        return_rok:
            if (SvAMAGIC(sv)) {
@@ -2033,6 +2164,7 @@ macros.
 NV
 Perl_sv_2nv(pTHX_ register SV *sv)
 {
+    dVAR;
     if (!sv)
        return 0.0;
     if (SvGMAGICAL(sv)) {
@@ -2262,6 +2394,7 @@ S_uiv_2buf(char *buf, IV iv, UV uv, int is_uv, char **peob)
 
 static char *
 S_stringify_regexp(pTHX_ SV *sv, MAGIC *mg, STRLEN *lp) {
+    dVAR;
     const regexp * const re = (regexp *)mg->mg_obj;
 
     if (!mg->mg_ptr) {
@@ -2351,8 +2484,8 @@ usually end up here too.
 char *
 Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
 {
+    dVAR;
     register char *s;
-    int olderrno;
 
     if (!sv) {
        if (lp)
@@ -2452,13 +2585,13 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                const SV *const referent = (SV*)SvRV(sv);
 
                if (!referent) {
-                   tsv = sv_2mortal(newSVpvn("NULLREF", 7));
+                   tsv = sv_2mortal(newSVpvs("NULLREF"));
                } else if (SvTYPE(referent) == SVt_PVMG
                           && ((SvFLAGS(referent) &
                                (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG))
                               == (SVs_OBJECT|SVs_SMG))
                           && (mg = mg_find(referent, PERL_MAGIC_qr))) {
-                   return S_stringify_regexp(aTHX_ sv, mg, lp);
+                   return stringify_regexp(sv, mg, lp);
                } else {
                    const char *const typestr = sv_reftype(referent, 0);
 
@@ -2496,10 +2629,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
 
        if (SvTYPE(sv) < SVt_PVIV)
            sv_upgrade(sv, SVt_PVIV);
-       if (isUIOK)
-           ptr = uiv_2buf(buf, 0, SvUVX(sv), 1, &ebuf);
-       else
-           ptr = uiv_2buf(buf, SvIVX(sv), 0, 0, &ebuf);
+       ptr = uiv_2buf(buf, SvIVX(sv), SvUVX(sv), isUIOK, &ebuf);
        /* inlined from sv_setpvn */
        SvGROW_mutable(sv, (STRLEN)(ebuf - ptr + 1));
        Move(ptr,SvPVX_mutable(sv),ebuf - ptr,char);
@@ -2514,11 +2644,12 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
            SvIsUV_on(sv);
     }
     else if (SvNOKp(sv)) {
+       const int olderrno = errno;
        if (SvTYPE(sv) < SVt_PVNV)
            sv_upgrade(sv, SVt_PVNV);
        /* The +20 is pure guesswork.  Configure test needed. --jhi */
        s = SvGROW_mutable(sv, NV_DIG + 20);
-       olderrno = errno;       /* some Xenix systems wipe out errno here */
+       /* some Xenix systems wipe out errno here */
 #ifdef apollo
        if (SvNVX(sv) == 0.0)
            (void)strcpy(s,"0");
@@ -2640,16 +2771,18 @@ sv_true() or its macro equivalent.
 bool
 Perl_sv_2bool(pTHX_ register SV *sv)
 {
+    dVAR;
     SvGETMAGIC(sv);
 
     if (!SvOK(sv))
        return 0;
     if (SvROK(sv)) {
-       SV* tmpsv;
-        if (SvAMAGIC(sv) && (tmpsv=AMG_CALLun(sv,bool_)) &&
-                (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv))))
-           return (bool)SvTRUE(tmpsv);
-      return SvRV(sv) != 0;
+       if (SvAMAGIC(sv)) {
+           SV * const tmpsv = AMG_CALLun(sv,bool_);
+           if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv))))
+               return (bool)SvTRUE(tmpsv);
+       }
+       return SvRV(sv) != 0;
     }
     if (SvPOKp(sv)) {
        register XPV* const Xpvtmp = (XPV*)SvANY(sv);
@@ -2702,6 +2835,7 @@ use the Encode extension for that.
 STRLEN
 Perl_sv_utf8_upgrade_flags(pTHX_ register SV *sv, I32 flags)
 {
+    dVAR;
     if (sv == &PL_sv_undef)
        return 0;
     if (!SvPOK(sv)) {
@@ -2771,6 +2905,7 @@ use the Encode extension for that.
 bool
 Perl_sv_utf8_downgrade(pTHX_ register SV* sv, bool fail_ok)
 {
+    dVAR;
     if (SvPOKp(sv) && SvUTF8(sv)) {
         if (SvCUR(sv)) {
            U8 *s;
@@ -2898,9 +3033,179 @@ copy-ish functions and macros use this underneath.
 =cut
 */
 
+static void
+S_glob_assign(pTHX_ SV *dstr, SV *sstr, const int dtype)
+{
+    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)
+           sv_upgrade(dstr, SVt_PVGV);
+       sv_magic(dstr, dstr, PERL_MAGIC_glob, NULL, 0);
+       GvSTASH(dstr) = GvSTASH(sstr);
+       if (GvSTASH(dstr))
+           Perl_sv_add_backref(aTHX_ (SV*)GvSTASH(dstr), dstr);
+       GvNAME(dstr) = savepvn(name, len);
+       GvNAMELEN(dstr) = len;
+       SvFAKE_on(dstr);        /* can coerce to non-glob */
+    }
+
+#ifdef GV_UNIQUE_CHECK
+    if (GvUNIQUE((GV*)dstr)) {
+       Perl_croak(aTHX_ PL_no_modify);
+    }
+#endif
+
+    (void)SvOK_off(dstr);
+    GvINTRO_off(dstr);         /* one-shot flag */
+    gp_free((GV*)dstr);
+    GvGP(dstr) = gp_ref(GvGP(sstr));
+    if (SvTAINTED(sstr))
+       SvTAINT(dstr);
+    if (GvIMPORTED(dstr) != GVf_IMPORTED
+       && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
+       {
+           GvIMPORTED_on(dstr);
+       }
+    GvMULTI_on(dstr);
+    return;
+}
+
+static void
+S_pvgv_assign(pTHX_ SV *dstr, SV *sstr) {
+    SV * const sref = SvREFCNT_inc(SvRV(sstr));
+    SV *dref = NULL;
+    const int intro = GvINTRO(dstr);
+
+#ifdef GV_UNIQUE_CHECK
+    if (GvUNIQUE((GV*)dstr)) {
+       Perl_croak(aTHX_ PL_no_modify);
+    }
+#endif
+
+    if (intro) {
+       GvINTRO_off(dstr);      /* one-shot flag */
+       GvLINE(dstr) = CopLINE(PL_curcop);
+       GvEGV(dstr) = (GV*)dstr;
+    }
+    GvMULTI_on(dstr);
+    switch (SvTYPE(sref)) {
+    case SVt_PVAV:
+       if (intro)
+           SAVEGENERICSV(GvAV(dstr));
+       else
+           dref = (SV*)GvAV(dstr);
+       GvAV(dstr) = (AV*)sref;
+       if (!GvIMPORTED_AV(dstr)
+           && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
+           {
+               GvIMPORTED_AV_on(dstr);
+           }
+       break;
+    case SVt_PVHV:
+       if (intro)
+           SAVEGENERICSV(GvHV(dstr));
+       else
+           dref = (SV*)GvHV(dstr);
+       GvHV(dstr) = (HV*)sref;
+       if (!GvIMPORTED_HV(dstr)
+           && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
+           {
+               GvIMPORTED_HV_on(dstr);
+           }
+       break;
+    case SVt_PVCV:
+       if (intro) {
+           if (GvCVGEN(dstr) && GvCV(dstr) != (CV*)sref) {
+               SvREFCNT_dec(GvCV(dstr));
+               GvCV(dstr) = NULL;
+               GvCVGEN(dstr) = 0; /* Switch off cacheness. */
+               PL_sub_generation++;
+           }
+           SAVEGENERICSV(GvCV(dstr));
+       }
+       else
+           dref = (SV*)GvCV(dstr);
+       if (GvCV(dstr) != (CV*)sref) {
+           CV* const cv = GvCV(dstr);
+           if (cv) {
+               if (!GvCVGEN((GV*)dstr) &&
+                   (CvROOT(cv) || CvXSUB(cv)))
+                   {
+                       /* Redefining a sub - warning is mandatory if
+                          it was a const and its value changed. */
+                       if (CvCONST(cv) && CvCONST((CV*)sref)
+                           && cv_const_sv(cv) == cv_const_sv((CV*)sref)) {
+                           /* They are 2 constant subroutines generated from
+                              the same constant. This probably means that
+                              they are really the "same" proxy subroutine
+                              instantiated in 2 places. Most likely this is
+                              when a constant is exported twice.  Don't warn.
+                           */
+                       }
+                       else if (ckWARN(WARN_REDEFINE)
+                                || (CvCONST(cv)
+                                    && (!CvCONST((CV*)sref)
+                                        || sv_cmp(cv_const_sv(cv),
+                                                  cv_const_sv((CV*)sref))))) {
+                           Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
+                                       CvCONST(cv)
+                                       ? "Constant subroutine %s::%s redefined"
+                                       : "Subroutine %s::%s redefined",
+                                       HvNAME_get(GvSTASH((GV*)dstr)),
+                                       GvENAME((GV*)dstr));
+                       }
+                   }
+               if (!intro)
+                   cv_ckproto(cv, (GV*)dstr,
+                              SvPOK(sref) ? SvPVX_const(sref) : NULL);
+           }
+           GvCV(dstr) = (CV*)sref;
+           GvCVGEN(dstr) = 0; /* Switch off cacheness. */
+           GvASSUMECV_on(dstr);
+           PL_sub_generation++;
+       }
+       if (!GvIMPORTED_CV(dstr) && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) {
+           GvIMPORTED_CV_on(dstr);
+       }
+       break;
+    case SVt_PVIO:
+       if (intro)
+           SAVEGENERICSV(GvIOp(dstr));
+       else
+           dref = (SV*)GvIOp(dstr);
+       GvIOp(dstr) = (IO*)sref;
+       break;
+    case SVt_PVFM:
+       if (intro)
+           SAVEGENERICSV(GvFORM(dstr));
+       else
+           dref = (SV*)GvFORM(dstr);
+       GvFORM(dstr) = (CV*)sref;
+       break;
+    default:
+       if (intro)
+           SAVEGENERICSV(GvSV(dstr));
+       else
+           dref = (SV*)GvSV(dstr);
+       GvSV(dstr) = sref;
+       if (!GvIMPORTED_SV(dstr) && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) {
+           GvIMPORTED_SV_on(dstr);
+       }
+       break;
+    }
+    if (dref)
+       SvREFCNT_dec(dref);
+    if (SvTAINTED(sstr))
+       SvTAINT(dstr);
+    return;
+}
+
 void
 Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
 {
+    dVAR;
     register U32 sflags;
     register int dtype;
     register int stype;
@@ -2949,8 +3254,11 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            SvIV_set(dstr,  SvIVX(sstr));
            if (SvIsUV(sstr))
                SvIsUV_on(dstr);
-           if (SvTAINTED(sstr))
-               SvTAINT(dstr);
+           /* SvTAINTED can only be true if the SV has taint magic, which in
+              turn means that the SV type is PVMG (or greater). This is the
+              case statement for SVt_IV, so this cannot be true (whatever gcov
+              may say).  */
+           assert(!SvTAINTED(sstr));
            return;
        }
        goto undef_sstr;
@@ -2970,8 +3278,11 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            }
            SvNV_set(dstr, SvNVX(sstr));
            (void)SvNOK_only(dstr);
-           if (SvTAINTED(sstr))
-               SvTAINT(dstr);
+           /* SvTAINTED can only be true if the SV has taint magic, which in
+              turn means that the SV type is PVMG (or greater). This is the
+              case statement for SVt_NV, so this cannot be true (whatever gcov
+              may say).  */
+           assert(!SvTAINTED(sstr));
            return;
        }
        goto undef_sstr;
@@ -2991,7 +3302,8 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                GvMULTI_on(dstr);
                return;
            }
-           goto glob_assign;
+           S_glob_assign(aTHX_ dstr, sstr, dtype);
+           return;
        }
        break;
     case SVt_PVFM:
@@ -3030,40 +3342,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
 
     case SVt_PVGV:
        if (dtype <= SVt_PVGV) {
-  glob_assign:
-           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)
-                   sv_upgrade(dstr, SVt_PVGV);
-               sv_magic(dstr, dstr, PERL_MAGIC_glob, Nullch, 0);
-               GvSTASH(dstr) = GvSTASH(sstr);
-               if (GvSTASH(dstr))
-                   Perl_sv_add_backref(aTHX_ (SV*)GvSTASH(dstr), dstr);
-               GvNAME(dstr) = savepvn(name, len);
-               GvNAMELEN(dstr) = len;
-               SvFAKE_on(dstr);        /* can coerce to non-glob */
-           }
-
-#ifdef GV_UNIQUE_CHECK
-                if (GvUNIQUE((GV*)dstr)) {
-                    Perl_croak(aTHX_ PL_no_modify);
-                }
-#endif
-
-           (void)SvOK_off(dstr);
-           GvINTRO_off(dstr);          /* one-shot flag */
-           gp_free((GV*)dstr);
-           GvGP(dstr) = gp_ref(GvGP(sstr));
-           if (SvTAINTED(sstr))
-               SvTAINT(dstr);
-           if (GvIMPORTED(dstr) != GVf_IMPORTED
-               && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
-           {
-               GvIMPORTED_on(dstr);
-           }
-           GvMULTI_on(dstr);
+           S_glob_assign(aTHX_ dstr, sstr, dtype);
            return;
        }
        /* FALL THROUGH */
@@ -3073,8 +3352,10 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            mg_get(sstr);
            if ((int)SvTYPE(sstr) != stype) {
                stype = SvTYPE(sstr);
-               if (stype == SVt_PVGV && dtype <= SVt_PVGV)
-                   goto glob_assign;
+               if (stype == SVt_PVGV && dtype <= SVt_PVGV) {
+                   S_glob_assign(aTHX_ dstr, sstr, dtype);
+                   return;
+               }
            }
        }
        if (stype == SVt_PVLV)
@@ -3088,128 +3369,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
     if (sflags & SVf_ROK) {
        if (dtype >= SVt_PV) {
            if (dtype == SVt_PVGV) {
-               SV * const sref = SvREFCNT_inc(SvRV(sstr));
-               SV *dref = 0;
-               const int intro = GvINTRO(dstr);
-
-#ifdef GV_UNIQUE_CHECK
-                if (GvUNIQUE((GV*)dstr)) {
-                    Perl_croak(aTHX_ PL_no_modify);
-                }
-#endif
-
-               if (intro) {
-                   GvINTRO_off(dstr);  /* one-shot flag */
-                   GvLINE(dstr) = CopLINE(PL_curcop);
-                   GvEGV(dstr) = (GV*)dstr;
-               }
-               GvMULTI_on(dstr);
-               switch (SvTYPE(sref)) {
-               case SVt_PVAV:
-                   if (intro)
-                       SAVEGENERICSV(GvAV(dstr));
-                   else
-                       dref = (SV*)GvAV(dstr);
-                   GvAV(dstr) = (AV*)sref;
-                   if (!GvIMPORTED_AV(dstr)
-                       && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
-                   {
-                       GvIMPORTED_AV_on(dstr);
-                   }
-                   break;
-               case SVt_PVHV:
-                   if (intro)
-                       SAVEGENERICSV(GvHV(dstr));
-                   else
-                       dref = (SV*)GvHV(dstr);
-                   GvHV(dstr) = (HV*)sref;
-                   if (!GvIMPORTED_HV(dstr)
-                       && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
-                   {
-                       GvIMPORTED_HV_on(dstr);
-                   }
-                   break;
-               case SVt_PVCV:
-                   if (intro) {
-                       if (GvCVGEN(dstr) && GvCV(dstr) != (CV*)sref) {
-                           SvREFCNT_dec(GvCV(dstr));
-                           GvCV(dstr) = Nullcv;
-                           GvCVGEN(dstr) = 0; /* Switch off cacheness. */
-                           PL_sub_generation++;
-                       }
-                       SAVEGENERICSV(GvCV(dstr));
-                   }
-                   else
-                       dref = (SV*)GvCV(dstr);
-                   if (GvCV(dstr) != (CV*)sref) {
-                       CV* const cv = GvCV(dstr);
-                       if (cv) {
-                           if (!GvCVGEN((GV*)dstr) &&
-                               (CvROOT(cv) || CvXSUB(cv)))
-                           {
-                               /* Redefining a sub - warning is mandatory if
-                                  it was a const and its value changed. */
-                               if (ckWARN(WARN_REDEFINE)
-                                   || (CvCONST(cv)
-                                       && (!CvCONST((CV*)sref)
-                                           || sv_cmp(cv_const_sv(cv),
-                                                     cv_const_sv((CV*)sref)))))
-                               {
-                                   Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
-                                       CvCONST(cv)
-                                       ? "Constant subroutine %s::%s redefined"
-                                       : "Subroutine %s::%s redefined",
-                                       HvNAME_get(GvSTASH((GV*)dstr)),
-                                       GvENAME((GV*)dstr));
-                               }
-                           }
-                           if (!intro)
-                               cv_ckproto(cv, (GV*)dstr,
-                                          SvPOK(sref)
-                                          ? SvPVX_const(sref) : Nullch);
-                       }
-                       GvCV(dstr) = (CV*)sref;
-                       GvCVGEN(dstr) = 0; /* Switch off cacheness. */
-                       GvASSUMECV_on(dstr);
-                       PL_sub_generation++;
-                   }
-                   if (!GvIMPORTED_CV(dstr)
-                       && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
-                   {
-                       GvIMPORTED_CV_on(dstr);
-                   }
-                   break;
-               case SVt_PVIO:
-                   if (intro)
-                       SAVEGENERICSV(GvIOp(dstr));
-                   else
-                       dref = (SV*)GvIOp(dstr);
-                   GvIOp(dstr) = (IO*)sref;
-                   break;
-               case SVt_PVFM:
-                   if (intro)
-                       SAVEGENERICSV(GvFORM(dstr));
-                   else
-                       dref = (SV*)GvFORM(dstr);
-                   GvFORM(dstr) = (CV*)sref;
-                   break;
-               default:
-                   if (intro)
-                       SAVEGENERICSV(GvSV(dstr));
-                   else
-                       dref = (SV*)GvSV(dstr);
-                   GvSV(dstr) = sref;
-                   if (!GvIMPORTED_SV(dstr)
-                       && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
-                   {
-                       GvIMPORTED_SV_on(dstr);
-                   }
-                   break;
-               }
-               if (dref)
-                   SvREFCNT_dec(dref);
-               if (SvTAINTED(sstr))
-                   SvTAINT(dstr);
+               S_pvgv_assign(aTHX_ dstr, sstr);
                return;
            }
            if (SvPVX_const(dstr)) {
@@ -3220,25 +3380,11 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        }
        (void)SvOK_off(dstr);
        SvRV_set(dstr, SvREFCNT_inc(SvRV(sstr)));
-       SvROK_on(dstr);
-       if (sflags & SVp_NOK) {
-           SvNOKp_on(dstr);
-           /* Only set the public OK flag if the source has public OK.  */
-           if (sflags & SVf_NOK)
-               SvFLAGS(dstr) |= SVf_NOK;
-           SvNV_set(dstr, SvNVX(sstr));
-       }
-       if (sflags & SVp_IOK) {
-           (void)SvIOKp_on(dstr);
-           if (sflags & SVf_IOK)
-               SvFLAGS(dstr) |= SVf_IOK;
-           if (sflags & SVf_IVisUV)
-               SvIsUV_on(dstr);
-           SvIV_set(dstr, SvIVX(sstr));
-       }
-       if (SvAMAGIC(sstr)) {
-           SvAMAGIC_on(dstr);
-       }
+       SvFLAGS(dstr) |= sflags & (SVf_ROK|SVf_AMAGIC);
+       assert(!(sflags & SVp_NOK));
+       assert(!(sflags & SVp_IOK));
+       assert(!(sflags & SVf_NOK));
+       assert(!(sflags & SVf_IOK));
     }
     else if (sflags & SVp_POK) {
         bool isSwipe = 0;
@@ -3355,63 +3501,45 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
 
                 SvTEMP_off(dstr);
                 (void)SvOK_off(sstr);  /* NOTE: nukes most SvFLAGS on sstr */
-                SvPV_set(sstr, Nullch);
+                SvPV_set(sstr, NULL);
                 SvLEN_set(sstr, 0);
                 SvCUR_set(sstr, 0);
                 SvTEMP_off(sstr);
             }
         }
-       if (sflags & SVf_UTF8)
-           SvUTF8_on(dstr);
        if (sflags & SVp_NOK) {
-           SvNOKp_on(dstr);
-           if (sflags & SVf_NOK)
-               SvFLAGS(dstr) |= SVf_NOK;
            SvNV_set(dstr, SvNVX(sstr));
        }
        if (sflags & SVp_IOK) {
-           (void)SvIOKp_on(dstr);
-           if (sflags & SVf_IOK)
-               SvFLAGS(dstr) |= SVf_IOK;
+           SvRELEASE_IVX(dstr);
+           SvIV_set(dstr, SvIVX(sstr));
+           /* Must do this otherwise some other overloaded use of 0x80000000
+              gets confused. I guess SVpbm_VALID */
            if (sflags & SVf_IVisUV)
                SvIsUV_on(dstr);
-           SvIV_set(dstr, SvIVX(sstr));
        }
-       if (SvVOK(sstr)) {
-           const MAGIC * const smg = mg_find(sstr,PERL_MAGIC_vstring);
-           sv_magic(dstr, NULL, PERL_MAGIC_vstring,
-                       smg->mg_ptr, smg->mg_len);
-           SvRMAGICAL_on(dstr);
+       SvFLAGS(dstr) |= sflags & (SVf_IOK|SVp_IOK|SVf_NOK|SVp_NOK|SVf_UTF8);
+       {
+           const MAGIC * const smg = SvVOK(sstr);
+           if (smg) {
+               sv_magic(dstr, NULL, PERL_MAGIC_vstring,
+                        smg->mg_ptr, smg->mg_len);
+               SvRMAGICAL_on(dstr);
+           }
        }
     }
-    else if (sflags & SVp_IOK) {
-       if (sflags & SVf_IOK)
-           (void)SvIOK_only(dstr);
-       else {
-           (void)SvOK_off(dstr);
-           (void)SvIOKp_on(dstr);
+    else if (sflags & (SVp_IOK|SVp_NOK)) {
+       (void)SvOK_off(dstr);
+       SvFLAGS(dstr) |= sflags & (SVf_IOK|SVp_IOK|SVf_IVisUV|SVf_NOK|SVp_NOK);
+       if (sflags & SVp_IOK) {
+           /* XXXX Do we want to set IsUV for IV(ROK)?  Be extra safe... */
+           SvIV_set(dstr, SvIVX(sstr));
        }
-       /* XXXX Do we want to set IsUV for IV(ROK)?  Be extra safe... */
-       if (sflags & SVf_IVisUV)
-           SvIsUV_on(dstr);
-       SvIV_set(dstr, SvIVX(sstr));
        if (sflags & SVp_NOK) {
-           if (sflags & SVf_NOK)
-               (void)SvNOK_on(dstr);
-           else
-               (void)SvNOKp_on(dstr);
+           SvFLAGS(dstr) |= sflags & (SVf_NOK|SVp_NOK);
            SvNV_set(dstr, SvNVX(sstr));
        }
     }
-    else if (sflags & SVp_NOK) {
-       if (sflags & SVf_NOK)
-           (void)SvNOK_only(dstr);
-       else {
-           (void)SvOK_off(dstr);
-           SvNOKp_on(dstr);
-       }
-       SvNV_set(dstr, SvNVX(sstr));
-    }
     else {
        if (dtype == SVt_PVGV) {
            if (ckWARN(WARN_MISC))
@@ -3521,6 +3649,7 @@ undefined.  Does not handle 'set' magic.  See C<sv_setpvn_mg>.
 void
 Perl_sv_setpvn(pTHX_ register SV *sv, register const char *ptr, register STRLEN len)
 {
+    dVAR;
     register char *dptr;
 
     SV_CHECK_THINKFIRST_COW_DROP(sv);
@@ -3571,6 +3700,7 @@ handle 'set' magic.  See C<sv_setpv_mg>.
 void
 Perl_sv_setpv(pTHX_ register SV *sv, register const char *ptr)
 {
+    dVAR;
     register STRLEN len;
 
     SV_CHECK_THINKFIRST_COW_DROP(sv);
@@ -3620,6 +3750,7 @@ See C<sv_usepvn_mg>.
 void
 Perl_sv_usepvn(pTHX_ register SV *sv, register char *ptr, register STRLEN len)
 {
+    dVAR;
     STRLEN allocate;
     SV_CHECK_THINKFIRST_COW_DROP(sv);
     SvUPGRADE(sv, SVt_PV);
@@ -3666,7 +3797,7 @@ S_sv_release_COW(pTHX_ register SV *sv, const char *pvx, STRLEN len, SV *after)
 {
     if (len) { /* this SV was SvIsCOW_normal(sv) */
          /* we need to find the SV pointing to us.  */
-        SV * const current = SV_COW_NEXT_SV(after);
+        SV *current = SV_COW_NEXT_SV(after);
 
         if (current == sv) {
             /* The SV we point to points back to us (there were only two of us
@@ -3721,6 +3852,7 @@ with flags set to 0.
 void
 Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
 {
+    dVAR;
 #ifdef PERL_OLD_COPY_ON_WRITE
     if (SvREADONLY(sv)) {
         /* At this point I believe I should acquire a global SV mutex.  */
@@ -3738,7 +3870,7 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
             SvFAKE_off(sv);
             SvREADONLY_off(sv);
             /* This SV doesn't own the buffer, so need to Newx() a new one:  */
-            SvPV_set(sv, (char*)0);
+            SvPV_set(sv, NULL);
             SvLEN_set(sv, 0);
             if (flags & SV_COW_DROP_PV) {
                 /* OK, so we don't need to copy our buffer.  */
@@ -3765,7 +3897,7 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
            const STRLEN len = SvCUR(sv);
            SvFAKE_off(sv);
            SvREADONLY_off(sv);
-           SvPV_set(sv, Nullch);
+           SvPV_set(sv, NULL);
            SvLEN_set(sv, 0);
            SvGROW(sv, len + 1);
            Move(pvx,SvPVX(sv),len,char);
@@ -3850,8 +3982,9 @@ in terms of this function.
 void
 Perl_sv_catpvn_flags(pTHX_ register SV *dsv, register const char *sstr, register STRLEN slen, I32 flags)
 {
+    dVAR;
     STRLEN dlen;
-    const char *dstr = SvPV_force_flags(dsv, dlen, flags);
+    const char * const dstr = SvPV_force_flags(dsv, dlen, flags);
 
     SvGROW(dsv, dlen + slen + 1);
     if (sstr == dstr)
@@ -3884,6 +4017,7 @@ and C<sv_catsv_nomg> are implemented in terms of this function.
 void
 Perl_sv_catsv_flags(pTHX_ SV *dsv, register SV *ssv, I32 flags)
 {
+    dVAR;
     if (ssv) {
        STRLEN slen;
        const char *spv = SvPV_const(ssv, slen);
@@ -3932,6 +4066,7 @@ valid UTF-8.  Handles 'get' magic, but not 'set' magic.  See C<sv_catpv_mg>.
 void
 Perl_sv_catpv(pTHX_ register SV *sv, register const char *ptr)
 {
+    dVAR;
     register STRLEN len;
     STRLEN tlen;
     char *junk;
@@ -3967,9 +4102,16 @@ Perl_sv_catpv_mg(pTHX_ register SV *sv, register const char *ptr)
 /*
 =for apidoc newSV
 
-Create a new null SV, or if len > 0, create a new empty SVt_PV type SV
-with an initial PV allocation of len+1. Normally accessed via the C<NEWSV>
-macro.
+Creates a new SV.  A non-zero C<len> parameter indicates the number of
+bytes of preallocated string space the SV should have.  An extra byte for a
+trailing NUL is also reserved.  (SvPOK is not set for the SV even if string
+space is allocated.)  The reference count for the new SV is set to 1.
+
+In 5.9.3, newSV() replaces the older NEWSV() API, and drops the first
+parameter, I<x>, a debug aid which allowed callers to identify themselves.
+This aid has been superseded by a new build option, PERL_MEM_LOG (see
+L<perlhack/PERL_MEM_LOG>).  The older API is still there for use in XS
+modules supporting older perls.
 
 =cut
 */
@@ -3977,6 +4119,7 @@ macro.
 SV *
 Perl_newSV(pTHX_ STRLEN len)
 {
+    dVAR;
     register SV *sv;
 
     new_SV(sv);
@@ -4006,9 +4149,10 @@ to contain an C<SV*> and is stored as-is with its REFCNT incremented.
 =cut
 */
 MAGIC *        
-Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, const MGVTBL *vtable,
+Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, MGVTBL *vtable,
                 const char* name, I32 namlen)
 {
+    dVAR;
     MAGIC* mg;
 
     if (SvTYPE(sv) < SVt_PVMG) {
@@ -4093,7 +4237,8 @@ to add more than one instance of the same 'how'.
 void
 Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 namlen)
 {
-    const MGVTBL *vtable;
+    dVAR;
+    MGVTBL *vtable;
     MAGIC* mg;
 
 #ifdef PERL_OLD_COPY_ON_WRITE
@@ -4298,7 +4443,8 @@ Perl_sv_unmagic(pTHX_ SV *sv, int type)
     }
     if (!SvMAGIC(sv)) {
        SvMAGICAL_off(sv);
-       SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+       SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+       SvMAGIC_set(sv, NULL);
     }
 
     return 0;
@@ -4342,16 +4488,46 @@ Perl_sv_rvweaken(pTHX_ SV *sv)
 void
 Perl_sv_add_backref(pTHX_ SV *tsv, SV *sv)
 {
+    dVAR;
     AV *av;
-    MAGIC *mg;
-    if (SvMAGICAL(tsv) && (mg = mg_find(tsv, PERL_MAGIC_backref)))
-       av = (AV*)mg->mg_obj;
-    else {
-       av = newAV();
-       sv_magic(tsv, (SV*)av, PERL_MAGIC_backref, NULL, 0);
-       /* av now has a refcnt of 2, which avoids it getting freed
-        * before us during global cleanup. The extra ref is removed
-        * by magic_killbackrefs() when tsv is being freed */
+
+    if (SvTYPE(tsv) == SVt_PVHV) {
+       AV **const avp = Perl_hv_backreferences_p(aTHX_ (HV*)tsv);
+
+       av = *avp;
+       if (!av) {
+           /* There is no AV in the offical place - try a fixup.  */
+           MAGIC *const mg = mg_find(tsv, PERL_MAGIC_backref);
+
+           if (mg) {
+               /* Aha. They've got it stowed in magic.  Bring it back.  */
+               av = (AV*)mg->mg_obj;
+               /* Stop mg_free decreasing the refernce count.  */
+               mg->mg_obj = NULL;
+               /* Stop mg_free even calling the destructor, given that
+                  there's no AV to free up.  */
+               mg->mg_virtual = 0;
+               sv_unmagic(tsv, PERL_MAGIC_backref);
+           } else {
+               av = newAV();
+               AvREAL_off(av);
+               SvREFCNT_inc(av);
+           }
+           *avp = av;
+       }
+    } else {
+       const MAGIC *const mg
+           = SvMAGICAL(tsv) ? mg_find(tsv, PERL_MAGIC_backref) : NULL;
+       if (mg)
+           av = (AV*)mg->mg_obj;
+       else {
+           av = newAV();
+           AvREAL_off(av);
+           sv_magic(tsv, (SV*)av, PERL_MAGIC_backref, NULL, 0);
+           /* av now has a refcnt of 2, which avoids it getting freed
+            * before us during global cleanup. The extra ref is removed
+            * by magic_killbackrefs() when tsv is being freed */
+       }
     }
     if (AvFILLp(av) >= AvMAX(av)) {
         av_extend(av, AvFILLp(av)+1);
@@ -4366,17 +4542,33 @@ Perl_sv_add_backref(pTHX_ SV *tsv, SV *sv)
 STATIC void
 S_sv_del_backref(pTHX_ SV *tsv, SV *sv)
 {
-    AV *av;
+    dVAR;
+    AV *av = NULL;
     SV **svp;
     I32 i;
-    MAGIC *mg = NULL;
-    if (!SvMAGICAL(tsv) || !(mg = mg_find(tsv, PERL_MAGIC_backref))) {
+
+    if (SvTYPE(tsv) == SVt_PVHV && SvOOK(tsv)) {
+       av = *Perl_hv_backreferences_p(aTHX_ (HV*)tsv);
+       /* We mustn't attempt to "fix up" the hash here by moving the
+          backreference array back to the hv_aux structure, as that is stored
+          in the main HvARRAY(), and hfreentries assumes that no-one
+          reallocates HvARRAY() while it is running.  */
+    }
+    if (!av) {
+       const MAGIC *const mg
+           = SvMAGICAL(tsv) ? mg_find(tsv, PERL_MAGIC_backref) : NULL;
+       if (mg)
+           av = (AV *)mg->mg_obj;
+    }
+    if (!av) {
        if (PL_in_clean_all)
            return;
-    }
-    if (!SvMAGICAL(tsv) || !(mg = mg_find(tsv, PERL_MAGIC_backref)))
        Perl_croak(aTHX_ "panic: del_backref");
-    av = (AV *)mg->mg_obj;
+    }
+
+    if (SvIS_FREED(av))
+       return;
+
     svp = AvARRAY(av);
     /* We shouldn't be in here more than once, but for paranoia reasons lets
        not assume this.  */
@@ -4391,12 +4583,53 @@ S_sv_del_backref(pTHX_ SV *tsv, SV *sv)
                */
                svp[i] = svp[fill];
            }
-           svp[fill] = Nullsv;
+           svp[fill] = NULL;
            AvFILLp(av) = fill - 1;
        }
     }
 }
 
+int
+Perl_sv_kill_backrefs(pTHX_ SV *sv, AV *av)
+{
+    SV **svp = AvARRAY(av);
+
+    PERL_UNUSED_ARG(sv);
+
+    /* Not sure why the av can get freed ahead of its sv, but somehow it does
+       in ext/B/t/bytecode.t test 15 (involving print <DATA>)  */
+    if (svp && !SvIS_FREED(av)) {
+       SV *const *const last = svp + AvFILLp(av);
+
+       while (svp <= last) {
+           if (*svp) {
+               SV *const referrer = *svp;
+               if (SvWEAKREF(referrer)) {
+                   /* XXX Should we check that it hasn't changed? */
+                   SvRV_set(referrer, 0);
+                   SvOK_off(referrer);
+                   SvWEAKREF_off(referrer);
+               } else if (SvTYPE(referrer) == SVt_PVGV ||
+                          SvTYPE(referrer) == SVt_PVLV) {
+                   /* You lookin' at me?  */
+                   assert(GvSTASH(referrer));
+                   assert(GvSTASH(referrer) == (HV*)sv);
+                   GvSTASH(referrer) = 0;
+               } else {
+                   Perl_croak(aTHX_
+                              "panic: magic_killbackrefs (flags=%"UVxf")",
+                              (UV)SvFLAGS(referrer));
+               }
+
+               *svp = NULL;
+           }
+           svp++;
+       }
+    }
+    SvREFCNT_dec(av); /* remove extra count added by sv_add_backref() */
+    return 0;
+}
+
 /*
 =for apidoc sv_insert
 
@@ -4409,6 +4642,7 @@ the Perl substr() function.
 void
 Perl_sv_insert(pTHX_ SV *bigstr, STRLEN offset, STRLEN len, const char *little, STRLEN littlelen)
 {
+    dVAR;
     register char *big;
     register char *mid;
     register char *midend;
@@ -4506,6 +4740,7 @@ time you'll want to use C<sv_setsv> or one of its many macro front-ends.
 void
 Perl_sv_replace(pTHX_ register SV *sv, register SV *nsv)
 {
+    dVAR;
     const U32 refcnt = SvREFCNT(sv);
     SV_CHECK_THINKFIRST_COW_DROP(sv);
     if (SvREFCNT(nsv) != 1) {
@@ -4678,6 +4913,7 @@ Perl_sv_clear(pTHX_ register SV *sv)
        cv_undef((CV*)sv);
        goto freescalar;
     case SVt_PVHV:
+       Perl_hv_kill_backrefs(aTHX_ (HV*)sv);
        hv_undef((HV*)sv);
        break;
     case SVt_PVAV:
@@ -5103,15 +5339,13 @@ Perl_sv_pos_u2b(pTHX_ register SV *sv, I32* offsetp, I32* lenp)
     start = (U8*)SvPV_const(sv, len);
     if (len) {
        STRLEN boffset = 0;
-       STRLEN *cache = 0;
+       STRLEN *cache = NULL;
        const U8 *s = start;
        I32 uoffset = *offsetp;
        const U8 * const send = s + len;
-       MAGIC *mg = 0;
-       bool found = FALSE;
+       MAGIC *mg = NULL;
+       bool found = utf8_mg_pos(sv, &mg, &cache, 0, offsetp, *offsetp, &s, start, send);
 
-         if (utf8_mg_pos(sv, &mg, &cache, 0, offsetp, *offsetp, &s, start, send))
-             found = TRUE;
         if (!found && uoffset > 0) {
              while (s < send && uoffset--)
                   s += UTF8SKIP(s);
@@ -5293,13 +5527,14 @@ coerce its args to strings if necessary.
 I32
 Perl_sv_eq(pTHX_ register SV *sv1, register SV *sv2)
 {
+    dVAR;
     const char *pv1;
     STRLEN cur1;
     const char *pv2;
     STRLEN cur2;
     I32  eq     = 0;
-    char *tpv   = Nullch;
-    SV* svrecode = Nullsv;
+    char *tpv   = NULL;
+    SV* svrecode = NULL;
 
     if (!sv1) {
        pv1 = "";
@@ -5388,11 +5623,12 @@ coerce its args to strings if necessary.  See also C<sv_cmp_locale>.
 I32
 Perl_sv_cmp(pTHX_ register SV *sv1, register SV *sv2)
 {
+    dVAR;
     STRLEN cur1, cur2;
     const char *pv1, *pv2;
-    char *tpv = Nullch;
+    char *tpv = NULL;
     I32  cmp;
-    SV *svrecode = Nullsv;
+    SV *svrecode = NULL;
 
     if (!sv1) {
        pv1 = "";
@@ -5471,6 +5707,7 @@ if necessary.  See also C<sv_cmp_locale>.  See also C<sv_cmp>.
 I32
 Perl_sv_cmp_locale(pTHX_ register SV *sv1, register SV *sv2)
 {
+    dVAR;
 #ifdef USE_LOCALE_COLLATE
 
     char *pv1, *pv2;
@@ -5535,6 +5772,7 @@ settings.
 char *
 Perl_sv_collxfrm(pTHX_ SV *sv, STRLEN *nxp)
 {
+    dVAR;
     MAGIC *mg;
 
     mg = SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_collxfrm) : (MAGIC *) NULL;
@@ -5591,6 +5829,7 @@ appending to the currently-stored string.
 char *
 Perl_sv_gets(pTHX_ register SV *sv, register PerlIO *fp, I32 append)
 {
+    dVAR;
     const char *rsptr;
     STRLEN rslen;
     register STDCHAR rslast;
@@ -5618,7 +5857,7 @@ Perl_sv_gets(pTHX_ register SV *sv, register PerlIO *fp, I32 append)
                sv_pos_u2b(sv,&append,0);
            }
        } else if (SvUTF8(sv)) {
-           SV * const tsv = NEWSV(0,0);
+           SV * const tsv = newSV(0);
            sv_gets(tsv, fp, 0);
            sv_utf8_upgrade_nomg(tsv);
            SvCUR_set(sv,append);
@@ -5861,7 +6100,7 @@ thats_really_all_folks:
     {
        /*The big, slow, and stupid way. */
 #ifdef USE_HEAP_INSTEAD_OF_STACK       /* Even slower way. */
-       STDCHAR *buf = 0;
+       STDCHAR *buf = NULL;
        Newx(buf, 8192, STDCHAR);
        assert(buf);
 #else
@@ -5931,7 +6170,7 @@ screamer2:
     }
 
 return_string_or_null:
-    return (SvCUR(sv) - append) ? SvPVX(sv) : Nullch;
+    return (SvCUR(sv) - append) ? SvPVX(sv) : NULL;
 }
 
 /*
@@ -5946,6 +6185,7 @@ if necessary. Handles 'get' magic.
 void
 Perl_sv_inc(pTHX_ register SV *sv)
 {
+    dVAR;
     register char *d;
     int flags;
 
@@ -6102,6 +6342,7 @@ if necessary. Handles 'get' magic.
 void
 Perl_sv_dec(pTHX_ register SV *sv)
 {
+    dVAR;
     int flags;
 
     if (!sv)
@@ -6218,6 +6459,7 @@ statement boundaries.  See also C<sv_newmortal> and C<sv_2mortal>.
 SV *
 Perl_sv_mortalcopy(pTHX_ SV *oldstr)
 {
+    dVAR;
     register SV *sv;
 
     new_SV(sv);
@@ -6242,6 +6484,7 @@ See also C<sv_mortalcopy> and C<sv_2mortal>.
 SV *
 Perl_sv_newmortal(pTHX)
 {
+    dVAR;
     register SV *sv;
 
     new_SV(sv);
@@ -6268,7 +6511,7 @@ Perl_sv_2mortal(pTHX_ register SV *sv)
 {
     dVAR;
     if (!sv)
-       return sv;
+       return NULL;
     if (SvREADONLY(sv) && SvIMMORTAL(sv))
        return sv;
     EXTEND_MORTAL(1);
@@ -6290,6 +6533,7 @@ strlen().  For efficiency, consider using C<newSVpvn> instead.
 SV *
 Perl_newSVpv(pTHX_ const char *s, STRLEN len)
 {
+    dVAR;
     register SV *sv;
 
     new_SV(sv);
@@ -6311,6 +6555,7 @@ C<len> bytes long.  If the C<s> argument is NULL the new SV will be undefined.
 SV *
 Perl_newSVpvn(pTHX_ const char *s, STRLEN len)
 {
+    dVAR;
     register SV *sv;
 
     new_SV(sv);
@@ -6332,6 +6577,7 @@ SV if the hek is NULL.
 SV *
 Perl_newSVhek(pTHX_ const HEK *hek)
 {
+    dVAR;
     if (!hek) {
        SV *sv;
 
@@ -6390,6 +6636,7 @@ hash lookup will avoid string compare.
 SV *
 Perl_newSVpvn_share(pTHX_ const char *src, I32 len, U32 hash)
 {
+    dVAR;
     register SV *sv;
     bool is_utf8 = FALSE;
     if (len < 0) {
@@ -6460,6 +6707,7 @@ Perl_newSVpvf(pTHX_ const char* pat, ...)
 SV *
 Perl_vnewSVpvf(pTHX_ const char* pat, va_list* args)
 {
+    dVAR;
     register SV *sv;
     new_SV(sv);
     sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
@@ -6478,6 +6726,7 @@ The reference count for the SV is set to 1.
 SV *
 Perl_newSVnv(pTHX_ NV n)
 {
+    dVAR;
     register SV *sv;
 
     new_SV(sv);
@@ -6497,6 +6746,7 @@ SV is set to 1.
 SV *
 Perl_newSViv(pTHX_ IV i)
 {
+    dVAR;
     register SV *sv;
 
     new_SV(sv);
@@ -6516,6 +6766,7 @@ The reference count for the SV is set to 1.
 SV *
 Perl_newSVuv(pTHX_ UV u)
 {
+    dVAR;
     register SV *sv;
 
     new_SV(sv);
@@ -6535,6 +6786,7 @@ SV is B<not> incremented.
 SV *
 Perl_newRV_noinc(pTHX_ SV *tmpRef)
 {
+    dVAR;
     register SV *sv;
 
     new_SV(sv);
@@ -6552,6 +6804,7 @@ Perl_newRV_noinc(pTHX_ SV *tmpRef)
 SV *
 Perl_newRV(pTHX_ SV *tmpRef)
 {
+    dVAR;
     return newRV_noinc(SvREFCNT_inc(tmpRef));
 }
 
@@ -6567,14 +6820,15 @@ Creates a new SV which is an exact duplicate of the original SV.
 SV *
 Perl_newSVsv(pTHX_ register SV *old)
 {
+    dVAR;
     register SV *sv;
 
     if (!old)
-       return Nullsv;
+       return NULL;
     if (SvTYPE(old) == SVTYPEMASK) {
         if (ckWARN_d(WARN_INTERNAL))
            Perl_warner(aTHX_ packWARN(WARN_INTERNAL), "semi-panic: attempt to dup freed string");
-       return Nullsv;
+       return NULL;
     }
     new_SV(sv);
     /* SV_GMAGIC is the default for sv_setv()
@@ -6654,7 +6908,7 @@ Perl_sv_reset(pTHX_ register const char *s, HV *stash)
                    SvOK_off(sv);
                    if (SvTYPE(sv) >= SVt_PV) {
                        SvCUR_set(sv, 0);
-                       if (SvPVX_const(sv) != Nullch)
+                       if (SvPVX_const(sv) != NULL)
                            *SvPVX(sv) = '\0';
                        SvTAINT(sv);
                    }
@@ -6709,7 +6963,7 @@ Perl_sv_2io(pTHX_ SV *sv)
            Perl_croak(aTHX_ PL_no_usym, "filehandle");
        if (SvROK(sv))
            return sv_2io(SvRV(sv));
-       gv = gv_fetchsv(sv, FALSE, SVt_PVIO);
+       gv = gv_fetchsv(sv, 0, SVt_PVIO);
        if (gv)
            io = GvIO(gv);
        else
@@ -6726,6 +6980,7 @@ Perl_sv_2io(pTHX_ SV *sv)
 
 Using various gambits, try to get a CV from an SV; in addition, try if
 possible to set C<*st> and C<*gvp> to the stash and GV associated with it.
+The flags in C<lref> are passed to sv_fetchsv.
 
 =cut
 */
@@ -6734,20 +6989,21 @@ CV *
 Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref)
 {
     dVAR;
-    GV *gv = Nullgv;
-    CV *cv = Nullcv;
+    GV *gv = NULL;
+    CV *cv = NULL;
 
     if (!sv)
-       return *gvp = Nullgv, Nullcv;
+       return *st = NULL, *gvp = NULL, NULL;
     switch (SvTYPE(sv)) {
     case SVt_PVCV:
        *st = CvSTASH(sv);
-       *gvp = Nullgv;
+       *gvp = NULL;
        return (CV*)sv;
     case SVt_PVHV:
     case SVt_PVAV:
-       *gvp = Nullgv;
-       return Nullcv;
+       *st = NULL;
+       *gvp = NULL;
+       return NULL;
     case SVt_PVGV:
        gv = (GV*)sv;
        *gvp = gv;
@@ -6763,7 +7019,7 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref)
            sv = SvRV(sv);
            if (SvTYPE(sv) == SVt_PVCV) {
                cv = (CV*)sv;
-               *gvp = Nullgv;
+               *gvp = NULL;
                *st = CvSTASH(cv);
                return cv;
            }
@@ -6777,15 +7033,22 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref)
        else
            gv = gv_fetchsv(sv, lref, SVt_PVCV);
        *gvp = gv;
-       if (!gv)
-           return Nullcv;
+       if (!gv) {
+           *st = NULL;
+           return NULL;
+       }
+       /* Some flags to gv_fetchsv mean don't really create the GV  */
+       if (SvTYPE(gv) != SVt_PVGV) {
+           *st = NULL;
+           return NULL;
+       }
        *st = GvESTASH(gv);
     fix_gv:
        if (lref && !GvCVu(gv)) {
            SV *tmpsv;
            ENTER;
-           tmpsv = NEWSV(704,0);
-           gv_efullname3(tmpsv, gv, Nullch);
+           tmpsv = newSV(0);
+           gv_efullname3(tmpsv, gv, NULL);
            /* XXX this is probably not what they think they're getting.
             * It has the same effect as "sub name;", i.e. just a forward
             * declaration! */
@@ -6860,7 +7123,7 @@ C<SvPV_force> and C<SvPV_force_nomg>
 char *
 Perl_sv_pvn_force_flags(pTHX_ SV *sv, STRLEN *lp, I32 flags)
 {
-
+    dVAR;
     if (SvTHINKFIRST(sv) && !SvROK(sv))
         sv_force_normal_flags(sv, 0);
 
@@ -7058,6 +7321,7 @@ reference count is 1.
 SV*
 Perl_newSVrv(pTHX_ SV *rv, const char *classname)
 {
+    dVAR;
     SV *sv;
 
     new_SV(sv);
@@ -7099,7 +7363,7 @@ Copies a pointer into a new SV, optionally blessing the SV.  The C<rv>
 argument will be upgraded to an RV.  That RV will be modified to point to
 the new SV.  If the C<pv> argument is NULL then C<PL_sv_undef> will be placed
 into the SV.  The C<classname> argument indicates the package for the
-blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+blessing.  Set C<classname> to C<NULL> to avoid the blessing.  The new SV
 will have a reference count of 1, and the RV will be returned.
 
 Do not use with other Perl types such as HV, AV, SV, CV, because those
@@ -7113,6 +7377,7 @@ Note that C<sv_setref_pvn> copies the string while this copies the pointer.
 SV*
 Perl_sv_setref_pv(pTHX_ SV *rv, const char *classname, void *pv)
 {
+    dVAR;
     if (!pv) {
        sv_setsv(rv, &PL_sv_undef);
        SvSETMAGIC(rv);
@@ -7128,7 +7393,7 @@ Perl_sv_setref_pv(pTHX_ SV *rv, const char *classname, void *pv)
 Copies an integer into a new SV, optionally blessing the SV.  The C<rv>
 argument will be upgraded to an RV.  That RV will be modified to point to
 the new SV.  The C<classname> argument indicates the package for the
-blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+blessing.  Set C<classname> to C<NULL> to avoid the blessing.  The new SV
 will have a reference count of 1, and the RV will be returned.
 
 =cut
@@ -7147,7 +7412,7 @@ Perl_sv_setref_iv(pTHX_ SV *rv, const char *classname, IV iv)
 Copies an unsigned integer into a new SV, optionally blessing the SV.  The C<rv>
 argument will be upgraded to an RV.  That RV will be modified to point to
 the new SV.  The C<classname> argument indicates the package for the
-blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+blessing.  Set C<classname> to C<NULL> to avoid the blessing.  The new SV
 will have a reference count of 1, and the RV will be returned.
 
 =cut
@@ -7166,7 +7431,7 @@ Perl_sv_setref_uv(pTHX_ SV *rv, const char *classname, UV uv)
 Copies a double into a new SV, optionally blessing the SV.  The C<rv>
 argument will be upgraded to an RV.  That RV will be modified to point to
 the new SV.  The C<classname> argument indicates the package for the
-blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+blessing.  Set C<classname> to C<NULL> to avoid the blessing.  The new SV
 will have a reference count of 1, and the RV will be returned.
 
 =cut
@@ -7186,7 +7451,7 @@ Copies a string into a new SV, optionally blessing the SV.  The length of the
 string must be specified with C<n>.  The C<rv> argument will be upgraded to
 an RV.  That RV will be modified to point to the new SV.  The C<classname>
 argument indicates the package for the blessing.  Set C<classname> to
-C<Nullch> to avoid the blessing.  The new SV will have a reference count
+C<NULL> to avoid the blessing.  The new SV will have a reference count
 of 1, and the RV will be returned.
 
 Note that C<sv_setref_pv> copies the pointer while this copies the string.
@@ -7214,6 +7479,7 @@ of the SV is unaffected.
 SV*
 Perl_sv_bless(pTHX_ SV *sv, HV *stash)
 {
+    dVAR;
     SV *tmpRef;
     if (!SvROK(sv))
         Perl_croak(aTHX_ "Can't bless non-reference value");
@@ -7253,6 +7519,7 @@ Perl_sv_bless(pTHX_ SV *sv, HV *stash)
 STATIC void
 S_sv_unglob(pTHX_ SV *sv)
 {
+    dVAR;
     void *xpvmg;
 
     assert(SvTYPE(sv) == SVt_PVGV);
@@ -7261,7 +7528,7 @@ S_sv_unglob(pTHX_ SV *sv)
        gp_free((GV*)sv);
     if (GvSTASH(sv)) {
        sv_del_backref((SV*)GvSTASH(sv), sv);
-       GvSTASH(sv) = Nullhv;
+       GvSTASH(sv) = NULL;
     }
     sv_unmagic(sv, PERL_MAGIC_glob);
     Safefree(GvNAME(sv));
@@ -7607,11 +7874,10 @@ Perl_sv_vsetpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     sv_vcatpvfn(sv, pat, patlen, args, svargs, svmax, maybe_tainted);
 }
 
-/* private function for use in sv_vcatpvfn via the EXPECT_NUMBER macro */
-
 STATIC I32
 S_expect_number(pTHX_ char** pattern)
 {
+    dVAR;
     I32 var = 0;
     switch (**pattern) {
     case '1': case '2': case '3':
@@ -7627,10 +7893,9 @@ S_expect_number(pTHX_ char** pattern)
     }
     return var;
 }
-#define EXPECT_NUMBER(pattern, var) (var = S_expect_number(aTHX_ &pattern))
 
-static char *
-F0convert(NV nv, char *endbuf, STRLEN *len)
+STATIC char *
+S_F0convert(NV nv, char *endbuf, STRLEN *len)
 {
     const int neg = nv < 0;
     UV uv;
@@ -7652,7 +7917,7 @@ F0convert(NV nv, char *endbuf, STRLEN *len)
        *len = endbuf - p;
        return p;
     }
-    return Nullch;
+    return NULL;
 }
 
 
@@ -7680,16 +7945,17 @@ Usually used via one of its frontends C<sv_vcatpvf> and C<sv_vcatpvf_mg>.
 void
 Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, bool *maybe_tainted)
 {
+    dVAR;
     char *p;
     char *q;
     const char *patend;
     STRLEN origlen;
     I32 svix = 0;
     static const char nullstr[] = "(null)";
-    SV *argsv = Nullsv;
+    SV *argsv = NULL;
     bool has_utf8 = DO_UTF8(sv);    /* has the result utf8? */
     const bool pat_utf8 = has_utf8; /* the pattern is in utf8? */
-    SV *nsv = Nullsv;
+    SV *nsv = NULL;
     /* Times 4: a decimal digit takes more than 3 binary digits.
      * NV_DIG: mantissa takes than many decimal digits.
      * Plus 32: Playing safe. */
@@ -7779,7 +8045,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        STRLEN zeros = 0;
        bool has_precis = FALSE;
        STRLEN precis = 0;
-       I32 osvix = svix;
+       const I32 osvix = svix;
        bool is_utf8 = FALSE;  /* is this item utf8?   */
 #ifdef HAS_LDBL_SPRINTF_BUG
        /* This is to try to fix a bug with irix/nonstop-ux/powerux and
@@ -7791,9 +8057,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        U8 utf8buf[UTF8_MAXBYTES+1];
        STRLEN esignlen = 0;
 
-       const char *eptr = Nullch;
+       const char *eptr = NULL;
        STRLEN elen = 0;
-       SV *vecsv = Nullsv;
+       SV *vecsv = NULL;
        const U8 *vecstr = Null(U8*);
        STRLEN veclen = 0;
        char c = 0;
@@ -7866,7 +8132,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            STRLEN n = 0;
            if (*q == '-')
                sv = *q++;
-           EXPECT_NUMBER(q, n);
+           n = expect_number(&q);
            if (*q++ == 'p') {
                if (sv) {                       /* SVf */
                    if (n) {
@@ -7895,7 +8161,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            q = r; 
        }
 
-       if (EXPECT_NUMBER(q, width)) {
+       if ( (width = expect_number(&q)) ) {
            if (*q == '$') {
                ++q;
                efix = width;
@@ -7936,7 +8202,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
       tryasterisk:
        if (*q == '*') {
            q++;
-           if (EXPECT_NUMBER(q, ewix))
+           if ( (ewix = expect_number(&q)) )
                if (*q++ != '$')
                    goto unknown;
            asterisk = TRUE;
@@ -7958,7 +8224,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        {
            if( *q == '0' )
                fill = *q++;
-           EXPECT_NUMBER(q, width);
+           width = expect_number(&q);
        }
 
        if (vectorize) {
@@ -7997,6 +8263,11 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                 */
                if (sv_derived_from(vecsv, "version")) {
                    char *version = savesvpv(vecsv);
+                   if ( hv_exists((HV*)SvRV(vecsv), "alpha", 5 ) ) {
+                       Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
+                       "vector argument not supported with alpha versions");
+                       goto unknown;
+                   }
                    vecsv = sv_newmortal();
                    /* scan_vstring is expected to be called during
                     * tokenization, so we need to fake up the end
@@ -8032,7 +8303,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            q++;
            if (*q == '*') {
                q++;
-               if (EXPECT_NUMBER(q, epix) && *q++ != '$')
+               if ( ((epix = expect_number(&q))) && (*q++ != '$') )
                    goto unknown;
                /* XXX: todo, support specified precision parameter */
                if (epix)
@@ -8632,7 +8903,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                                       "\"%%\\%03"UVof"\"",
                                       (UV)c & 0xFF);
                } else
-                   sv_catpv(msg, "end of string");
+                   sv_catpvs(msg, "end of string");
                Perl_warner(aTHX_ packWARN(WARN_PRINTF), "%"SVf, msg); /* yes, this is reentrant */
            }
 
@@ -8764,8 +9035,8 @@ ptr_table_* functions.
 #define io_dup_inc(s,t)        (IO*)SvREFCNT_inc(sv_dup((SV*)s,t))
 #define gv_dup(s,t)    (GV*)sv_dup((SV*)s,t)
 #define gv_dup_inc(s,t)        (GV*)SvREFCNT_inc(sv_dup((SV*)s,t))
-#define SAVEPV(p)      (p ? savepv(p) : Nullch)
-#define SAVEPVN(p,n)   (p ? savepvn(p,n) : Nullch)
+#define SAVEPV(p)      ((p) ? savepv(p) : NULL)
+#define SAVEPVN(p,n)   ((p) ? savepvn(p,n) : NULL)
 
 
 /* Duplicate a regexp. Required reading: pregcomp() and pregfree() in
@@ -8876,9 +9147,9 @@ Perl_re_dup(pTHX_ const REGEXP *r, CLONE_PARAMS *param)
     if (RX_MATCH_COPIED(ret))
        ret->subbeg  = SAVEPVN(r->subbeg, r->sublen);
     else
-       ret->subbeg = Nullch;
+       ret->subbeg = NULL;
 #ifdef PERL_OLD_COPY_ON_WRITE
-    ret->saved_copy = Nullsv;
+    ret->saved_copy = NULL;
 #endif
 
     ptr_table_store(PL_ptr_table, r, ret);
@@ -8980,15 +9251,9 @@ Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS* param)
            nmg->mg_obj = (SV*)re_dup((REGEXP*)mg->mg_obj, param);
        }
        else if(mg->mg_type == PERL_MAGIC_backref) {
-           const AV * const av = (AV*) mg->mg_obj;
-           SV **svp;
-           I32 i;
-           (void)SvREFCNT_inc(nmg->mg_obj = (SV*)newAV());
-           svp = AvARRAY(av);
-           for (i = AvFILLp(av); i >= 0; i--) {
-               if (!svp[i]) continue;
-               av_push((AV*)nmg->mg_obj,sv_dup(svp[i],param));
-           }
+           /* The backref AV has its reference count deliberately bumped by
+              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;
@@ -9006,7 +9271,7 @@ Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS* param)
                if (mg->mg_type == PERL_MAGIC_overload_table &&
                        AMT_AMAGIC((AMT*)mg->mg_ptr))
                {
-                   AMT * const amtp = (AMT*)mg->mg_ptr;
+                   const AMT * const amtp = (AMT*)mg->mg_ptr;
                    AMT * const namtp = (AMT*)nmg->mg_ptr;
                    I32 i;
                    for (i = 1; i < NofAMmeth; i++) {
@@ -9132,7 +9397,7 @@ void
 Perl_ptr_table_clear(pTHX_ PTR_TBL_t *tbl)
 {
     if (tbl && tbl->tbl_items) {
-       register PTR_TBL_ENT_t **array = tbl->tbl_ary;
+       register PTR_TBL_ENT_t * const * const array = tbl->tbl_ary;
        UV riter = tbl->tbl_max;
 
        do {
@@ -9164,7 +9429,7 @@ Perl_ptr_table_free(pTHX_ PTR_TBL_t *tbl)
 
 
 void
-Perl_rvpv_dup(pTHX_ SV *dstr, SV *sstr, CLONE_PARAMS* param)
+Perl_rvpv_dup(pTHX_ SV *dstr, const SV *sstr, CLONE_PARAMS* param)
 {
     if (SvROK(sstr)) {
        SvRV_set(dstr, SvWEAKREF(sstr)
@@ -9203,20 +9468,20 @@ Perl_rvpv_dup(pTHX_ SV *dstr, SV *sstr, CLONE_PARAMS* param)
        if (SvTYPE(dstr) == SVt_RV)
            SvRV_set(dstr, NULL);
        else
-           SvPV_set(dstr, 0);
+           SvPV_set(dstr, NULL);
     }
 }
 
 /* duplicate an SV of any type (including AV, HV etc) */
 
 SV *
-Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
+Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
 {
     dVAR;
     SV *dstr;
 
     if (!sstr || SvTYPE(sstr) == SVTYPEMASK)
-       return Nullsv;
+       return NULL;
     /* look for it in the table first */
     dstr = (SV*)ptr_table_fetch(PL_ptr_table, sstr);
     if (dstr)
@@ -9225,12 +9490,11 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
     if(param->flags & CLONEf_JOIN_IN) {
         /** We are joining here so we don't want do clone
            something that is bad **/
-       const char *hvname;
-
-        if(SvTYPE(sstr) == SVt_PVHV &&
-          (hvname = HvNAME_get(sstr))) {
-           /** don't clone stashes if they already exist **/
-           return (SV*)gv_stashpv(hvname,0);
+       if (SvTYPE(sstr) == SVt_PVHV) {
+           const char * const hvname = HvNAME_get(sstr);
+           if (hvname)
+               /** don't clone stashes if they already exist **/
+               return (SV*)gv_stashpv(hvname,0);
         }
     }
 
@@ -9242,11 +9506,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
     dstr->sv_debug_line = sstr->sv_debug_line;
     dstr->sv_debug_inpad = sstr->sv_debug_inpad;
     dstr->sv_debug_cloned = 1;
-#  ifdef NETWARE
     dstr->sv_debug_file = savepv(sstr->sv_debug_file);
-#  else
-    dstr->sv_debug_file = savesharedpv(sstr->sv_debug_file);
-#  endif
 #endif
 
     ptr_table_store(PL_ptr_table, sstr, dstr);
@@ -9429,13 +9689,13 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
                    }
                }
                else {
-                   SvPV_set(dstr, Nullch);
+                   SvPV_set(dstr, NULL);
                    AvALLOC((AV*)dstr)  = (SV**)NULL;
                }
                break;
            case SVt_PVHV:
                {
-                   HEK *hvname = 0;
+                   HEK *hvname = NULL;
 
                    if (HvARRAY((HV*)sstr)) {
                        STRLEN i = 0;
@@ -9468,10 +9728,16 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
                            daux->xhv_eiter = saux->xhv_eiter
                                ? he_dup(saux->xhv_eiter,
                                         (bool)!!HvSHAREKEYS(sstr), param) : 0;
+                           daux->xhv_backreferences = saux->xhv_backreferences
+                               ? (AV*) SvREFCNT_inc(
+                                                    sv_dup((SV*)saux->
+                                                           xhv_backreferences,
+                                                           param))
+                               : 0;
                        }
                    }
                    else {
-                       SvPV_set(dstr, Nullch);
+                       SvPV_set(dstr, NULL);
                    }
                    /* Record stashes for possible cloning in Perl_clone(). */
                    if(hvname)
@@ -9493,7 +9759,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
                /* don't dup if copying back - CvGV isn't refcounted, so the
                 * duped GV may never be freed. A bit of a hack! DAPM */
                CvGV(dstr)      = (param->flags & CLONEf_JOIN_IN) ?
-                   Nullgv : gv_dup(CvGV(dstr), param) ;
+                   NULL : gv_dup(CvGV(dstr), param) ;
                if (!(param->flags & CLONEf_COPY_STACKS)) {
                    CvDEPTH(dstr) = 0;
                }
@@ -9535,8 +9801,8 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param)
     ptr_table_store(PL_ptr_table, cxs, ncxs);
 
     while (ix >= 0) {
-       PERL_CONTEXT *cx = &cxs[ix];
-       PERL_CONTEXT *ncx = &ncxs[ix];
+       PERL_CONTEXT * const cx = &cxs[ix];
+       PERL_CONTEXT * const ncx = &ncxs[ix];
        ncx->cx_type    = cx->cx_type;
        if (CxTYPE(cx) == CXt_SUBST) {
            Perl_croak(aTHX_ "Cloning substitution context is unimplemented");
@@ -9555,7 +9821,7 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param)
                                           : cv_dup(cx->blk_sub.cv,param));
                ncx->blk_sub.argarray   = (cx->blk_sub.hasargs
                                           ? av_dup_inc(cx->blk_sub.argarray, param)
-                                          : Nullav);
+                                          : NULL);
                ncx->blk_sub.savearray  = av_dup_inc(cx->blk_sub.savearray, param);
                ncx->blk_sub.olddepth   = cx->blk_sub.olddepth;
                ncx->blk_sub.hasargs    = cx->blk_sub.hasargs;
@@ -10129,15 +10395,17 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     param->flags = flags;
     param->proto_perl = proto_perl;
 
-    Zero(&PL_body_arenaroots, 1, PL_body_arenaroots);
+    INIT_TRACK_MEMPOOL(my_perl->Imemory_debug_header, my_perl);
+
+    PL_body_arenas = NULL;
     Zero(&PL_body_roots, 1, PL_body_roots);
     
     PL_nice_chunk      = NULL;
     PL_nice_chunk_size = 0;
     PL_sv_count                = 0;
     PL_sv_objcount     = 0;
-    PL_sv_root         = Nullsv;
-    PL_sv_arenaroot    = Nullsv;
+    PL_sv_root         = NULL;
+    PL_sv_arenaroot    = NULL;
 
     PL_debug           = proto_perl->Idebug;
 
@@ -10237,6 +10505,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_minus_p         = proto_perl->Iminus_p;
     PL_minus_l         = proto_perl->Iminus_l;
     PL_minus_a         = proto_perl->Iminus_a;
+    PL_minus_E         = proto_perl->Iminus_E;
     PL_minus_F         = proto_perl->Iminus_F;
     PL_doswitches      = proto_perl->Idoswitches;
     PL_dowarn          = proto_perl->Idowarn;
@@ -10272,20 +10541,20 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_regex_padav = newAV();
     {
        const I32 len = av_len((AV*)proto_perl->Iregex_padav);
-       SV** const regexen = AvARRAY((AV*)proto_perl->Iregex_padav);
+       SV* const * const regexen = AvARRAY((AV*)proto_perl->Iregex_padav);
        IV i;
        av_push(PL_regex_padav,
                sv_dup_inc(regexen[0],param));
        for(i = 1; i <= len; i++) {
-            if(SvREPADTMP(regexen[i])) {
-             av_push(PL_regex_padav, sv_dup_inc(regexen[i], param));
-            } else {
-               av_push(PL_regex_padav,
-                    SvREFCNT_inc(
-                        newSViv(PTR2IV(re_dup(INT2PTR(REGEXP *,
-                             SvIVX(regexen[i])), param)))
-                       ));
-           }
+           const SV * const regex = regexen[i];
+           SV * const sv =
+               SvREPADTMP(regex)
+                   ? sv_dup_inc(regex, param)
+                   : SvREFCNT_inc(
+                       newSViv(PTR2IV(re_dup(
+                               INT2PTR(REGEXP *, SvIVX(regex)), param))))
+               ;
+           av_push(PL_regex_padav, sv);
        }
     }
     PL_regex_pad = AvARRAY(PL_regex_padav);
@@ -10342,7 +10611,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     if (proto_perl->Iop_mask)
        PL_op_mask      = SAVEPVN(proto_perl->Iop_mask, PL_maxo);
     else
-       PL_op_mask      = Nullch;
+       PL_op_mask      = NULL;
     /* PL_asserting        = proto_perl->Iasserting; */
 
     /* current interpreter roots */
@@ -10360,13 +10629,13 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_lastfd          = proto_perl->Ilastfd;
     PL_oldname         = proto_perl->Ioldname;         /* XXX not quite right */
     PL_Argv            = NULL;
-    PL_Cmd             = Nullch;
+    PL_Cmd             = NULL;
     PL_gensym          = proto_perl->Igensym;
     PL_preambled       = proto_perl->Ipreambled;
     PL_preambleav      = av_dup_inc(proto_perl->Ipreambleav, param);
     PL_laststatval     = proto_perl->Ilaststatval;
     PL_laststype       = proto_perl->Ilaststype;
-    PL_mess_sv         = Nullsv;
+    PL_mess_sv         = NULL;
 
     PL_ors_sv          = sv_dup_inc(proto_perl->Iors_sv, param);
 
@@ -10378,6 +10647,14 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     }
     else
        PL_exitlist     = (PerlExitListEntry*)NULL;
+
+    PL_my_cxt_size = proto_perl->Imy_cxt_size;
+    if (PL_my_cxt_size) {
+       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 *);
+    }
+    else
+       PL_my_cxt_list  = (void**)NULL;
     PL_modglobal       = hv_dup_inc(proto_perl->Imodglobal, param);
     PL_custom_op_names  = hv_dup_inc(proto_perl->Icustom_op_names,param);
     PL_custom_op_descs  = hv_dup_inc(proto_perl->Icustom_op_descs,param);
@@ -10465,7 +10742,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        PL_linestart    = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
     }
     else {
-        PL_linestr = NEWSV(65,79);
+        PL_linestr = newSV(79);
         sv_upgrade(PL_linestr,SVt_PVIV);
         sv_setpvn(PL_linestr,"",0);
        PL_bufptr = PL_oldbufptr = PL_oldoldbufptr = PL_linestart = SvPVX(PL_linestr);
@@ -10580,7 +10857,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 #endif
 
     /* swatch cache */
-    PL_last_swash_hv   = Nullhv;       /* reinits on demand */
+    PL_last_swash_hv   = NULL; /* reinits on demand */
     PL_last_swash_klen = 0;
     PL_last_swash_key[0]= '\0';
     PL_last_swash_tmps = (U8*)NULL;
@@ -10589,7 +10866,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_glob_index      = proto_perl->Iglob_index;
     PL_srand_called    = proto_perl->Isrand_called;
     PL_uudmap['M']     = 0;            /* reinits on demand */
-    PL_bitcount                = Nullch;       /* reinits on demand */
+    PL_bitcount                = NULL; /* reinits on demand */
 
     if (proto_perl->Ipsig_pend) {
        Newxz(PL_psig_pend, SIG_SIZE, int);
@@ -10665,6 +10942,20 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     else {
        init_stacks();
        ENTER;                  /* perl_destruct() wants to LEAVE; */
+
+       /* although we're not duplicating the tmps stack, we should still
+        * add entries for any SVs on the tmps stack that got cloned by a
+        * non-refcount means (eg a temp in @_); otherwise they will be
+        * orphaned
+        */
+       for (i = 0; i<= proto_perl->Ttmps_ix; i++) {
+           SV * const nsv = (SV*)ptr_table_fetch(PL_ptr_table,
+                   proto_perl->Ttmps_stack[i]);
+           if (nsv && !SvREFCNT(nsv)) {
+               EXTEND_MORTAL(1);
+               PL_tmps_stack[++PL_tmps_ix] = SvREFCNT_inc(nsv);
+           }
+       }
     }
 
     PL_start_env       = proto_perl->Tstart_env;       /* XXXXXX */
@@ -10672,7 +10963,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_op              = proto_perl->Top;
 
-    PL_Sv              = Nullsv;
+    PL_Sv              = NULL;
     PL_Xpv             = (XPV*)NULL;
     PL_na              = proto_perl->Tna;
 
@@ -10711,7 +11002,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_sortstash       = hv_dup(proto_perl->Tsortstash, param);
     PL_firstgv         = gv_dup(proto_perl->Tfirstgv, param);
     PL_secondgv                = gv_dup(proto_perl->Tsecondgv, param);
-    PL_efloatbuf       = Nullch;               /* reinits on demand */
+    PL_efloatbuf       = NULL;         /* reinits on demand */
     PL_efloatsize      = 0;                    /* reinits on demand */
 
     /* regex stuff */
@@ -10719,29 +11010,29 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_screamfirst     = NULL;
     PL_screamnext      = NULL;
     PL_maxscream       = -1;                   /* reinits on demand */
-    PL_lastscream      = Nullsv;
+    PL_lastscream      = NULL;
 
     PL_watchaddr       = NULL;
-    PL_watchok         = Nullch;
+    PL_watchok         = NULL;
 
     PL_regdummy                = proto_perl->Tregdummy;
-    PL_regprecomp      = Nullch;
+    PL_regprecomp      = NULL;
     PL_regnpar         = 0;
     PL_regsize         = 0;
     PL_colorset                = 0;            /* reinits PL_colors[] */
     /*PL_colors[6]     = {0,0,0,0,0,0};*/
-    PL_reginput                = Nullch;
-    PL_regbol          = Nullch;
-    PL_regeol          = Nullch;
+    PL_reginput                = NULL;
+    PL_regbol          = NULL;
+    PL_regeol          = NULL;
     PL_regstartp       = (I32*)NULL;
     PL_regendp         = (I32*)NULL;
     PL_reglastparen    = (U32*)NULL;
     PL_reglastcloseparen       = (U32*)NULL;
-    PL_regtill         = Nullch;
+    PL_regtill         = NULL;
     PL_reg_start_tmp   = (char**)NULL;
     PL_reg_start_tmpl  = 0;
     PL_regdata         = (struct reg_data*)NULL;
-    PL_bostr           = Nullch;
+    PL_bostr           = NULL;
     PL_reg_flags       = 0;
     PL_reg_eval_set    = 0;
     PL_regnarrate      = 0;
@@ -10750,21 +11041,21 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_regcc           = (CURCUR*)NULL;
     PL_reg_call_cc     = (struct re_cc_state*)NULL;
     PL_reg_re          = (regexp*)NULL;
-    PL_reg_ganch       = Nullch;
-    PL_reg_sv          = Nullsv;
+    PL_reg_ganch       = NULL;
+    PL_reg_sv          = NULL;
     PL_reg_match_utf8  = FALSE;
     PL_reg_magic       = (MAGIC*)NULL;
     PL_reg_oldpos      = 0;
     PL_reg_oldcurpm    = (PMOP*)NULL;
     PL_reg_curpm       = (PMOP*)NULL;
-    PL_reg_oldsaved    = Nullch;
+    PL_reg_oldsaved    = NULL;
     PL_reg_oldsavedlen = 0;
 #ifdef PERL_OLD_COPY_ON_WRITE
-    PL_nrs             = Nullsv;
+    PL_nrs             = NULL;
 #endif
     PL_reg_maxiter     = 0;
     PL_reg_leftiter    = 0;
-    PL_reg_poscache    = Nullch;
+    PL_reg_poscache    = NULL;
     PL_reg_poscache_size= 0;
 
     /* RE engine - function pointers */
@@ -10953,7 +11244,7 @@ S_find_hash_subscript(pTHX_ HV *hv, SV* val)
 
     if (!hv || SvMAGICAL(hv) || !HvARRAY(hv) ||
                        (HvTOTALKEYS(hv) > FUV_MAX_SEARCH_SIZE))
-       return Nullsv;
+       return NULL;
 
     array = HvARRAY(hv);
 
@@ -10966,13 +11257,13 @@ S_find_hash_subscript(pTHX_ HV *hv, SV* val)
                    HeVAL(entry) == &PL_sv_placeholder)
                continue;
            if (!HeKEY(entry))
-               return Nullsv;
+               return NULL;
            if (HeKLEN(entry) == HEf_SVKEY)
                return sv_mortalcopy(HeKEY_sv(entry));
            return sv_2mortal(newSVpvn(HeKEY(entry), HeKLEN(entry)));
        }
     }
-    return Nullsv;
+    return NULL;
 }
 
 /* Look for an entry in the array whose value has the same SV as val;
@@ -10981,6 +11272,7 @@ S_find_hash_subscript(pTHX_ HV *hv, SV* val)
 STATIC I32
 S_find_array_subscript(pTHX_ AV *av, SV* val)
 {
+    dVAR;
     SV** svp;
     I32 i;
     if (!av || SvMAGICAL(av) || !AvARRAY(av) ||
@@ -11037,7 +11329,7 @@ S_varname(pTHX_ GV *gv, const char gvtype, PADOFFSET targ,
        AV *av;
 
        if (!cv || !CvPADLIST(cv))
-           return Nullsv;
+           return NULL;
        av = (AV*)(*av_fetch(CvPADLIST(cv), 0, FALSE));
        sv = *av_fetch(av, targ, FALSE);
        /* SvLEN in a pad name is not to be trusted */
@@ -11045,7 +11337,7 @@ S_varname(pTHX_ GV *gv, const char gvtype, PADOFFSET targ,
     }
 
     if (subscript_type == FUV_SUBSCRIPT_HASH) {
-       SV * const sv = NEWSV(0,0);
+       SV * const sv = newSV(0);
        *SvPVX(name) = '$';
        Perl_sv_catpvf(aTHX_ name, "{%s}",
            pv_display(sv,SvPVX_const(keyname), SvCUR(keyname), 0, 32));
@@ -11056,7 +11348,7 @@ S_varname(pTHX_ GV *gv, const char gvtype, PADOFFSET targ,
        Perl_sv_catpvf(aTHX_ name, "[%"IVdf"]", (IV)aindex);
     }
     else if (subscript_type == FUV_SUBSCRIPT_WITHIN)
-       sv_insert(name, 0, 0,  "within ", 7);
+       Perl_sv_insert(aTHX_ name, 0, 0,  STR_WITH_LEN("within "));
 
     return name;
 }
@@ -11093,7 +11385,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
 
     if (!obase || (match && (!uninit_sv || uninit_sv == &PL_sv_undef ||
                            uninit_sv == &PL_sv_placeholder)))
-       return Nullsv;
+       return NULL;
 
     switch (obase->op_type) {
 
@@ -11105,12 +11397,12 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
        const bool pad  = (obase->op_type == OP_PADAV || obase->op_type == OP_PADHV);
        const bool hash = (obase->op_type == OP_PADHV || obase->op_type == OP_RV2HV);
        I32 index = 0;
-       SV *keysv = Nullsv;
+       SV *keysv = NULL;
        int subscript_type = FUV_SUBSCRIPT_WITHIN;
 
        if (pad) { /* @lex, %lex */
            sv = PAD_SVl(obase->op_targ);
-           gv = Nullgv;
+           gv = NULL;
        }
        else {
            if (cUNOPx(obase)->op_first->op_type == OP_GV) {
@@ -11147,14 +11439,14 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
     case OP_PADSV:
        if (match && PAD_SVl(obase->op_targ) != uninit_sv)
            break;
-       return varname(Nullgv, '$', obase->op_targ,
-                                   Nullsv, 0, FUV_SUBSCRIPT_NONE);
+       return varname(NULL, '$', obase->op_targ,
+                                   NULL, 0, FUV_SUBSCRIPT_NONE);
 
     case OP_GVSV:
        gv = cGVOPx_gv(obase);
        if (!gv || (match && GvSV(gv) != uninit_sv))
            break;
-       return varname(gv, '$', 0, Nullsv, 0, FUV_SUBSCRIPT_NONE);
+       return varname(gv, '$', 0, NULL, 0, FUV_SUBSCRIPT_NONE);
 
     case OP_AELEMFAST:
        if (obase->op_flags & OPf_SPECIAL) { /* lexical array */
@@ -11167,8 +11459,8 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                if (!svp || *svp != uninit_sv)
                    break;
            }
-           return varname(Nullgv, '$', obase->op_targ,
-                   Nullsv, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
+           return varname(NULL, '$', obase->op_targ,
+                   NULL, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
        }
        else {
            gv = cGVOPx_gv(obase);
@@ -11184,7 +11476,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                    break;
            }
            return varname(gv, '$', 0,
-                   Nullsv, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
+                   NULL, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
        }
        break;
 
@@ -11201,12 +11493,12 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
            /* $a[uninit_expr] or $h{uninit_expr} */
            return find_uninit_var(cBINOPx(obase)->op_last, uninit_sv, match);
 
-       gv = Nullgv;
+       gv = NULL;
        o = cBINOPx(obase)->op_first;
        kid = cBINOPx(obase)->op_last;
 
        /* get the av or hv, and optionally the gv */
-       sv = Nullsv;
+       sv = NULL;
        if  (o->op_type == OP_PADAV || o->op_type == OP_PADHV) {
            sv = PAD_SV(o->op_targ);
        }
@@ -11241,7 +11533,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                return varname(gv, '%', o->op_targ,
                            cSVOPx_sv(kid), 0, FUV_SUBSCRIPT_HASH);
            else
-               return varname(gv, '@', o->op_targ, Nullsv,
+               return varname(gv, '@', o->op_targ, NULL,
                            SvIV(cSVOPx_sv(kid)), FUV_SUBSCRIPT_ARRAY);
        }
        else  {
@@ -11257,14 +11549,14 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                const I32 index = S_find_array_subscript(aTHX_ (AV*)sv, uninit_sv);
                if (index >= 0)
                    return varname(gv, '@', o->op_targ,
-                                       Nullsv, index, FUV_SUBSCRIPT_ARRAY);
+                                       NULL, index, FUV_SUBSCRIPT_ARRAY);
            }
            if (match)
                break;
            return varname(gv,
                (o->op_type == OP_PADAV || o->op_type == OP_RV2AV)
                ? '@' : '%',
-               o->op_targ, Nullsv, 0, FUV_SUBSCRIPT_WITHIN);
+               o->op_targ, NULL, 0, FUV_SUBSCRIPT_WITHIN);
        }
 
        break;
@@ -11286,7 +11578,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                if (match && GvSV(gv) != uninit_sv)
                    break;
                return varname(gv, '$', 0,
-                           Nullsv, 0, FUV_SUBSCRIPT_NONE);
+                           NULL, 0, FUV_SUBSCRIPT_NONE);
            }
            /* other possibilities not handled are:
             * open $x; or open my $x;  should return '${*$x}'
@@ -11330,7 +11622,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
     case OP_SCHOMP:
     case OP_CHOMP:
        if (SvROK(PL_rs) && uninit_sv == SvRV(PL_rs))
-           return sv_2mortal(newSVpvn("${$/}", 5));
+           return sv_2mortal(newSVpvs("${$/}"));
        /* FALL THROUGH */
 
     default:
@@ -11372,7 +11664,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
        }
        break;
     }
-    return Nullsv;
+    return NULL;
 }
 
 
@@ -11387,8 +11679,9 @@ Print appropriate "Use of uninitialized variable" warning
 void
 Perl_report_uninit(pTHX_ SV* uninit_sv)
 {
+    dVAR;
     if (PL_op) {
-       SV* varname = Nullsv;
+       SV* varname = NULL;
        if (uninit_sv) {
            varname = find_uninit_var(PL_op, uninit_sv,0);
            if (varname)