Include vim/emacs modelines in generated files to open them
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index 470d483..568f81b 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, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 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.
@@ -49,7 +49,7 @@
 
 #ifdef PERL_COPY_ON_WRITE
 #define SV_COW_NEXT_SV(sv)     INT2PTR(SV *,SvUVX(sv))
-#define SV_COW_NEXT_SV_SET(current,next)       SvUVX(current) = PTR2UV(next)
+#define SV_COW_NEXT_SV_SET(current,next)       SvUV_set(current, PTR2UV(next))
 /* This is a pessimistic view. Scalar must be purely a read-write PV to copy-
    on-write.  */
 #endif
@@ -63,14 +63,13 @@ av, hv...) contains type and reference count information, as well as a
 pointer to the body (struct xrv, xpv, xpviv...), which contains fields
 specific to each type.
 
-Normally, this allocation is done using arenas, which are approximately
-1K chunks of memory parcelled up into N heads or bodies. The first slot
-in each arena is reserved, and is used to hold a link to the next arena.
-In the case of heads, the unused first slot also contains some flags and
-a note of the number of slots.  Snaked through each arena chain is a
+Normally, this allocation is done using arenas, which by default are
+approximately 4K chunks of memory parcelled up into N heads or bodies.  The
+first slot in each arena is reserved, and is used to hold a link to the next
+arena.  In the case of heads, the unused first slot also contains some flags
+and a note of the number of slots.  Snaked through each arena chain is a
 linked list of free items; when this becomes empty, an extra arena is
-allocated and divided up into N items which are threaded into the free
-list.
+allocated and divided up into N items which are threaded into the free list.
 
 The following global variables are associated with arenas:
 
@@ -86,7 +85,8 @@ are not allocated using arenas, but are instead just malloc()/free()ed as
 required. Also, if PURIFY is defined, arenas are abandoned altogether,
 with all items individually malloc()ed. In addition, a few SV heads are
 not allocated from an arena, but are instead directly created as static
-or auto variables, eg PL_sv_undef.
+or auto variables, eg PL_sv_undef.  The size of arenas can be changed from
+the default by setting PERL_ARENA_SIZE appropriately at compile time.
 
 The SV arena serves the secondary purpose of allowing still-live SVs
 to be located and destroyed during final cleanup.
@@ -165,8 +165,19 @@ Public API:
  * "A time to plant, and a time to uproot what was planted..."
  */
 
+#ifdef DEBUG_LEAKING_SCALARS
+#  ifdef NETWARE
+#    define FREE_SV_DEBUG_FILE(sv) PerlMemfree((sv)->sv_debug_file)
+#  else
+#    define FREE_SV_DEBUG_FILE(sv) PerlMemShared_free((sv)->sv_debug_file)
+#  endif
+#else
+#  define FREE_SV_DEBUG_FILE(sv)
+#endif
+
 #define plant_SV(p) \
     STMT_START {                                       \
+       FREE_SV_DEBUG_FILE(p);                          \
        SvANY(p) = (void *)PL_sv_root;                  \
        SvFLAGS(p) = SVTYPEMASK;                        \
        PL_sv_root = (p);                               \
@@ -200,6 +211,17 @@ S_new_SV(pTHX)
     SvANY(sv) = 0;
     SvREFCNT(sv) = 1;
     SvFLAGS(sv) = 0;
+    sv->sv_debug_optype = PL_op ? PL_op->op_type : 0;
+    sv->sv_debug_line = (U16) ((PL_copline == NOLINE) ?
+        (PL_curcop ? CopLINE(PL_curcop) : 0) : PL_copline);
+    sv->sv_debug_inpad = 0;
+    sv->sv_debug_cloned = 0;
+#  ifdef NETWARE
+    sv->sv_debug_file = PL_curcop ? savepv(CopFILE(PL_curcop)): NULL;
+#  else
+    sv->sv_debug_file = PL_curcop ? savesharedpv(CopFILE(PL_curcop)): NULL;
+#  endif
+    
     return sv;
 }
 #  define new_SV(p) (p)=S_new_SV(aTHX)
@@ -245,8 +267,10 @@ S_del_sv(pTHX_ SV *p)
        for (sva = PL_sv_arenaroot; sva; sva = (SV *) SvANY(sva)) {
            sv = sva + 1;
            svend = &sva[SvREFCNT(sva)];
-           if (p >= sv && p < svend)
+           if (p >= sv && p < svend) {
                ok = 1;
+               break;
+           }
        }
        if (!ok) {
            if (ckWARN_d(WARN_INTERNAL))        
@@ -296,11 +320,18 @@ Perl_sv_add_arena(pTHX_ char *ptr, U32 size, U32 flags)
     sv = sva + 1;
     while (sv < svend) {
        SvANY(sv) = (void *)(SV*)(sv + 1);
+#ifdef DEBUGGING
        SvREFCNT(sv) = 0;
+#endif
+       /* Must always set typemask because it's awlays checked in on cleanup
+          when the arenas are walked looking for objects.  */
        SvFLAGS(sv) = SVTYPEMASK;
        sv++;
     }
     SvANY(sv) = 0;
+#ifdef DEBUGGING
+    SvREFCNT(sv) = 0;
+#endif
     SvFLAGS(sv) = SVTYPEMASK;
 }
 
@@ -394,10 +425,10 @@ do_clean_objs(pTHX_ SV *sv)
        if (SvWEAKREF(sv)) {
            sv_del_backref(sv);
            SvWEAKREF_off(sv);
-           SvRV(sv) = 0;
+           SvRV_set(sv, NULL);
        } else {
            SvROK_off(sv);
-           SvRV(sv) = 0;
+           SvRV_set(sv, NULL);
            SvREFCNT_dec(rv);
        }
     }
@@ -592,13 +623,30 @@ Perl_sv_free_arenas(pTHX)
     PL_xpvbm_arenaroot = 0;
     PL_xpvbm_root = 0;
 
-    for (arena = (XPV*)PL_he_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
-       Safefree(arena);
+    {
+       HE *he;
+       HE *he_next;
+       for (he = PL_he_arenaroot; he; he = he_next) {
+           he_next = HeNEXT(he);
+           Safefree(he);
+       }
     }
     PL_he_arenaroot = 0;
     PL_he_root = 0;
 
+#if defined(USE_ITHREADS)
+    {
+       struct ptr_tbl_ent *pte;
+       struct ptr_tbl_ent *pte_next;
+       for (pte = PL_pte_arenaroot; pte; pte = pte_next) {
+           pte_next = pte->next;
+           Safefree(pte);
+       }
+    }
+    PL_pte_arenaroot = 0;
+    PL_pte_root = 0;
+#endif
+
     if (PL_nice_chunk)
        Safefree(PL_nice_chunk);
     PL_nice_chunk = Nullch;
@@ -623,8 +671,8 @@ Perl_sv_free_arenas(pTHX)
 STATIC SV*
 S_find_hash_subscript(pTHX_ HV *hv, SV* val)
 {
+    dVAR;
     register HE **array;
-    register HE *entry;
     I32 i;
 
     if (!hv || SvMAGICAL(hv) || !HvARRAY(hv) ||
@@ -634,6 +682,7 @@ S_find_hash_subscript(pTHX_ HV *hv, SV* val)
     array = HvARRAY(hv);
 
     for (i=HvMAX(hv); i>0; i--) {
+       register HE *entry;
        for (entry = array[i]; entry; entry = HeNEXT(entry)) {
            if (HeVAL(entry) != val)
                continue;
@@ -682,7 +731,7 @@ S_find_array_subscript(pTHX_ AV *av, SV* val)
 #define FUV_SUBSCRIPT_WITHIN   4       /* "within @foo"   */
 
 STATIC SV*
-S_varname(pTHX_ GV *gv, char *gvtype, PADOFFSET targ,
+S_varname(pTHX_ GV *gv, const char *gvtype, PADOFFSET targ,
        SV* keyname, I32 aindex, int subscript_type)
 {
     AV *av;
@@ -696,15 +745,13 @@ S_varname(pTHX_ GV *gv, char *gvtype, PADOFFSET targ,
         * XXX get rid of all this if gv_fullnameX() ever supports this
         * directly */
 
-       char *p;
+       const char *p;
        HV *hv = GvSTASH(gv);
        sv_setpv(name, gvtype);
        if (!hv)
            p = "???";
-       else if (!HvNAME(hv))
+       else if (!(p=HvNAME(hv)))
            p = "__ANON__";
-       else
-           p = HvNAME(hv);
        if (strNE(p, "main")) {
            sv_catpv(name,p);
            sv_catpvn(name,"::", 2);
@@ -770,6 +817,7 @@ PL_comppad/PL_curpad points to the currently executing pad.
 STATIC SV *
 S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
 {
+    dVAR;
     SV *sv;
     AV *av;
     SV **svp;
@@ -787,8 +835,8 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
     case OP_PADAV:
     case OP_PADHV:
       {
-       bool pad  = (obase->op_type == OP_PADAV || obase->op_type == OP_PADHV);
-       bool hash = (obase->op_type == OP_PADHV || obase->op_type == OP_RV2HV);
+       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;
        int subscript_type = FUV_SUBSCRIPT_WITHIN;
@@ -938,9 +986,9 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                                                keysv, 0, FUV_SUBSCRIPT_HASH);
            }
            else {
-               I32 index = S_find_array_subscript(aTHX_ (AV*)sv, uninit_sv);
+               const I32 index = S_find_array_subscript(aTHX_ (AV*)sv, uninit_sv);
                if (index >= 0)
-               return S_varname(aTHX_ gv, "@", o->op_targ,
+                   return S_varname(aTHX_ gv, "@", o->op_targ,
                                        Nullsv, index, FUV_SUBSCRIPT_ARRAY);
            }
            if (match)
@@ -1125,12 +1173,12 @@ S_more_xiv(pTHX)
     register IV* xiv;
     register IV* xivend;
     XPV* ptr;
-    New(705, ptr, 1008/sizeof(XPV), XPV);
+    New(705, ptr, PERL_ARENA_SIZE/sizeof(XPV), XPV);
     ptr->xpv_pv = (char*)PL_xiv_arenaroot;     /* linked list of xiv arenas */
     PL_xiv_arenaroot = ptr;                    /* to keep Purify happy */
 
     xiv = (IV*) ptr;
-    xivend = &xiv[1008 / sizeof(IV) - 1];
+    xivend = &xiv[PERL_ARENA_SIZE / sizeof(IV) - 1];
     xiv += (sizeof(XPV) - 1) / sizeof(IV) + 1; /* fudge by size of XPV */
     PL_xiv_root = xiv;
     while (xiv < xivend) {
@@ -1175,12 +1223,12 @@ S_more_xnv(pTHX)
     register NV* xnv;
     register NV* xnvend;
     XPV *ptr;
-    New(711, ptr, 1008/sizeof(XPV), XPV);
+    New(711, ptr, PERL_ARENA_SIZE/sizeof(XPV), XPV);
     ptr->xpv_pv = (char*)PL_xnv_arenaroot;
     PL_xnv_arenaroot = ptr;
 
     xnv = (NV*) ptr;
-    xnvend = &xnv[1008 / sizeof(NV) - 1];
+    xnvend = &xnv[PERL_ARENA_SIZE / sizeof(NV) - 1];
     xnv += (sizeof(XPVIV) - 1) / sizeof(NV) + 1; /* fudge by sizeof XPVIV */
     PL_xnv_root = xnv;
     while (xnv < xnvend) {
@@ -1224,12 +1272,12 @@ S_more_xrv(pTHX)
     register XRV* xrv;
     register XRV* xrvend;
     XPV *ptr;
-    New(712, ptr, 1008/sizeof(XPV), XPV);
+    New(712, ptr, PERL_ARENA_SIZE/sizeof(XPV), XPV);
     ptr->xpv_pv = (char*)PL_xrv_arenaroot;
     PL_xrv_arenaroot = ptr;
 
     xrv = (XRV*) ptr;
-    xrvend = &xrv[1008 / sizeof(XRV) - 1];
+    xrvend = &xrv[PERL_ARENA_SIZE / sizeof(XRV) - 1];
     xrv += (sizeof(XPV) - 1) / sizeof(XRV) + 1;
     PL_xrv_root = xrv;
     while (xrv < xrvend) {
@@ -1272,11 +1320,11 @@ S_more_xpv(pTHX)
 {
     register XPV* xpv;
     register XPV* xpvend;
-    New(713, xpv, 1008/sizeof(XPV), XPV);
+    New(713, xpv, PERL_ARENA_SIZE/sizeof(XPV), XPV);
     xpv->xpv_pv = (char*)PL_xpv_arenaroot;
     PL_xpv_arenaroot = xpv;
 
-    xpvend = &xpv[1008 / sizeof(XPV) - 1];
+    xpvend = &xpv[PERL_ARENA_SIZE / sizeof(XPV) - 1];
     PL_xpv_root = ++xpv;
     while (xpv < xpvend) {
        xpv->xpv_pv = (char*)(xpv + 1);
@@ -1318,11 +1366,11 @@ S_more_xpviv(pTHX)
 {
     register XPVIV* xpviv;
     register XPVIV* xpvivend;
-    New(714, xpviv, 1008/sizeof(XPVIV), XPVIV);
+    New(714, xpviv, PERL_ARENA_SIZE/sizeof(XPVIV), XPVIV);
     xpviv->xpv_pv = (char*)PL_xpviv_arenaroot;
     PL_xpviv_arenaroot = xpviv;
 
-    xpvivend = &xpviv[1008 / sizeof(XPVIV) - 1];
+    xpvivend = &xpviv[PERL_ARENA_SIZE / sizeof(XPVIV) - 1];
     PL_xpviv_root = ++xpviv;
     while (xpviv < xpvivend) {
        xpviv->xpv_pv = (char*)(xpviv + 1);
@@ -1364,11 +1412,11 @@ S_more_xpvnv(pTHX)
 {
     register XPVNV* xpvnv;
     register XPVNV* xpvnvend;
-    New(715, xpvnv, 1008/sizeof(XPVNV), XPVNV);
+    New(715, xpvnv, PERL_ARENA_SIZE/sizeof(XPVNV), XPVNV);
     xpvnv->xpv_pv = (char*)PL_xpvnv_arenaroot;
     PL_xpvnv_arenaroot = xpvnv;
 
-    xpvnvend = &xpvnv[1008 / sizeof(XPVNV) - 1];
+    xpvnvend = &xpvnv[PERL_ARENA_SIZE / sizeof(XPVNV) - 1];
     PL_xpvnv_root = ++xpvnv;
     while (xpvnv < xpvnvend) {
        xpvnv->xpv_pv = (char*)(xpvnv + 1);
@@ -1410,11 +1458,11 @@ S_more_xpvcv(pTHX)
 {
     register XPVCV* xpvcv;
     register XPVCV* xpvcvend;
-    New(716, xpvcv, 1008/sizeof(XPVCV), XPVCV);
+    New(716, xpvcv, PERL_ARENA_SIZE/sizeof(XPVCV), XPVCV);
     xpvcv->xpv_pv = (char*)PL_xpvcv_arenaroot;
     PL_xpvcv_arenaroot = xpvcv;
 
-    xpvcvend = &xpvcv[1008 / sizeof(XPVCV) - 1];
+    xpvcvend = &xpvcv[PERL_ARENA_SIZE / sizeof(XPVCV) - 1];
     PL_xpvcv_root = ++xpvcv;
     while (xpvcv < xpvcvend) {
        xpvcv->xpv_pv = (char*)(xpvcv + 1);
@@ -1456,11 +1504,11 @@ S_more_xpvav(pTHX)
 {
     register XPVAV* xpvav;
     register XPVAV* xpvavend;
-    New(717, xpvav, 1008/sizeof(XPVAV), XPVAV);
+    New(717, xpvav, PERL_ARENA_SIZE/sizeof(XPVAV), XPVAV);
     xpvav->xav_array = (char*)PL_xpvav_arenaroot;
     PL_xpvav_arenaroot = xpvav;
 
-    xpvavend = &xpvav[1008 / sizeof(XPVAV) - 1];
+    xpvavend = &xpvav[PERL_ARENA_SIZE / sizeof(XPVAV) - 1];
     PL_xpvav_root = ++xpvav;
     while (xpvav < xpvavend) {
        xpvav->xav_array = (char*)(xpvav + 1);
@@ -1502,11 +1550,11 @@ S_more_xpvhv(pTHX)
 {
     register XPVHV* xpvhv;
     register XPVHV* xpvhvend;
-    New(718, xpvhv, 1008/sizeof(XPVHV), XPVHV);
+    New(718, xpvhv, PERL_ARENA_SIZE/sizeof(XPVHV), XPVHV);
     xpvhv->xhv_array = (char*)PL_xpvhv_arenaroot;
     PL_xpvhv_arenaroot = xpvhv;
 
-    xpvhvend = &xpvhv[1008 / sizeof(XPVHV) - 1];
+    xpvhvend = &xpvhv[PERL_ARENA_SIZE / sizeof(XPVHV) - 1];
     PL_xpvhv_root = ++xpvhv;
     while (xpvhv < xpvhvend) {
        xpvhv->xhv_array = (char*)(xpvhv + 1);
@@ -1548,11 +1596,11 @@ S_more_xpvmg(pTHX)
 {
     register XPVMG* xpvmg;
     register XPVMG* xpvmgend;
-    New(719, xpvmg, 1008/sizeof(XPVMG), XPVMG);
+    New(719, xpvmg, PERL_ARENA_SIZE/sizeof(XPVMG), XPVMG);
     xpvmg->xpv_pv = (char*)PL_xpvmg_arenaroot;
     PL_xpvmg_arenaroot = xpvmg;
 
-    xpvmgend = &xpvmg[1008 / sizeof(XPVMG) - 1];
+    xpvmgend = &xpvmg[PERL_ARENA_SIZE / sizeof(XPVMG) - 1];
     PL_xpvmg_root = ++xpvmg;
     while (xpvmg < xpvmgend) {
        xpvmg->xpv_pv = (char*)(xpvmg + 1);
@@ -1594,11 +1642,11 @@ S_more_xpvlv(pTHX)
 {
     register XPVLV* xpvlv;
     register XPVLV* xpvlvend;
-    New(720, xpvlv, 1008/sizeof(XPVLV), XPVLV);
+    New(720, xpvlv, PERL_ARENA_SIZE/sizeof(XPVLV), XPVLV);
     xpvlv->xpv_pv = (char*)PL_xpvlv_arenaroot;
     PL_xpvlv_arenaroot = xpvlv;
 
-    xpvlvend = &xpvlv[1008 / sizeof(XPVLV) - 1];
+    xpvlvend = &xpvlv[PERL_ARENA_SIZE / sizeof(XPVLV) - 1];
     PL_xpvlv_root = ++xpvlv;
     while (xpvlv < xpvlvend) {
        xpvlv->xpv_pv = (char*)(xpvlv + 1);
@@ -1640,11 +1688,11 @@ S_more_xpvbm(pTHX)
 {
     register XPVBM* xpvbm;
     register XPVBM* xpvbmend;
-    New(721, xpvbm, 1008/sizeof(XPVBM), XPVBM);
+    New(721, xpvbm, PERL_ARENA_SIZE/sizeof(XPVBM), XPVBM);
     xpvbm->xpv_pv = (char*)PL_xpvbm_arenaroot;
     PL_xpvbm_arenaroot = xpvbm;
 
-    xpvbmend = &xpvbm[1008 / sizeof(XPVBM) - 1];
+    xpvbmend = &xpvbm[PERL_ARENA_SIZE / sizeof(XPVBM) - 1];
     PL_xpvbm_root = ++xpvbm;
     while (xpvbm < xpvbmend) {
        xpvbm->xpv_pv = (char*)(xpvbm + 1);
@@ -1757,13 +1805,13 @@ bool
 Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
 {
 
-    char*      pv = NULL;
-    U32                cur = 0;
-    U32                len = 0;
-    IV         iv = 0;
-    NV         nv = 0.0;
-    MAGIC*     magic = NULL;
-    HV*                stash = Nullhv;
+    char*      pv;
+    U32                cur;
+    U32                len;
+    IV         iv;
+    NV         nv;
+    MAGIC*     magic;
+    HV*                stash;
 
     if (mt != SVt_PV && SvIsCOW(sv)) {
        sv_force_normal_flags(sv, 0);
@@ -1772,64 +1820,39 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
     if (SvTYPE(sv) == mt)
        return TRUE;
 
-    if (mt < SVt_PVIV)
-       (void)SvOOK_off(sv);
+    pv = NULL;
+    cur = 0;
+    len = 0;
+    iv = 0;
+    nv = 0.0;
+    magic = NULL;
+    stash = Nullhv;
 
     switch (SvTYPE(sv)) {
     case SVt_NULL:
-       pv      = 0;
-       cur     = 0;
-       len     = 0;
-       iv      = 0;
-       nv      = 0.0;
-       magic   = 0;
-       stash   = 0;
        break;
     case SVt_IV:
-       pv      = 0;
-       cur     = 0;
-       len     = 0;
        iv      = SvIVX(sv);
-       nv      = (NV)SvIVX(sv);
        del_XIV(SvANY(sv));
-       magic   = 0;
-       stash   = 0;
        if (mt == SVt_NV)
            mt = SVt_PVNV;
        else if (mt < SVt_PVIV)
            mt = SVt_PVIV;
        break;
     case SVt_NV:
-       pv      = 0;
-       cur     = 0;
-       len     = 0;
        nv      = SvNVX(sv);
-       iv      = I_V(nv);
-       magic   = 0;
-       stash   = 0;
        del_XNV(SvANY(sv));
-       SvANY(sv) = 0;
        if (mt < SVt_PVNV)
            mt = SVt_PVNV;
        break;
     case SVt_RV:
        pv      = (char*)SvRV(sv);
-       cur     = 0;
-       len     = 0;
-       iv      = PTR2IV(pv);
-       nv      = PTR2NV(pv);
        del_XRV(SvANY(sv));
-       magic   = 0;
-       stash   = 0;
        break;
     case SVt_PV:
        pv      = SvPVX(sv);
        cur     = SvCUR(sv);
        len     = SvLEN(sv);
-       iv      = 0;
-       nv      = 0.0;
-       magic   = 0;
-       stash   = 0;
        del_XPV(SvANY(sv));
        if (mt <= SVt_IV)
            mt = SVt_PVIV;
@@ -1841,9 +1864,6 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        cur     = SvCUR(sv);
        len     = SvLEN(sv);
        iv      = SvIVX(sv);
-       nv      = 0.0;
-       magic   = 0;
-       stash   = 0;
        del_XPVIV(SvANY(sv));
        break;
     case SVt_PVNV:
@@ -1852,11 +1872,13 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        len     = SvLEN(sv);
        iv      = SvIVX(sv);
        nv      = SvNVX(sv);
-       magic   = 0;
-       stash   = 0;
        del_XPVNV(SvANY(sv));
        break;
     case SVt_PVMG:
+       /* Because the XPVMG of PL_mess_sv isn't allocated from the arena,
+          there's no way that it can be safely upgraded, because perl.c
+          expects to Safefree(SvANY(PL_mess_sv))  */
+       assert(sv != PL_mess_sv);
        pv      = SvPVX(sv);
        cur     = SvCUR(sv);
        len     = SvLEN(sv);
@@ -1878,161 +1900,123 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        Perl_croak(aTHX_ "Can't upgrade to undef");
     case SVt_IV:
        SvANY(sv) = new_XIV();
-       SvIVX(sv)       = iv;
+       SvIV_set(sv, iv);
        break;
     case SVt_NV:
        SvANY(sv) = new_XNV();
-       SvNVX(sv)       = nv;
+       SvNV_set(sv, nv);
        break;
     case SVt_RV:
        SvANY(sv) = new_XRV();
-       SvRV(sv) = (SV*)pv;
-       break;
-    case SVt_PV:
-       SvANY(sv) = new_XPV();
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       break;
-    case SVt_PVIV:
-       SvANY(sv) = new_XPVIV();
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       SvIVX(sv)       = iv;
-       if (SvNIOK(sv))
-           (void)SvIOK_on(sv);
-       SvNOK_off(sv);
-       break;
-    case SVt_PVNV:
-       SvANY(sv) = new_XPVNV();
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       SvIVX(sv)       = iv;
-       SvNVX(sv)       = nv;
-       break;
-    case SVt_PVMG:
-       SvANY(sv) = new_XPVMG();
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       SvIVX(sv)       = iv;
-       SvNVX(sv)       = nv;
-       SvMAGIC(sv)     = magic;
-       SvSTASH(sv)     = stash;
-       break;
-    case SVt_PVLV:
-       SvANY(sv) = new_XPVLV();
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       SvIVX(sv)       = iv;
-       SvNVX(sv)       = nv;
-       SvMAGIC(sv)     = magic;
-       SvSTASH(sv)     = stash;
-       LvTARGOFF(sv)   = 0;
-       LvTARGLEN(sv)   = 0;
-       LvTARG(sv)      = 0;
-       LvTYPE(sv)      = 0;
-       GvGP(sv)        = 0;
-       GvNAME(sv)      = 0;
-       GvNAMELEN(sv)   = 0;
-       GvSTASH(sv)     = 0;
-       GvFLAGS(sv)     = 0;
-       break;
-    case SVt_PVAV:
-       SvANY(sv) = new_XPVAV();
-       if (pv)
-           Safefree(pv);
-       SvPVX(sv)       = 0;
-       AvMAX(sv)       = -1;
-       AvFILLp(sv)     = -1;
-       SvIVX(sv)       = 0;
-       SvNVX(sv)       = 0.0;
-       SvMAGIC(sv)     = magic;
-       SvSTASH(sv)     = stash;
-       AvALLOC(sv)     = 0;
-       AvARYLEN(sv)    = 0;
-       AvFLAGS(sv)     = AVf_REAL;
+       SvRV_set(sv, (SV*)pv);
        break;
     case SVt_PVHV:
        SvANY(sv) = new_XPVHV();
-       if (pv)
-           Safefree(pv);
-       SvPVX(sv)       = 0;
-       HvFILL(sv)      = 0;
-       HvMAX(sv)       = 0;
-       HvTOTALKEYS(sv) = 0;
-       HvPLACEHOLDERS(sv) = 0;
-       SvMAGIC(sv)     = magic;
-       SvSTASH(sv)     = stash;
        HvRITER(sv)     = 0;
        HvEITER(sv)     = 0;
        HvPMROOT(sv)    = 0;
        HvNAME(sv)      = 0;
+       HvFILL(sv)      = 0;
+       HvMAX(sv)       = 0;
+       HvTOTALKEYS(sv) = 0;
+       HvPLACEHOLDERS(sv) = 0;
+
+       /* Fall through...  */
+       if (0) {
+       case SVt_PVAV:
+           SvANY(sv) = new_XPVAV();
+           AvMAX(sv)   = -1;
+           AvFILLp(sv) = -1;
+           AvALLOC(sv) = 0;
+           AvARYLEN(sv)= 0;
+           AvFLAGS(sv) = AVf_REAL;
+           SvIV_set(sv, 0);
+           SvNV_set(sv, 0.0);
+       }
+       /* to here.  */
+       /* XXX? Only SVt_NULL is ever upgraded to AV or HV?  */
+       assert(!pv);
+       /* FIXME. Should be able to remove all this if()... if the above
+          assertion is genuinely always true.  */
+       if(SvOOK(sv)) {
+           pv -= iv;
+           SvFLAGS(sv) &= ~SVf_OOK;
+       }
+       Safefree(pv);
+       SvPV_set(sv, (char*)0);
+       SvMAGIC_set(sv, magic);
+       SvSTASH_set(sv, stash);
        break;
+
+    case SVt_PVIO:
+       SvANY(sv) = new_XPVIO();
+       Zero(SvANY(sv), 1, XPVIO);
+       IoPAGE_LEN(sv)  = 60;
+       goto set_magic_common;
+    case SVt_PVFM:
+       SvANY(sv) = new_XPVFM();
+       Zero(SvANY(sv), 1, XPVFM);
+       goto set_magic_common;
+    case SVt_PVBM:
+       SvANY(sv) = new_XPVBM();
+       BmRARE(sv)      = 0;
+       BmUSEFUL(sv)    = 0;
+       BmPREVIOUS(sv)  = 0;
+       goto set_magic_common;
+    case SVt_PVGV:
+       SvANY(sv) = new_XPVGV();
+       GvGP(sv)        = 0;
+       GvNAME(sv)      = 0;
+       GvNAMELEN(sv)   = 0;
+       GvSTASH(sv)     = 0;
+       GvFLAGS(sv)     = 0;
+       goto set_magic_common;
     case SVt_PVCV:
        SvANY(sv) = new_XPVCV();
        Zero(SvANY(sv), 1, XPVCV);
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       SvIVX(sv)       = iv;
-       SvNVX(sv)       = nv;
-       SvMAGIC(sv)     = magic;
-       SvSTASH(sv)     = stash;
-       break;
-    case SVt_PVGV:
-       SvANY(sv) = new_XPVGV();
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       SvIVX(sv)       = iv;
-       SvNVX(sv)       = nv;
-       SvMAGIC(sv)     = magic;
-       SvSTASH(sv)     = stash;
+       goto set_magic_common;
+    case SVt_PVLV:
+       SvANY(sv) = new_XPVLV();
+       LvTARGOFF(sv)   = 0;
+       LvTARGLEN(sv)   = 0;
+       LvTARG(sv)      = 0;
+       LvTYPE(sv)      = 0;
        GvGP(sv)        = 0;
        GvNAME(sv)      = 0;
        GvNAMELEN(sv)   = 0;
        GvSTASH(sv)     = 0;
        GvFLAGS(sv)     = 0;
-       break;
-    case SVt_PVBM:
-       SvANY(sv) = new_XPVBM();
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       SvIVX(sv)       = iv;
-       SvNVX(sv)       = nv;
-       SvMAGIC(sv)     = magic;
-       SvSTASH(sv)     = stash;
-       BmRARE(sv)      = 0;
-       BmUSEFUL(sv)    = 0;
-       BmPREVIOUS(sv)  = 0;
-       break;
-    case SVt_PVFM:
-       SvANY(sv) = new_XPVFM();
-       Zero(SvANY(sv), 1, XPVFM);
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       SvIVX(sv)       = iv;
-       SvNVX(sv)       = nv;
-       SvMAGIC(sv)     = magic;
-       SvSTASH(sv)     = stash;
-       break;
-    case SVt_PVIO:
-       SvANY(sv) = new_XPVIO();
-       Zero(SvANY(sv), 1, XPVIO);
-       SvPVX(sv)       = pv;
-       SvCUR(sv)       = cur;
-       SvLEN(sv)       = len;
-       SvIVX(sv)       = iv;
-       SvNVX(sv)       = nv;
-       SvMAGIC(sv)     = magic;
-       SvSTASH(sv)     = stash;
-       IoPAGE_LEN(sv)  = 60;
+       /* Fall through.  */
+       if (0) {
+       case SVt_PVMG:
+           SvANY(sv) = new_XPVMG();
+       }
+    set_magic_common:
+       SvMAGIC_set(sv, magic);
+       SvSTASH_set(sv, stash);
+       /* Fall through.  */
+       if (0) {
+       case SVt_PVNV:
+           SvANY(sv) = new_XPVNV();
+       }
+       SvNV_set(sv, nv);
+       /* Fall through.  */
+       if (0) {
+       case SVt_PVIV:
+           SvANY(sv) = new_XPVIV();
+           if (SvNIOK(sv))
+               (void)SvIOK_on(sv);
+           SvNOK_off(sv);
+       }
+       SvIV_set(sv, iv);
+       /* Fall through.  */
+       if (0) {
+       case SVt_PV:
+           SvANY(sv) = new_XPV();
+       }
+       SvPV_set(sv, pv);
+       SvCUR_set(sv, cur);
+       SvLEN_set(sv, len);
        break;
     }
     return TRUE;
@@ -2053,8 +2037,8 @@ Perl_sv_backoff(pTHX_ register SV *sv)
     assert(SvOOK(sv));
     if (SvIVX(sv)) {
        char *s = SvPVX(sv);
-       SvLEN(sv) += SvIVX(sv);
-       SvPVX(sv) -= SvIVX(sv);
+       SvLEN_set(sv, SvLEN(sv) + SvIVX(sv));
+       SvPV_set(sv, SvPVX(sv) - SvIVX(sv));
        SvIV_set(sv, 0);
        Move(s, SvPVX(sv), SvCUR(sv)+1, char);
     }
@@ -2114,7 +2098,7 @@ Perl_sv_grow(pTHX_ register SV *sv, register STRLEN newlen)
 #endif
            Renew(s,newlen,char);
        }
-        else {
+       else {
            New(703, s, newlen, char);
            if (SvPVX(sv) && SvCUR(sv)) {
                Move(SvPVX(sv), s, (newlen < SvCUR(sv)) ? newlen : SvCUR(sv), char);
@@ -2161,7 +2145,7 @@ Perl_sv_setiv(pTHX_ register SV *sv, IV i)
                   OP_DESC(PL_op));
     }
     (void)SvIOK_only(sv);                      /* validate number */
-    SvIVX(sv) = i;
+    SvIV_set(sv, i);
     SvTAINT(sv);
 }
 
@@ -2206,7 +2190,7 @@ Perl_sv_setuv(pTHX_ register SV *sv, UV u)
     }
     sv_setiv(sv, 0);
     SvIsUV_on(sv);
-    SvUVX(sv) = u;
+    SvUV_set(sv, u);
 }
 
 /*
@@ -2271,7 +2255,7 @@ Perl_sv_setnv(pTHX_ register SV *sv, NV num)
        Perl_croak(aTHX_ "Can't coerce %s to number in %s", sv_reftype(sv,0),
                   OP_NAME(PL_op));
     }
-    SvNVX(sv) = num;
+    SvNV_set(sv, num);
     (void)SvNOK_only(sv);                      /* validate number */
     SvTAINT(sv);
 }
@@ -2482,14 +2466,14 @@ S_sv_2iuv_non_preserve(pTHX_ register SV *sv, I32 numtype)
     if (SvNVX(sv) < (NV)IV_MIN) {
        (void)SvIOKp_on(sv);
        (void)SvNOK_on(sv);
-       SvIVX(sv) = IV_MIN;
+       SvIV_set(sv, IV_MIN);
        return IS_NUMBER_UNDERFLOW_IV;
     }
     if (SvNVX(sv) > (NV)UV_MAX) {
        (void)SvIOKp_on(sv);
        (void)SvNOK_on(sv);
        SvIsUV_on(sv);
-       SvUVX(sv) = UV_MAX;
+       SvUV_set(sv, UV_MAX);
        return IS_NUMBER_OVERFLOW_UV;
     }
     (void)SvIOKp_on(sv);
@@ -2497,7 +2481,7 @@ S_sv_2iuv_non_preserve(pTHX_ register SV *sv, I32 numtype)
     /* Can't use strtol etc to convert this string.  (See truth table in
        sv_2iv  */
     if (SvNVX(sv) <= (UV)IV_MAX) {
-        SvIVX(sv) = I_V(SvNVX(sv));
+        SvIV_set(sv, I_V(SvNVX(sv)));
         if ((NV)(SvIVX(sv)) == SvNVX(sv)) {
             SvIOK_on(sv); /* Integer is precise. NOK, IOK */
         } else {
@@ -2506,7 +2490,7 @@ S_sv_2iuv_non_preserve(pTHX_ register SV *sv, I32 numtype)
         return SvNVX(sv) < 0 ? IS_NUMBER_UNDERFLOW_UV : IS_NUMBER_IV_AND_UV;
     }
     SvIsUV_on(sv);
-    SvUVX(sv) = U_V(SvNVX(sv));
+    SvUV_set(sv, U_V(SvNVX(sv)));
     if ((NV)(SvUVX(sv)) == SvNVX(sv)) {
         if (SvUVX(sv) == UV_MAX) {
             /* As we know that NVs don't preserve UVs, UV_MAX cannot
@@ -2605,7 +2589,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
           answer is the UV IV_MAX +1. Hence < ensures that dodgy boundary
           cases go to UV */
        if (SvNVX(sv) < (NV)IV_MAX + 0.5) {
-           SvIVX(sv) = I_V(SvNVX(sv));
+           SvIV_set(sv, I_V(SvNVX(sv)));
            if (SvNVX(sv) == (NV) SvIVX(sv)
 #ifndef NV_PRESERVES_UV
                && (((UV)1 << NV_PRESERVES_UV_BITS) >
@@ -2643,7 +2627,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
               0x8000000000000000 which will be exact. NWC */
        }
        else {
-           SvUVX(sv) = U_V(SvNVX(sv));
+           SvUV_set(sv, U_V(SvNVX(sv)));
            if (
                (SvNVX(sv) == (NV) SvUVX(sv))
 #ifndef  NV_PRESERVES_UV
@@ -2668,7 +2652,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
     }
     else if (SvPOKp(sv) && SvLEN(sv)) {
        UV value;
-       int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
+       const int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
        /* We want to avoid a possible problem when we cache an IV which
           may be later translated to an NV, and the resulting NV is not
           the same as the direct translation of the initial string
@@ -2706,15 +2690,15 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
            if (!(numtype & IS_NUMBER_NEG)) {
                /* positive */;
                if (value <= (UV)IV_MAX) {
-                   SvIVX(sv) = (IV)value;
+                   SvIV_set(sv, (IV)value);
                } else {
-                   SvUVX(sv) = value;
+                   SvUV_set(sv, value);
                    SvIsUV_on(sv);
                }
            } else {
                /* 2s complement assumption  */
                if (value <= (UV)IV_MIN) {
-                   SvIVX(sv) = -(IV)value;
+                   SvIV_set(sv, -(IV)value);
                } else {
                    /* Too negative for an IV.  This is a double upgrade, but
                       I'm assuming it will be rare.  */
@@ -2723,8 +2707,8 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
                    SvNOK_on(sv);
                    SvIOK_off(sv);
                    SvIOKp_on(sv);
-                   SvNVX(sv) = -(NV)value;
-                   SvIVX(sv) = IV_MIN;
+                   SvNV_set(sv, -(NV)value);
+                   SvIV_set(sv, IV_MIN);
                }
            }
        }
@@ -2735,7 +2719,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
        if ((numtype & (IS_NUMBER_IN_UV | IS_NUMBER_NOT_INT))
            != IS_NUMBER_IN_UV) {
            /* It wasn't an (integer that doesn't overflow the UV). */
-           SvNVX(sv) = Atof(SvPVX(sv));
+           SvNV_set(sv, Atof(SvPVX(sv)));
 
            if (! numtype && ckWARN(WARN_NUMERIC))
                not_a_number(sv);
@@ -2753,7 +2737,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
            (void)SvIOKp_on(sv);
            (void)SvNOK_on(sv);
            if (SvNVX(sv) < (NV)IV_MAX + 0.5) {
-               SvIVX(sv) = I_V(SvNVX(sv));
+               SvIV_set(sv, I_V(SvNVX(sv)));
                if ((NV)(SvIVX(sv)) == SvNVX(sv)) {
                    SvIOK_on(sv);
                } else {
@@ -2764,10 +2748,10 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
                if (SvNVX(sv) > (NV)UV_MAX) {
                    SvIsUV_on(sv);
                    /* Integer is inaccurate. NOK, IOKp, is UV */
-                   SvUVX(sv) = UV_MAX;
+                   SvUV_set(sv, UV_MAX);
                    SvIsUV_on(sv);
                } else {
-                   SvUVX(sv) = U_V(SvNVX(sv));
+                   SvUV_set(sv, U_V(SvNVX(sv)));
                    /* 0xFFFFFFFFFFFFFFFF not an issue in here */
                    if ((NV)(SvUVX(sv)) == SvNVX(sv)) {
                        SvIOK_on(sv);
@@ -2793,7 +2777,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
                     /* Small enough to preserve all bits. */
                     (void)SvIOKp_on(sv);
                     SvNOK_on(sv);
-                    SvIVX(sv) = I_V(SvNVX(sv));
+                    SvIV_set(sv, I_V(SvNVX(sv)));
                     if ((NV)(SvIVX(sv)) == SvNVX(sv))
                         SvIOK_on(sv);
                     /* Assumption: first non-preserved integer is < IV_MAX,
@@ -2910,7 +2894,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
 
        (void)SvIOKp_on(sv);    /* Must do this first, to clear any SvOOK */
        if (SvNVX(sv) < (NV)IV_MAX + 0.5) {
-           SvIVX(sv) = I_V(SvNVX(sv));
+           SvIV_set(sv, I_V(SvNVX(sv)));
            if (SvNVX(sv) == (NV) SvIVX(sv)
 #ifndef NV_PRESERVES_UV
                && (((UV)1 << NV_PRESERVES_UV_BITS) >
@@ -2948,7 +2932,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
               0x8000000000000000 which will be exact. NWC */
        }
        else {
-           SvUVX(sv) = U_V(SvNVX(sv));
+           SvUV_set(sv, U_V(SvNVX(sv)));
            if (
                (SvNVX(sv) == (NV) SvUVX(sv))
 #ifndef  NV_PRESERVES_UV
@@ -2971,7 +2955,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
     }
     else if (SvPOKp(sv) && SvLEN(sv)) {
        UV value;
-       int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
+       const int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
 
        /* We want to avoid a possible problem when we cache a UV which
           may be later translated to an NV, and the resulting NV is not
@@ -3007,16 +2991,16 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
            if (!(numtype & IS_NUMBER_NEG)) {
                /* positive */;
                if (value <= (UV)IV_MAX) {
-                   SvIVX(sv) = (IV)value;
+                   SvIV_set(sv, (IV)value);
                } else {
                    /* it didn't overflow, and it was positive. */
-                   SvUVX(sv) = value;
+                   SvUV_set(sv, value);
                    SvIsUV_on(sv);
                }
            } else {
                /* 2s complement assumption  */
                if (value <= (UV)IV_MIN) {
-                   SvIVX(sv) = -(IV)value;
+                   SvIV_set(sv, -(IV)value);
                } else {
                    /* Too negative for an IV.  This is a double upgrade, but
                       I'm assuming it will be rare.  */
@@ -3025,8 +3009,8 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
                    SvNOK_on(sv);
                    SvIOK_off(sv);
                    SvIOKp_on(sv);
-                   SvNVX(sv) = -(NV)value;
-                   SvIVX(sv) = IV_MIN;
+                   SvNV_set(sv, -(NV)value);
+                   SvIV_set(sv, IV_MIN);
                }
            }
        }
@@ -3034,7 +3018,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
        if ((numtype & (IS_NUMBER_IN_UV | IS_NUMBER_NOT_INT))
            != IS_NUMBER_IN_UV) {
            /* It wasn't an integer, or it overflowed the UV. */
-           SvNVX(sv) = Atof(SvPVX(sv));
+           SvNV_set(sv, Atof(SvPVX(sv)));
 
             if (! numtype && ckWARN(WARN_NUMERIC))
                    not_a_number(sv);
@@ -3051,7 +3035,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
             (void)SvIOKp_on(sv);
             (void)SvNOK_on(sv);
             if (SvNVX(sv) < (NV)IV_MAX + 0.5) {
-                SvIVX(sv) = I_V(SvNVX(sv));
+                SvIV_set(sv, I_V(SvNVX(sv)));
                 if ((NV)(SvIVX(sv)) == SvNVX(sv)) {
                     SvIOK_on(sv);
                 } else {
@@ -3062,10 +3046,10 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
                 if (SvNVX(sv) > (NV)UV_MAX) {
                     SvIsUV_on(sv);
                     /* Integer is inaccurate. NOK, IOKp, is UV */
-                    SvUVX(sv) = UV_MAX;
+                    SvUV_set(sv, UV_MAX);
                     SvIsUV_on(sv);
                 } else {
-                    SvUVX(sv) = U_V(SvNVX(sv));
+                    SvUV_set(sv, U_V(SvNVX(sv)));
                     /* 0xFFFFFFFFFFFFFFFF not an issue in here, NVs
                        NV preservse UV so can do correct comparison.  */
                     if ((NV)(SvUVX(sv)) == SvNVX(sv)) {
@@ -3091,7 +3075,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
                     /* Small enough to preserve all bits. */
                     (void)SvIOKp_on(sv);
                     SvNOK_on(sv);
-                    SvIVX(sv) = I_V(SvNVX(sv));
+                    SvIV_set(sv, I_V(SvNVX(sv)));
                     if ((NV)(SvIVX(sv)) == SvNVX(sv))
                         SvIOK_on(sv);
                     /* Assumption: first non-preserved integer is < IV_MAX,
@@ -3206,7 +3190,7 @@ Perl_sv_2nv(pTHX_ register SV *sv)
         return SvNVX(sv);
     }
     if (SvIOKp(sv)) {
-       SvNVX(sv) = SvIsUV(sv) ? (NV)SvUVX(sv) : (NV)SvIVX(sv);
+       SvNV_set(sv, SvIsUV(sv) ? (NV)SvUVX(sv) : (NV)SvIVX(sv));
 #ifdef NV_PRESERVES_UV
        SvNOK_on(sv);
 #else
@@ -3221,19 +3205,19 @@ Perl_sv_2nv(pTHX_ register SV *sv)
     }
     else if (SvPOKp(sv) && SvLEN(sv)) {
        UV value;
-       int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
+       const int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
        if (ckWARN(WARN_NUMERIC) && !SvIOKp(sv) && !numtype)
            not_a_number(sv);
 #ifdef NV_PRESERVES_UV
        if ((numtype & (IS_NUMBER_IN_UV | IS_NUMBER_NOT_INT))
            == IS_NUMBER_IN_UV) {
            /* It's definitely an integer */
-           SvNVX(sv) = (numtype & IS_NUMBER_NEG) ? -(NV)value : (NV)value;
+           SvNV_set(sv, (numtype & IS_NUMBER_NEG) ? -(NV)value : (NV)value);
        } else
-           SvNVX(sv) = Atof(SvPVX(sv));
+           SvNV_set(sv, Atof(SvPVX(sv)));
        SvNOK_on(sv);
 #else
-       SvNVX(sv) = Atof(SvPVX(sv));
+       SvNV_set(sv, Atof(SvPVX(sv)));
        /* Only set the public NV OK flag if this NV preserves the value in
           the PV at least as well as an IV/UV would.
           Not sure how to do this 100% reliably. */
@@ -3257,11 +3241,11 @@ Perl_sv_2nv(pTHX_ register SV *sv)
                 SvIOKp_on(sv);
 
                 if (numtype & IS_NUMBER_NEG) {
-                    SvIVX(sv) = -(IV)value;
+                    SvIV_set(sv, -(IV)value);
                 } else if (value <= (UV)IV_MAX) {
-                   SvIVX(sv) = (IV)value;
+                   SvIV_set(sv, (IV)value);
                } else {
-                   SvUVX(sv) = value;
+                   SvUV_set(sv, value);
                    SvIsUV_on(sv);
                }
 
@@ -3460,7 +3444,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
 
     if (!sv) {
        *lp = 0;
-       return "";
+       return (char *)"";
     }
     if (SvGMAGICAL(sv)) {
        if (flags & SV_GMAGIC)
@@ -3488,12 +3472,13 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                    report_uninit(sv);
            }
             *lp = 0;
-            return "";
+            return (char *)"";
         }
     }
     if (SvTHINKFIRST(sv)) {
        if (SvROK(sv)) {
            SV* tmpstr;
+            register const char *typestr;
             if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,string)) &&
                 (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
                 char *pv = SvPV(tmpstr, *lp);
@@ -3506,7 +3491,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
            origsv = sv;
            sv = (SV*)SvRV(sv);
            if (!sv)
-               s = "NULLREF";
+               typestr = "NULLREF";
            else {
                MAGIC *mg;
                
@@ -3516,10 +3501,10 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                           (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG))
                          == (SVs_OBJECT|SVs_SMG))
                         && (mg = mg_find(sv, PERL_MAGIC_qr))) {
-                       regexp *re = (regexp *)mg->mg_obj;
+                        const regexp *re = (regexp *)mg->mg_obj;
 
                        if (!mg->mg_ptr) {
-                           char *fptr = "msix";
+                            const char *fptr = "msix";
                            char reflags[6];
                            char ch;
                            int left = 0;
@@ -3559,10 +3544,10 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                              */
                             if (PMf_EXTENDED & re->reganch)
                             {
-                                char *endptr = re->precomp + re->prelen;
+                                const char *endptr = re->precomp + re->prelen;
                                 while (endptr >= re->precomp)
                                 {
-                                    char c = *(endptr--);
+                                    const char c = *(endptr--);
                                     if (c == '\n')
                                         break; /* don't need another */
                                     if (c == '#') {
@@ -3602,48 +3587,45 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                case SVt_PV:
                case SVt_PVIV:
                case SVt_PVNV:
-               case SVt_PVBM:  if (SvROK(sv))
-                                   s = "REF";
-                               else
-                                   s = "SCALAR";               break;
-               case SVt_PVLV:  s = SvROK(sv) ? "REF"
+               case SVt_PVBM:  typestr = SvROK(sv) ? "REF" : "SCALAR"; break;
+               case SVt_PVLV:  typestr = SvROK(sv) ? "REF"
                                /* tied lvalues should appear to be
                                 * scalars for backwards compatitbility */
                                : (LvTYPE(sv) == 't' || LvTYPE(sv) == 'T')
                                    ? "SCALAR" : "LVALUE";      break;
-               case SVt_PVAV:  s = "ARRAY";                    break;
-               case SVt_PVHV:  s = "HASH";                     break;
-               case SVt_PVCV:  s = "CODE";                     break;
-               case SVt_PVGV:  s = "GLOB";                     break;
-               case SVt_PVFM:  s = "FORMAT";                   break;
-               case SVt_PVIO:  s = "IO";                       break;
-               default:        s = "UNKNOWN";                  break;
+               case SVt_PVAV:  typestr = "ARRAY";      break;
+               case SVt_PVHV:  typestr = "HASH";       break;
+               case SVt_PVCV:  typestr = "CODE";       break;
+               case SVt_PVGV:  typestr = "GLOB";       break;
+               case SVt_PVFM:  typestr = "FORMAT";     break;
+               case SVt_PVIO:  typestr = "IO";         break;
+               default:        typestr = "UNKNOWN";    break;
                }
                tsv = NEWSV(0,0);
                if (SvOBJECT(sv)) {
                    const char *name = HvNAME(SvSTASH(sv));
                    Perl_sv_setpvf(aTHX_ tsv, "%s=%s(0x%"UVxf")",
-                                  name ? name : "__ANON__" , s, PTR2UV(sv));
+                                  name ? name : "__ANON__" , typestr, PTR2UV(sv));
                }
                else
-                   Perl_sv_setpvf(aTHX_ tsv, "%s(0x%"UVxf")", s, PTR2UV(sv));
+                   Perl_sv_setpvf(aTHX_ tsv, "%s(0x%"UVxf")", typestr, PTR2UV(sv));
                goto tokensaveref;
            }
-           *lp = strlen(s);
-           return s;
+           *lp = strlen(typestr);
+           return (char *)typestr;
        }
        if (SvREADONLY(sv) && !SvOK(sv)) {
            if (ckWARN(WARN_UNINITIALIZED))
                report_uninit(sv);
            *lp = 0;
-           return "";
+           return (char *)"";
        }
     }
     if (SvIOK(sv) || ((SvIOKp(sv) && !SvNOKp(sv)))) {
        /* I'm assuming that if both IV and NV are equally valid then
           converting the IV is going to be more efficient */
-       U32 isIOK = SvIOK(sv);
-       U32 isUIOK = SvIsUV(sv);
+       const U32 isIOK = SvIOK(sv);
+       const U32 isUIOK = SvIsUV(sv);
        char buf[TYPE_CHARS(UV)];
        char *ebuf, *ptr;
 
@@ -3699,7 +3681,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
        if (SvTYPE(sv) < SVt_PV)
            /* Typically the caller expects that sv_any is not NULL now.  */
            sv_upgrade(sv, SVt_PV);
-       return "";
+       return (char *)"";
     }
     *lp = s - SvPVX(sv);
     SvCUR_set(sv, *lp);
@@ -3720,8 +3702,9 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
        return SvPVX(tsv);
     }
     else {
+        dVAR;
        STRLEN len;
-       char *t;
+        const char *t;
 
        if (tsv) {
            sv_2mortal(tsv);
@@ -3933,9 +3916,6 @@ use the Encode extension for that.
 STRLEN
 Perl_sv_utf8_upgrade_flags(pTHX_ register SV *sv, I32 flags)
 {
-    U8 *s, *t, *e;
-    int  hibit = 0;
-
     if (sv == &PL_sv_undef)
        return 0;
     if (!SvPOK(sv)) {
@@ -3960,31 +3940,32 @@ Perl_sv_utf8_upgrade_flags(pTHX_ register SV *sv, I32 flags)
     if (PL_encoding && !(flags & SV_UTF8_NO_ENCODING))
         sv_recode_to_utf8(sv, PL_encoding);
     else { /* Assume Latin-1/EBCDIC */
-        /* This function could be much more efficient if we
-         * had a FLAG in SVs to signal if there are any hibit
-         * chars in the PV.  Given that there isn't such a flag
-         * make the loop as fast as possible. */
-        s = (U8 *) SvPVX(sv);
-        e = (U8 *) SvEND(sv);
-        t = s;
-        while (t < e) {
-             U8 ch = *t++;
-             if ((hibit = !NATIVE_IS_INVARIANT(ch)))
-                  break;
-        }
-        if (hibit) {
-             STRLEN len;
-             (void)SvOOK_off(sv);
-             s = (U8*)SvPVX(sv);
-             len = SvCUR(sv) + 1; /* Plus the \0 */
-             SvPVX(sv) = (char*)bytes_to_utf8((U8*)s, &len);
-             SvCUR(sv) = len - 1;
-             if (SvLEN(sv) != 0)
-                  Safefree(s); /* No longer using what was there before. */
-             SvLEN(sv) = len; /* No longer know the real size. */
-        }
-        /* Mark as UTF-8 even if no hibit - saves scanning loop */
-        SvUTF8_on(sv);
+       /* This function could be much more efficient if we
+        * had a FLAG in SVs to signal if there are any hibit
+        * chars in the PV.  Given that there isn't such a flag
+        * make the loop as fast as possible. */
+       U8 *s = (U8 *) SvPVX(sv);
+       U8 *e = (U8 *) SvEND(sv);
+       U8 *t = s;
+       int hibit = 0;
+       
+       while (t < e) {
+           U8 ch = *t++;
+           if ((hibit = !NATIVE_IS_INVARIANT(ch)))
+               break;
+       }
+       if (hibit) {
+           STRLEN len = SvCUR(sv) + 1; /* Plus the \0 */
+           s = bytes_to_utf8((U8*)s, &len);
+
+           SvPV_free(sv); /* No longer using what was there before. */
+
+           SvPV_set(sv, (char*)s);
+           SvCUR_set(sv, len - 1);
+           SvLEN_set(sv, len); /* No longer know the real size. */
+       }
+       /* Mark as UTF-8 even if no hibit - saves scanning loop */
+       SvUTF8_on(sv);
     }
     return SvCUR(sv);
 }
@@ -4026,7 +4007,7 @@ Perl_sv_utf8_downgrade(pTHX_ register SV* sv, bool fail_ok)
                        Perl_croak(aTHX_ "Wide character");
                }
            }
-           SvCUR(sv) = len;
+           SvCUR_set(sv, len);
        }
     }
     SvUTF8_off(sv);
@@ -4191,7 +4172,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                break;
            }
            (void)SvIOK_only(dstr);
-           SvIVX(dstr) = SvIVX(sstr);
+           SvIV_set(dstr,  SvIVX(sstr));
            if (SvIsUV(sstr))
                SvIsUV_on(dstr);
            if (SvTAINTED(sstr))
@@ -4213,7 +4194,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                sv_upgrade(dstr, SVt_PVNV);
                break;
            }
-           SvNVX(dstr) = SvNVX(sstr);
+           SvNV_set(dstr, SvNVX(sstr));
            (void)SvNOK_only(dstr);
            if (SvTAINTED(sstr))
                SvTAINT(dstr);
@@ -4465,21 +4446,20 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                return;
            }
            if (SvPVX(dstr)) {
-               (void)SvOOK_off(dstr);          /* backoff */
-               if (SvLEN(dstr))
-                   Safefree(SvPVX(dstr));
-               SvLEN(dstr)=SvCUR(dstr)=0;
+               SvPV_free(dstr);
+               SvLEN_set(dstr, 0);
+                SvCUR_set(dstr, 0);
            }
        }
        (void)SvOK_off(dstr);
-       SvRV(dstr) = SvREFCNT_inc(SvRV(sstr));
+       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;
-           SvNVX(dstr) = SvNVX(sstr);
+           SvNV_set(dstr, SvNVX(sstr));
        }
        if (sflags & SVp_IOK) {
            (void)SvIOKp_on(dstr);
@@ -4487,7 +4467,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                SvFLAGS(dstr) |= SVf_IOK;
            if (sflags & SVf_IVisUV)
                SvIsUV_on(dstr);
-           SvIVX(dstr) = SvIVX(sstr);
+           SvIV_set(dstr, SvIVX(sstr));
        }
        if (SvAMAGIC(sstr)) {
            SvAMAGIC_on(dstr);
@@ -4592,10 +4572,10 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                     SvPV_set(dstr,
                              sharepvn(SvPVX(sstr),
                                       (sflags & SVf_UTF8?-cur:cur), hash));
-                    SvUVX(dstr) = hash;
+                    SvUV_set(dstr, hash);
                 }
-                SvLEN(dstr) = len;
-                SvCUR(dstr) = cur;
+                SvLEN_set(dstr, len);
+                SvCUR_set(dstr, cur);
                 SvREADONLY_on(dstr);
                 SvFAKE_on(dstr);
                 /* Relesase a global SV mutex.  */
@@ -4622,7 +4602,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            SvNOKp_on(dstr);
            if (sflags & SVf_NOK)
                SvFLAGS(dstr) |= SVf_NOK;
-           SvNVX(dstr) = SvNVX(sstr);
+           SvNV_set(dstr, SvNVX(sstr));
        }
        if (sflags & SVp_IOK) {
            (void)SvIOKp_on(dstr);
@@ -4630,7 +4610,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                SvFLAGS(dstr) |= SVf_IOK;
            if (sflags & SVf_IVisUV)
                SvIsUV_on(dstr);
-           SvIVX(dstr) = SvIVX(sstr);
+           SvIV_set(dstr, SvIVX(sstr));
        }
        if (SvVOK(sstr)) {
            MAGIC *smg = mg_find(sstr,PERL_MAGIC_vstring);
@@ -4649,13 +4629,13 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        /* XXXX Do we want to set IsUV for IV(ROK)?  Be extra safe... */
        if (sflags & SVf_IVisUV)
            SvIsUV_on(dstr);
-       SvIVX(dstr) = SvIVX(sstr);
+       SvIV_set(dstr, SvIVX(sstr));
        if (sflags & SVp_NOK) {
            if (sflags & SVf_NOK)
                (void)SvNOK_on(dstr);
            else
                (void)SvNOKp_on(dstr);
-           SvNVX(dstr) = SvNVX(sstr);
+           SvNV_set(dstr, SvNVX(sstr));
        }
     }
     else if (sflags & SVp_NOK) {
@@ -4665,7 +4645,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            (void)SvOK_off(dstr);
            SvNOKp_on(dstr);
        }
-       SvNVX(dstr) = SvNVX(sstr);
+       SvNV_set(dstr, SvNVX(sstr));
     }
     else {
        if (dtype == SVt_PVGV) {
@@ -4734,7 +4714,7 @@ Perl_sv_setsv_cow(pTHX_ SV *dstr, SV *sstr)
            UV hash = SvUVX(sstr);
            DEBUG_C(PerlIO_printf(Perl_debug_log,
                                  "Fast copy on write: Sharing hash\n"));
-           SvUVX(dstr) = hash;
+           SvUV_set(dstr, hash);
            new_pv = sharepvn(SvPVX(sstr), (SvUTF8(sstr)?-cur:cur), hash);
            goto common_exit;
        }
@@ -4756,8 +4736,8 @@ Perl_sv_setsv_cow(pTHX_ SV *dstr, SV *sstr)
     SvFLAGS(dstr) = (SVt_PVIV|SVf_POK|SVp_POK|SVf_FAKE|SVf_READONLY);
     if (SvUTF8(sstr))
        SvUTF8_on(dstr);
-    SvLEN(dstr) = len;
-    SvCUR(dstr) = cur;
+    SvLEN_set(dstr, len);
+    SvCUR_set(dstr, cur);
     if (DEBUG_C_TEST) {
        sv_dump(dstr);
     }
@@ -4884,11 +4864,10 @@ Perl_sv_usepvn(pTHX_ register SV *sv, register char *ptr, register STRLEN len)
        (void)SvOK_off(sv);
        return;
     }
-    (void)SvOOK_off(sv);
-    if (SvPVX(sv) && SvLEN(sv))
-       Safefree(SvPVX(sv));
+    if (SvPVX(sv))
+       SvPV_free(sv);
     Renew(ptr, len+1, char);
-    SvPVX(sv) = ptr;
+    SvPV_set(sv, ptr);
     SvCUR_set(sv, len);
     SvLEN_set(sv, len+1);
     *SvEND(sv) = '\0';
@@ -4996,15 +4975,15 @@ 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 New() a new one:  */
-            SvPVX(sv) = 0;
-            SvLEN(sv) = 0;
+            SvPV_set(sv, (char*)0);
+            SvLEN_set(sv, 0);
             if (flags & SV_COW_DROP_PV) {
                 /* OK, so we don't need to copy our buffer.  */
                 SvPOK_off(sv);
             } else {
                 SvGROW(sv, cur + 1);
                 Move(pvx,SvPVX(sv),cur,char);
-                SvCUR(sv) = cur;
+                SvCUR_set(sv, cur);
                 *SvEND(sv) = '\0';
             }
             sv_release_COW(sv, pvx, cur, len, hash, next);
@@ -5025,8 +5004,8 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
             U32 hash   = SvUVX(sv);
            SvFAKE_off(sv);
            SvREADONLY_off(sv);
-            SvPVX(sv) = 0;
-            SvLEN(sv) = 0;
+            SvPV_set(sv, (char*)0);
+            SvLEN_set(sv, 0);
            SvGROW(sv, len + 1);
            Move(pvx,SvPVX(sv),len,char);
            *SvEND(sv) = '\0';
@@ -5072,7 +5051,7 @@ refer to the same chunk of data.
 */
 
 void
-Perl_sv_chop(pTHX_ register SV *sv, register char *ptr)
+Perl_sv_chop(pTHX_ register SV *sv, register const char *ptr)
 {
     register STRLEN delta;
     if (!ptr || !SvPOKp(sv))
@@ -5084,23 +5063,23 @@ Perl_sv_chop(pTHX_ register SV *sv, register char *ptr)
 
     if (!SvOOK(sv)) {
        if (!SvLEN(sv)) { /* make copy of shared string */
-           char *pvx = SvPVX(sv);
+           const char *pvx = SvPVX(sv);
            STRLEN len = SvCUR(sv);
            SvGROW(sv, len + 1);
            Move(pvx,SvPVX(sv),len,char);
            *SvEND(sv) = '\0';
        }
-       SvIVX(sv) = 0;
+       SvIV_set(sv, 0);
        /* Same SvOOK_on but SvOOK_on does a SvIOK_off
           and we do that anyway inside the SvNIOK_off
        */
        SvFLAGS(sv) |= SVf_OOK;
     }
     SvNIOK_off(sv);
-    SvLEN(sv) -= delta;
-    SvCUR(sv) -= delta;
-    SvPVX(sv) += delta;
-    SvIVX(sv) += delta;
+    SvLEN_set(sv, SvLEN(sv) - delta);
+    SvCUR_set(sv, SvCUR(sv) - delta);
+    SvPV_set(sv, SvPVX(sv) + delta);
+    SvIV_set(sv, SvIVX(sv) + delta);
 }
 
 /* sv_catpvn() is now a macro using Perl_sv_catpvn_flags();
@@ -5137,14 +5116,13 @@ void
 Perl_sv_catpvn_flags(pTHX_ register SV *dsv, register const char *sstr, register STRLEN slen, I32 flags)
 {
     STRLEN dlen;
-    char *dstr;
+    const char *dstr = SvPV_force_flags(dsv, dlen, flags);
 
-    dstr = SvPV_force_flags(dsv, dlen, flags);
     SvGROW(dsv, dlen + slen + 1);
     if (sstr == dstr)
        sstr = SvPVX(dsv);
     Move(sstr, SvPVX(dsv) + dlen, slen, char);
-    SvCUR(dsv) += slen;
+    SvCUR_set(dsv, SvCUR(dsv) + slen);
     *SvEND(dsv) = '\0';
     (void)SvPOK_only_UTF8(dsv);                /* validate pointer */
     SvTAINT(dsv);
@@ -5267,7 +5245,7 @@ Perl_sv_catpv(pTHX_ register SV *sv, register const char *ptr)
     if (ptr == junk)
        ptr = SvPVX(sv);
     Move(ptr,SvPVX(sv)+tlen,len+1,char);
-    SvCUR(sv) += len;
+    SvCUR_set(sv, SvCUR(sv) + len);
     (void)SvPOK_only_UTF8(sv);         /* validate pointer */
     SvTAINT(sv);
 }
@@ -5329,7 +5307,7 @@ 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, MGVTBL *vtable,
+Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, const MGVTBL *vtable,
                 const char* name, I32 namlen)
 {
     MAGIC* mg;
@@ -5339,7 +5317,7 @@ Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, MGVTBL *vtable,
     }
     Newz(702,mg, 1, MAGIC);
     mg->mg_moremagic = SvMAGIC(sv);
-    SvMAGIC(sv) = mg;
+    SvMAGIC_set(sv, mg);
 
     /* Sometimes a magic contains a reference loop, where the sv and
        object refer to each other.  To prevent a reference loop that
@@ -5415,8 +5393,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 = 0;
     MAGIC* mg;
-    MGVTBL *vtable = 0;
 
 #ifdef PERL_COPY_ON_WRITE
     if (SvIsCOW(sv))
@@ -5559,7 +5537,7 @@ Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 nam
     }
 
     /* Rest of work is done else where */
-    mg = sv_magicext(sv,obj,how,vtable,name,namlen);
+    mg = sv_magicext(sv,obj,how,(MGVTBL*)vtable,name,namlen);
 
     switch (how) {
     case PERL_MAGIC_taint:
@@ -5590,7 +5568,7 @@ Perl_sv_unmagic(pTHX_ SV *sv, int type)
     mgp = &SvMAGIC(sv);
     for (mg = *mgp; mg; mg = *mgp) {
        if (mg->mg_type == type) {
-           MGVTBL* vtbl = mg->mg_virtual;
+            const MGVTBL* const vtbl = mg->mg_virtual;
            *mgp = mg->mg_moremagic;
            if (vtbl && vtbl->svt_free)
                CALL_FPTR(vtbl->svt_free)(aTHX_ sv, mg);
@@ -5709,7 +5687,7 @@ the Perl substr() function.
 */
 
 void
-Perl_sv_insert(pTHX_ SV *bigstr, STRLEN offset, STRLEN len, char *little, STRLEN littlelen)
+Perl_sv_insert(pTHX_ SV *bigstr, STRLEN offset, STRLEN len, const char *little, STRLEN littlelen)
 {
     register char *big;
     register char *mid;
@@ -5740,7 +5718,7 @@ Perl_sv_insert(pTHX_ SV *bigstr, STRLEN offset, STRLEN len, char *little, STRLEN
        while (midend > mid)            /* shove everything down */
            *--bigend = *--midend;
        Move(little,big+offset,littlelen,char);
-       SvCUR(bigstr) += i;
+       SvCUR_set(bigstr, SvCUR(bigstr) + i);
        SvSETMAGIC(bigstr);
        return;
     }
@@ -5818,15 +5796,22 @@ Perl_sv_replace(pTHX_ register SV *sv, register SV *nsv)
            mg_free(nsv);
        else
            sv_upgrade(nsv, SVt_PVMG);
-       SvMAGIC(nsv) = SvMAGIC(sv);
+       SvMAGIC_set(nsv, SvMAGIC(sv));
        SvFLAGS(nsv) |= SvMAGICAL(sv);
        SvMAGICAL_off(sv);
-       SvMAGIC(sv) = 0;
+       SvMAGIC_set(sv, NULL);
     }
     SvREFCNT(sv) = 0;
     sv_clear(sv);
     assert(!SvREFCNT(sv));
+#ifdef DEBUG_LEAKING_SCALARS
+    sv->sv_flags  = nsv->sv_flags;
+    sv->sv_any    = nsv->sv_any;
+    sv->sv_refcnt = nsv->sv_refcnt;
+#else
     StructCopy(nsv,sv,SV);
+#endif
+
 #ifdef PERL_COPY_ON_WRITE
     if (SvIsCOW_normal(nsv)) {
        /* We need to follow the pointers around the loop to make the
@@ -5872,6 +5857,7 @@ instead.
 void
 Perl_sv_clear(pTHX_ register SV *sv)
 {
+    dVAR;
     HV* stash;
     assert(sv);
     assert(SvREFCNT(sv) == 0);
@@ -5904,7 +5890,7 @@ Perl_sv_clear(pTHX_ register SV *sv)
                    if(SvREFCNT(tmpref) < 2) {
                        /* tmpref is not kept alive! */
                        SvREFCNT(sv)--;
-                       SvRV(tmpref) = 0;
+                       SvRV_set(tmpref, NULL);
                        SvROK_off(tmpref);
                    }
                    SvREFCNT_dec(tmpref);
@@ -5985,7 +5971,11 @@ Perl_sv_clear(pTHX_ register SV *sv)
     case SVt_PVNV:
     case SVt_PVIV:
       freescalar:
-       SvOOK_off(sv);
+       /* Don't bother with SvOOK_off(sv); as we're only going to free it.  */
+       if (SvOOK(sv)) {
+           SvPV_set(sv, SvPVX(sv) - SvIVX(sv));
+           /* Don't even bother with turning off the OOK flag.  */
+       }
        /* FALL THROUGH */
     case SVt_PV:
     case SVt_RV:
@@ -6121,6 +6111,7 @@ Normally called via a wrapper macro C<SvREFCNT_dec>.
 void
 Perl_sv_free(pTHX_ SV *sv)
 {
+    dVAR;
     if (!sv)
        return;
     if (SvREFCNT(sv) == 0) {
@@ -6149,6 +6140,7 @@ Perl_sv_free(pTHX_ SV *sv)
 void
 Perl_sv_free2(pTHX_ SV *sv)
 {
+    dVAR;
 #ifdef DEBUGGING
     if (SvTEMP(sv)) {
        if (ckWARN_d(WARN_DEBUGGING))
@@ -6259,7 +6251,7 @@ S_utf8_mg_pos_init(pTHX_ SV *sv, MAGIC **mgp, STRLEN **cachep, I32 i, I32 *offse
 
     if (SvMAGICAL(sv) && !SvREADONLY(sv)) {
        if (!*mgp)
-           *mgp = sv_magicext(sv, 0, PERL_MAGIC_utf8, &PL_vtbl_utf8, 0, 0);
+           *mgp = sv_magicext(sv, 0, PERL_MAGIC_utf8, (MGVTBL*)&PL_vtbl_utf8, 0, 0);
        assert(*mgp);
 
        if ((*mgp)->mg_ptr)
@@ -6448,7 +6440,7 @@ Perl_sv_pos_u2b(pTHX_ register SV *sv, I32* offsetp, I32* lenp)
         if (lenp) {
              found = FALSE;
              start = s;
-              if (utf8_mg_pos(sv, &mg, &cache, 2, lenp, *lenp + *offsetp, &s, start, send)) {
+              if (utf8_mg_pos(sv, &mg, &cache, 2, lenp, *lenp, &s, start, send)) {
                   *lenp -= boffset;
                   found = TRUE;
               }
@@ -6617,9 +6609,9 @@ coerce its args to strings if necessary.
 I32
 Perl_sv_eq(pTHX_ register SV *sv1, register SV *sv2)
 {
-    char *pv1;
+    const char *pv1;
     STRLEN cur1;
-    char *pv2;
+    const char *pv2;
     STRLEN cur2;
     I32  eq     = 0;
     char *tpv   = Nullch;
@@ -6665,7 +6657,7 @@ Perl_sv_eq(pTHX_ register SV *sv1, register SV *sv2)
              if (SvUTF8(sv1)) {
                   /* sv1 is the UTF-8 one,
                    * if is equal it must be downgrade-able */
-                  char *pv = (char*)bytes_from_utf8((U8*)pv1,
+                  char *pv = (char*)bytes_from_utf8((const U8*)pv1,
                                                     &cur1, &is_utf8);
                   if (pv != pv1)
                        pv1 = tpv = pv;
@@ -6673,7 +6665,7 @@ Perl_sv_eq(pTHX_ register SV *sv1, register SV *sv2)
              else {
                   /* sv2 is the UTF-8 one,
                    * if is equal it must be downgrade-able */
-                  char *pv = (char *)bytes_from_utf8((U8*)pv2,
+                  char *pv = (char *)bytes_from_utf8((const U8*)pv2,
                                                      &cur2, &is_utf8);
                   if (pv != pv2)
                        pv2 = tpv = pv;
@@ -6713,7 +6705,8 @@ I32
 Perl_sv_cmp(pTHX_ register SV *sv1, register SV *sv2)
 {
     STRLEN cur1, cur2;
-    char *pv1, *pv2, *tpv = Nullch;
+    const char *pv1, *pv2;
+    char *tpv = Nullch;
     I32  cmp;
     SV *svrecode = Nullsv;
 
@@ -6741,7 +6734,7 @@ Perl_sv_cmp(pTHX_ register SV *sv1, register SV *sv2)
                 pv2 = SvPV(svrecode, cur2);
            }
            else {
-                pv2 = tpv = (char*)bytes_to_utf8((U8*)pv2, &cur2);
+                pv2 = tpv = (char*)bytes_to_utf8((const U8*)pv2, &cur2);
            }
        }
        else {
@@ -6751,7 +6744,7 @@ Perl_sv_cmp(pTHX_ register SV *sv1, register SV *sv2)
                 pv1 = SvPV(svrecode, cur1);
            }
            else {
-                pv1 = tpv = (char*)bytes_to_utf8((U8*)pv1, &cur1);
+                pv1 = tpv = (char*)bytes_to_utf8((const U8*)pv1, &cur1);
            }
        }
     }
@@ -6761,7 +6754,7 @@ Perl_sv_cmp(pTHX_ register SV *sv1, register SV *sv2)
     } else if (!cur2) {
        cmp = 1;
     } else {
-       I32 retval = memcmp((void*)pv1, (void*)pv2, cur1 < cur2 ? cur1 : cur2);
+        const I32 retval = memcmp((const void*)pv1, (const void*)pv2, cur1 < cur2 ? cur1 : cur2);
 
        if (retval) {
            cmp = retval < 0 ? -1 : 1;
@@ -6913,7 +6906,7 @@ appending to the currently-stored string.
 char *
 Perl_sv_gets(pTHX_ register SV *sv, register PerlIO *fp, I32 append)
 {
-    char *rsptr;
+    const char *rsptr;
     STRLEN rslen;
     register STDCHAR rslast;
     register STDCHAR *bp;
@@ -6967,7 +6960,7 @@ Perl_sv_gets(pTHX_ register SV *sv, register PerlIO *fp, I32 append)
         */
        Stat_t st;
        if (!PerlLIO_fstat(PerlIO_fileno(fp), &st) && S_ISREG(st.st_mode))  {
-           Off_t offset = PerlIO_tell(fp);
+           const Off_t offset = PerlIO_tell(fp);
            if (offset != (Off_t) -1 && st.st_size + append > offset) {
                (void) SvGROW(sv, (STRLEN)((st.st_size - offset) + append + 1));
            }
@@ -7182,17 +7175,7 @@ thats_really_all_folks:
    else
     {
        /*The big, slow, and stupid way. */
-
-      /* Any stack-challenged places. */
-#if defined(EPOC)
-      /* EPOC: need to work around SDK features.         *
-       * On WINS: MS VC5 generates calls to _chkstk,     *
-       * if a "large" stack frame is allocated.          *
-       * gcc on MARM does not generate calls like these. */
-#   define USEHEAPINSTEADOFSTACK
-#endif
-
-#ifdef USEHEAPINSTEADOFSTACK
+#ifdef USE_HEAP_INSTEAD_OF_STACK       /* Even slower way. */
        STDCHAR *buf = 0;
        New(0, buf, 8192, STDCHAR);
        assert(buf);
@@ -7202,7 +7185,7 @@ thats_really_all_folks:
 
 screamer2:
        if (rslen) {
-           register STDCHAR *bpe = buf + sizeof(buf);
+            const register STDCHAR *bpe = buf + sizeof(buf);
            bp = buf;
            while ((i = PerlIO_getc(fp)) != EOF && (*bp++ = (STDCHAR)i) != rslast && bp < bpe)
                ; /* keep reading */
@@ -7247,7 +7230,7 @@ screamer2:
                goto screamer2;
        }
 
-#ifdef USEHEAPINSTEADOFSTACK
+#ifdef USE_HEAP_INSTEAD_OF_STACK
        Safefree(buf);
 #endif
     }
@@ -7318,20 +7301,20 @@ Perl_sv_inc(pTHX_ register SV *sv)
                sv_setnv(sv, UV_MAX_P1);
            else
                (void)SvIOK_only_UV(sv);
-               ++SvUVX(sv);
+               SvUV_set(sv, SvUVX(sv) + 1);
        } else {
            if (SvIVX(sv) == IV_MAX)
                sv_setuv(sv, (UV)IV_MAX + 1);
            else {
                (void)SvIOK_only(sv);
-               ++SvIVX(sv);
+               SvIV_set(sv, SvIVX(sv) + 1);
            }   
        }
        return;
     }
     if (flags & SVp_NOK) {
        (void)SvNOK_only(sv);
-       SvNVX(sv) += 1.0;
+        SvNV_set(sv, SvNVX(sv) + 1.0);
        return;
     }
 
@@ -7339,7 +7322,7 @@ Perl_sv_inc(pTHX_ register SV *sv)
        if ((flags & SVTYPEMASK) < SVt_PVIV)
            sv_upgrade(sv, SVt_IV);
        (void)SvIOK_only(sv);
-       SvIVX(sv) = 1;
+       SvIV_set(sv, 1);
        return;
     }
     d = SvPVX(sv);
@@ -7366,7 +7349,7 @@ Perl_sv_inc(pTHX_ register SV *sv)
            /* sv_2iv *should* have made this an NV */
            if (flags & SVp_NOK) {
                (void)SvNOK_only(sv);
-               SvNVX(sv) += 1.0;
+                SvNV_set(sv, SvNVX(sv) + 1.0);
                return;
            }
            /* I don't think we can get here. Maybe I should assert this
@@ -7414,7 +7397,7 @@ Perl_sv_inc(pTHX_ register SV *sv)
     }
     /* oh,oh, the number grew */
     SvGROW(sv, SvCUR(sv) + 2);
-    SvCUR(sv)++;
+    SvCUR_set(sv, SvCUR(sv) + 1);
     for (d = SvPVX(sv) + SvCUR(sv); d > SvPVX(sv); d--)
        *d = d[-1];
     if (isDIGIT(d[1]))
@@ -7468,31 +7451,31 @@ Perl_sv_dec(pTHX_ register SV *sv)
        if (SvIsUV(sv)) {
            if (SvUVX(sv) == 0) {
                (void)SvIOK_only(sv);
-               SvIVX(sv) = -1;
+               SvIV_set(sv, -1);
            }
            else {
                (void)SvIOK_only_UV(sv);
-               --SvUVX(sv);
+               SvUV_set(sv, SvUVX(sv) + 1);
            }   
        } else {
            if (SvIVX(sv) == IV_MIN)
                sv_setnv(sv, (NV)IV_MIN - 1.0);
            else {
                (void)SvIOK_only(sv);
-               --SvIVX(sv);
+               SvIV_set(sv, SvIVX(sv) - 1);
            }   
        }
        return;
     }
     if (flags & SVp_NOK) {
-       SvNVX(sv) -= 1.0;
+        SvNV_set(sv, SvNVX(sv) - 1.0);
        (void)SvNOK_only(sv);
        return;
     }
     if (!(flags & SVp_POK)) {
        if ((flags & SVTYPEMASK) < SVt_PVNV)
            sv_upgrade(sv, SVt_NV);
-       SvNVX(sv) = -1.0;
+       SvNV_set(sv, 1.0);
        (void)SvNOK_only(sv);
        return;
     }
@@ -7514,7 +7497,7 @@ Perl_sv_dec(pTHX_ register SV *sv)
            /* sv_2iv *should* have made this an NV */
            if (flags & SVp_NOK) {
                (void)SvNOK_only(sv);
-               SvNVX(sv) -= 1.0;
+                SvNV_set(sv, SvNVX(sv) - 1.0);
                return;
            }
            /* I don't think we can get here. Maybe I should assert this
@@ -7600,6 +7583,7 @@ and C<sv_mortalcopy>.
 SV *
 Perl_sv_2mortal(pTHX_ register SV *sv)
 {
+    dVAR;
     if (!sv)
        return sv;
     if (SvREADONLY(sv) && SvIMMORTAL(sv))
@@ -7676,17 +7660,17 @@ Perl_newSVpvn_share(pTHX_ const char *src, I32 len, U32 hash)
        STRLEN tmplen = -len;
         is_utf8 = TRUE;
        /* See the note in hv.c:hv_fetch() --jhi */
-       src = (char*)bytes_from_utf8((U8*)src, &tmplen, &is_utf8);
+       src = (char*)bytes_from_utf8((const U8*)src, &tmplen, &is_utf8);
        len = tmplen;
     }
     if (!hash)
        PERL_HASH(hash, src, len);
     new_SV(sv);
     sv_upgrade(sv, SVt_PVIV);
-    SvPVX(sv) = sharepvn(src, is_utf8?-len:len, hash);
-    SvCUR(sv) = len;
-    SvUVX(sv) = hash;
-    SvLEN(sv) = 0;
+    SvPV_set(sv, sharepvn(src, is_utf8?-len:len, hash));
+    SvCUR_set(sv, len);
+    SvUV_set(sv, hash);
+    SvLEN_set(sv, 0);
     SvREADONLY_on(sv);
     SvFAKE_on(sv);
     SvPOK_on(sv);
@@ -7821,7 +7805,7 @@ Perl_newRV_noinc(pTHX_ SV *tmpRef)
     new_SV(sv);
     sv_upgrade(sv, SVt_RV);
     SvTEMP_off(tmpRef);
-    SvRV(sv) = tmpRef;
+    SvRV_set(sv, tmpRef);
     SvROK_on(sv);
     return sv;
 }
@@ -7858,13 +7842,10 @@ Perl_newSVsv(pTHX_ register SV *old)
        return Nullsv;
     }
     new_SV(sv);
-    if (SvTEMP(old)) {
-       SvTEMP_off(old);
-       sv_setsv(sv,old);
-       SvTEMP_on(old);
-    }
-    else
-       sv_setsv(sv,old);
+    /* SV_GMAGIC is the default for sv_setv()
+       SV_NOSTEAL prevents TEMP buffers being, well, stolen, and saves games
+       with SvTEMP_off and SvTEMP_on round a call to sv_setsv.  */
+    sv_setsv_flags(sv, old, SV_GMAGIC | SV_NOSTEAL);
     return sv;
 }
 
@@ -7878,8 +7859,9 @@ Note that the perl-level function is vaguely deprecated.
 */
 
 void
-Perl_sv_reset(pTHX_ register char *s, HV *stash)
+Perl_sv_reset(pTHX_ register const char *s, HV *stash)
 {
+    dVAR;
     register HE *entry;
     register GV *gv;
     register SV *sv;
@@ -8012,6 +7994,7 @@ possible to set C<*st> and C<*gvp> to the stash and GV associated with it.
 CV *
 Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref)
 {
+    dVAR;
     GV *gv = Nullgv;
     CV *cv = Nullcv;
 
@@ -8097,7 +8080,7 @@ Perl_sv_true(pTHX_ register SV *sv)
     if (!sv)
        return 0;
     if (SvPOK(sv)) {
-       register XPV* tXpv;
+       const register XPV* tXpv;
        if ((tXpv = (XPV*)SvANY(sv)) &&
                (tXpv->xpv_cur > 1 ||
                (tXpv->xpv_cur && *tXpv->xpv_pv != '0')))
@@ -8402,11 +8385,13 @@ Returns a string describing what the SV is a reference to.
 */
 
 char *
-Perl_sv_reftype(pTHX_ SV *sv, int ob)
+Perl_sv_reftype(pTHX_ const SV *sv, int ob)
 {
+    /* The fact that I don't need to downcast to char * everywhere, only in ?:
+       inside return suggests a const propagation bug in g++.  */
     if (ob && SvOBJECT(sv)) {
        char *name = HvNAME(SvSTASH(sv));
-       return name ? name : "__ANON__";
+       return name ? name : (char *) "__ANON__";
     }
     else {
        switch (SvTYPE(sv)) {
@@ -8419,18 +8404,18 @@ Perl_sv_reftype(pTHX_ SV *sv, int ob)
        case SVt_PVNV:
        case SVt_PVMG:
        case SVt_PVBM:
-                               if (SvVOK(sv))
+                               if (SvVOK(sv))
                                    return "VSTRING";
                                if (SvROK(sv))
                                    return "REF";
                                else
                                    return "SCALAR";
-                               
-       case SVt_PVLV:          return SvROK(sv) ? "REF"
+
+       case SVt_PVLV:          return (char *)  (SvROK(sv) ? "REF"
                                /* tied lvalues should appear to be
                                 * scalars for backwards compatitbility */
                                : (LvTYPE(sv) == 't' || LvTYPE(sv) == 'T')
-                                   ? "SCALAR" : "LVALUE";
+                                   ? "SCALAR" : "LVALUE");
        case SVt_PVAV:          return "ARRAY";
        case SVt_PVHV:          return "HASH";
        case SVt_PVCV:          return "CODE";
@@ -8527,15 +8512,13 @@ Perl_newSVrv(pTHX_ SV *rv, const char *classname)
     if (SvTYPE(rv) < SVt_RV)
        sv_upgrade(rv, SVt_RV);
     else if (SvTYPE(rv) > SVt_RV) {
-       SvOOK_off(rv);
-       if (SvPVX(rv) && SvLEN(rv))
-           Safefree(SvPVX(rv));
+       SvPV_free(rv);
        SvCUR_set(rv, 0);
        SvLEN_set(rv, 0);
     }
 
     SvOK_off(rv);
-    SvRV(rv) = sv;
+    SvRV_set(rv, sv);
     SvROK_on(rv);
 
     if (classname) {
@@ -8684,7 +8667,7 @@ Perl_sv_bless(pTHX_ SV *sv, HV *stash)
     if (SvTYPE(tmpRef) != SVt_PVIO)
        ++PL_sv_objcount;
     (void)SvUPGRADE(tmpRef, SVt_PVMG);
-    SvSTASH(tmpRef) = (HV*)SvREFCNT_inc(stash);
+    SvSTASH_set(tmpRef, (HV*)SvREFCNT_inc(stash));
 
     if (Gv_AMG(stash))
        SvAMAGIC_on(sv);
@@ -8752,10 +8735,10 @@ Perl_sv_unref_flags(pTHX_ SV *sv, U32 flags)
     if (SvWEAKREF(sv)) {
        sv_del_backref(sv);
        SvWEAKREF_off(sv);
-       SvRV(sv) = 0;
+       SvRV_set(sv, NULL);
        return;
     }
-    SvRV(sv) = 0;
+    SvRV_set(sv, NULL);
     SvROK_off(sv);
     /* You can't have a || SvREADONLY(rv) here, as $a = $$a, where $a was
        assigned to as BEGIN {$a = \"Foo"} will fail.  */
@@ -9011,7 +8994,8 @@ output to an SV.  If the appended data contains "wide" characters
 (including, but not limited to, SVs with a UTF-8 PV formatted with %s,
 and characters >255 formatted with %c), the original SV might get
 upgraded to UTF-8.  Handles 'get' magic, but not 'set' magic.  See
-C<sv_catpvf_mg>.
+C<sv_catpvf_mg>. If the original SV was UTF-8, the pattern should be
+valid UTF-8; if the original SV was bytes, the pattern should be too.
 
 =cut */
 
@@ -9151,6 +9135,8 @@ Usually used via one of its frontends C<sv_vcatpvf> and C<sv_vcatpvf_mg>.
 =cut
 */
 
+/* XXX maybe_tainted is never assigned to, so the doc above is lying. */
+
 void
 Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, bool *maybe_tainted)
 {
@@ -9159,7 +9145,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     char *patend;
     STRLEN origlen;
     I32 svix = 0;
-    static char nullstr[] = "(null)";
+    static const char nullstr[] = "(null)";
     SV *argsv = Nullsv;
     bool has_utf8; /* has the result utf8? */
     bool pat_utf8; /* the pattern is in utf8? */
@@ -9183,7 +9169,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        switch (pat[1]) {
        case 's':
            if (args) {
-               char *s = va_arg(*args, char*);
+                const char *s = va_arg(*args, char*);
                sv_catpv(sv, s ? s : nullstr);
            }
            else if (svix < svmax) {
@@ -9273,7 +9259,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 #endif
 
        char esignbuf[4];
-       U8 utf8buf[UTF8_MAXLEN+1];
+       U8 utf8buf[UTF8_MAXBYTES+1];
        STRLEN esignlen = 0;
 
        char *eptr = Nullch;
@@ -9297,7 +9283,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        STRLEN have;
        STRLEN need;
        STRLEN gap;
-       char *dotstr = ".";
+        const char *dotstr = ".";
        STRLEN dotstrlen = 1;
        I32 efix = 0; /* explicit format parameter index */
        I32 ewix = 0; /* explicit width index */
@@ -9392,11 +9378,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                fill = *q++;
            EXPECT_NUMBER(q, width);
 
-#ifdef CHECK_FORMAT
-       if ((*q == 'p') && left) {
-            vectorize = (width == 1);
-       }
-#endif
        if (vectorize) {
            if (vectorarg) {
                if (args)
@@ -9567,7 +9548,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 #endif
                    elen = strlen(eptr);
                else {
-                   eptr = nullstr;
+                   eptr = (char *)nullstr;
                    elen = sizeof nullstr - 1;
                }
            }
@@ -9617,10 +9598,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                left = FALSE;
                if (!width)
                    goto format_sv;     /* %-p  -> %_   */
-               if (vectorize) {
-                   width = 0;
-                   goto format_d;      /* %-1p -> %vd  */      
-               }
                precis = width;
                has_precis = TRUE;
                width = 0;
@@ -9639,9 +9616,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 #else
            intsize = 'l';
 #endif
-#ifdef CHECK_FORMAT
-       format_d:
-#endif
            /* FALL THROUGH */
        case 'd':
        case 'i':
@@ -9806,19 +9780,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                }
                break;
            default:            /* it had better be ten or less */
-#if defined(PERL_Y2KWARN)
-               if (ckWARN(WARN_Y2K)) {
-                   STRLEN n;
-                   char *s = SvPV(sv,n);
-                   if (n >= 2 && s[n-2] == '1' && s[n-1] == '9'
-                       && (n == 2 || !isDIGIT(s[n-3])))
-                   {
-                       Perl_warner(aTHX_ packWARN(WARN_Y2K),
-                                   "Possible Y2K bug: %%%c %s",
-                                   c, "format string following '19'");
-                   }
-               }
-#endif
                do {
                    dig = uv % base;
                    *--eptr = '0' + dig;
@@ -10091,7 +10052,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            Copy(eptr, p, elen, char);
            p += elen;
            *p = '\0';
-           SvCUR(sv) = p - SvPVX(sv);
+           SvCUR_set(sv, p - SvPVX(sv));
            svix = osvix;
            continue;   /* not "break" */
        }
@@ -10157,7 +10118,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        if (has_utf8)
            SvUTF8_on(sv);
        *p = '\0';
-       SvCUR(sv) = p - SvPVX(sv);
+       SvCUR_set(sv, p - SvPVX(sv));
        if (vectorize) {
            esignlen = 0;
            goto vector;
@@ -10210,6 +10171,7 @@ ptr_table_* functions.
 REGEXP *
 Perl_re_dup(pTHX_ REGEXP *r, CLONE_PARAMS *param)
 {
+    dVAR;
     REGEXP *ret;
     int i, len, npar;
     struct reg_substr_datum *s;
@@ -10242,7 +10204,7 @@ Perl_re_dup(pTHX_ REGEXP *r, CLONE_PARAMS *param)
     ret->regstclass = NULL;
     if (r->data) {
        struct reg_data *d;
-       int count = r->data->count;
+        const int count = r->data->count;
 
        Newc(0, d, sizeof(struct reg_data) + count*sizeof(void *),
                char, struct reg_data);
@@ -10252,6 +10214,8 @@ Perl_re_dup(pTHX_ REGEXP *r, CLONE_PARAMS *param)
        for (i = 0; i < count; i++) {
            d->what[i] = r->data->what[i];
            switch (d->what[i]) {
+               /* legal options are one of: sfpont
+                  see also regcomp.h and pregfree() */
            case 's':
                d->data[i] = sv_dup_inc((SV *)r->data->data[i], param);
                break;
@@ -10275,6 +10239,14 @@ Perl_re_dup(pTHX_ REGEXP *r, CLONE_PARAMS *param)
            case 'n':
                d->data[i] = r->data->data[i];
                break;
+           case 't':
+               d->data[i] = r->data->data[i];
+               OP_REFCNT_LOCK;
+               ((reg_trie_data*)d->data[i])->refcount++;
+               OP_REFCNT_UNLOCK;
+               break;
+            default:
+               Perl_croak(aTHX_ "panic: re_dup unknown data code '%c'", r->data->what[i]);
            }
        }
 
@@ -10315,6 +10287,8 @@ PerlIO *
 Perl_fp_dup(pTHX_ PerlIO *fp, char type, CLONE_PARAMS *param)
 {
     PerlIO *ret;
+    (void)type;
+
     if (!fp)
        return (PerlIO*)NULL;
 
@@ -10402,10 +10376,10 @@ 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) {
-           AV *av = (AV*) mg->mg_obj;
+           const AV * const av = (AV*) mg->mg_obj;
            SV **svp;
            I32 i;
-           SvREFCNT_inc(nmg->mg_obj = (SV*)newAV());
+           (void)SvREFCNT_inc(nmg->mg_obj = (SV*)newAV());
            svp = AvARRAY(av);
            for (i = AvFILLp(av); i >= 0; i--) {
                if (!svp[i]) continue;
@@ -10463,13 +10437,51 @@ Perl_ptr_table_new(pTHX)
 #  define PTR_TABLE_HASH(ptr) (PTR2UV(ptr) >> 2)
 #endif
 
+
+
+STATIC void
+S_more_pte(pTHX)
+{
+    register struct ptr_tbl_ent* pte;
+    register struct ptr_tbl_ent* pteend;
+    New(0, pte, PERL_ARENA_SIZE/sizeof(struct ptr_tbl_ent), struct ptr_tbl_ent);
+    pte->next = PL_pte_arenaroot;
+    PL_pte_arenaroot = pte;
+
+    pteend = &pte[PERL_ARENA_SIZE / sizeof(struct ptr_tbl_ent) - 1];
+    PL_pte_root = ++pte;
+    while (pte < pteend) {
+       pte->next = pte + 1;
+       pte++;
+    }
+    pte->next = 0;
+}
+
+STATIC struct ptr_tbl_ent*
+S_new_pte(pTHX)
+{
+    struct ptr_tbl_ent* pte;
+    if (!PL_pte_root)
+       S_more_pte(aTHX);
+    pte = PL_pte_root;
+    PL_pte_root = pte->next;
+    return pte;
+}
+
+STATIC void
+S_del_pte(pTHX_ struct ptr_tbl_ent*p)
+{
+    p->next = PL_pte_root;
+    PL_pte_root = p;
+}
+
 /* map an existing pointer using a table */
 
 void *
 Perl_ptr_table_fetch(pTHX_ PTR_TBL_t *tbl, void *sv)
 {
     PTR_TBL_ENT_t *tblent;
-    UV hash = PTR_TABLE_HASH(sv);
+    const UV hash = PTR_TABLE_HASH(sv);
     assert(tbl);
     tblent = tbl->tbl_ary[hash & tbl->tbl_max];
     for (; tblent; tblent = tblent->next) {
@@ -10488,7 +10500,7 @@ Perl_ptr_table_store(pTHX_ PTR_TBL_t *tbl, void *oldv, void *newv)
     /* XXX this may be pessimal on platforms where pointers aren't good
      * hash values e.g. if they grow faster in the most significant
      * bits */
-    UV hash = PTR_TABLE_HASH(oldv);
+    const UV hash = PTR_TABLE_HASH(oldv);
     bool empty = 1;
 
     assert(tbl);
@@ -10499,7 +10511,7 @@ Perl_ptr_table_store(pTHX_ PTR_TBL_t *tbl, void *oldv, void *newv)
            return;
        }
     }
-    Newz(0, tblent, 1, PTR_TBL_ENT_t);
+    tblent = S_new_pte(aTHX);
     tblent->oldval = oldv;
     tblent->newval = newv;
     tblent->next = *otblent;
@@ -10515,7 +10527,7 @@ void
 Perl_ptr_table_split(pTHX_ PTR_TBL_t *tbl)
 {
     PTR_TBL_ENT_t **ary = tbl->tbl_ary;
-    UV oldsize = tbl->tbl_max + 1;
+    const UV oldsize = tbl->tbl_max + 1;
     UV newsize = oldsize * 2;
     UV i;
 
@@ -10548,7 +10560,6 @@ Perl_ptr_table_clear(pTHX_ PTR_TBL_t *tbl)
 {
     register PTR_TBL_ENT_t **array;
     register PTR_TBL_ENT_t *entry;
-    register PTR_TBL_ENT_t *oentry = Null(PTR_TBL_ENT_t*);
     UV riter = 0;
     UV max;
 
@@ -10562,9 +10573,9 @@ Perl_ptr_table_clear(pTHX_ PTR_TBL_t *tbl)
 
     for (;;) {
         if (entry) {
-            oentry = entry;
+            PTR_TBL_ENT_t *oentry = entry;
             entry = entry->next;
-            Safefree(oentry);
+            S_del_pte(aTHX_ oentry);
         }
         if (!entry) {
             if (++riter > max) {
@@ -10590,10 +10601,6 @@ Perl_ptr_table_free(pTHX_ PTR_TBL_t *tbl)
     Safefree(tbl);
 }
 
-#ifdef DEBUGGING
-char *PL_watch_pvx;
-#endif
-
 /* attempt to make everything in the typeglob readonly */
 
 STATIC SV *
@@ -10657,15 +10664,16 @@ void
 Perl_rvpv_dup(pTHX_ SV *dstr, SV *sstr, CLONE_PARAMS* param)
 {
     if (SvROK(sstr)) {
-       SvRV(dstr) = SvWEAKREF(sstr)
-                    ? sv_dup(SvRV(sstr), param)
-                    : sv_dup_inc(SvRV(sstr), param);
+       SvRV_set(dstr, SvWEAKREF(sstr)
+                      ? sv_dup(SvRV(sstr), param)
+                      : sv_dup_inc(SvRV(sstr), param));
+
     }
     else if (SvPVX(sstr)) {
        /* Has something there */
        if (SvLEN(sstr)) {
            /* Normal PV - clone whole allocated space */
-           SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1);
+           SvPV_set(dstr, SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1));
            if (SvREADONLY(sstr) && SvFAKE(sstr)) {
                /* Not that normal - actually sstr is copy on write.
                   But we are a true, independant SV, so:  */
@@ -10682,31 +10690,35 @@ Perl_rvpv_dup(pTHX_ SV *dstr, SV *sstr, CLONE_PARAMS* param)
                        and they should not have these flags
                        turned off */
 
-                    SvPVX(dstr) = sharepvn(SvPVX(sstr), SvCUR(sstr),
-                                           SvUVX(sstr));
-                    SvUVX(dstr) = SvUVX(sstr);
+                    SvPV_set(dstr, sharepvn(SvPVX(sstr), SvCUR(sstr),
+                                           SvUVX(sstr)));
+                    SvUV_set(dstr, SvUVX(sstr));
                 } else {
 
-                    SvPVX(dstr) = SAVEPVN(SvPVX(sstr), SvCUR(sstr));
+                    SvPV_set(dstr, SAVEPVN(SvPVX(sstr), SvCUR(sstr)));
                     SvFAKE_off(dstr);
                     SvREADONLY_off(dstr);
                 }
            }
            else {
                /* Some other special case - random pointer */
-               SvPVX(dstr) = SvPVX(sstr);              
+               SvPV_set(dstr, SvPVX(sstr));            
            }
        }
     }
     else {
        /* Copy the Null */
-       SvPVX(dstr) = SvPVX(sstr);
+       if (SvTYPE(dstr) == SVt_RV)
+           SvRV_set(dstr, NULL);
+       else
+           SvPV_set(dstr, 0);
     }
 }
 
 SV *
 Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
 {
+    dVAR;
     SV *dstr;
 
     if (!sstr || SvTYPE(sstr) == SVTYPEMASK)
@@ -10730,6 +10742,19 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
 
     /* create anew and remember what it is */
     new_SV(dstr);
+
+#ifdef DEBUG_LEAKING_SCALARS
+    dstr->sv_debug_optype = sstr->sv_debug_optype;
+    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);
 
     /* clone */
@@ -10743,17 +10768,24 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
                      PL_watch_pvx, SvPVX(sstr));
 #endif
 
+    /* don't clone objects whose class has asked us not to */
+    if (SvOBJECT(sstr) && ! (SvFLAGS(SvSTASH(sstr)) & SVphv_CLONEABLE)) {
+       SvFLAGS(dstr) &= ~SVTYPEMASK;
+       SvOBJECT_off(dstr);
+       return dstr;
+    }
+
     switch (SvTYPE(sstr)) {
     case SVt_NULL:
        SvANY(dstr)     = NULL;
        break;
     case SVt_IV:
        SvANY(dstr)     = new_XIV();
-       SvIVX(dstr)     = SvIVX(sstr);
+       SvIV_set(dstr, SvIVX(sstr));
        break;
     case SVt_NV:
        SvANY(dstr)     = new_XNV();
-       SvNVX(dstr)     = SvNVX(sstr);
+       SvNV_set(dstr, SvNVX(sstr));
        break;
     case SVt_RV:
        SvANY(dstr)     = new_XRV();
@@ -10761,43 +10793,43 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        break;
     case SVt_PV:
        SvANY(dstr)     = new_XPV();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        break;
     case SVt_PVIV:
        SvANY(dstr)     = new_XPVIV();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        break;
     case SVt_PVNV:
        SvANY(dstr)     = new_XPVNV();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
-       SvNVX(dstr)     = SvNVX(sstr);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
+       SvNV_set(dstr, SvNVX(sstr));
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        break;
     case SVt_PVMG:
        SvANY(dstr)     = new_XPVMG();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
-       SvNVX(dstr)     = SvNVX(sstr);
-       SvMAGIC(dstr)   = mg_dup(SvMAGIC(sstr), param);
-       SvSTASH(dstr)   = hv_dup_inc(SvSTASH(sstr), param);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
+       SvNV_set(dstr, SvNVX(sstr));
+       SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
+       SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        break;
     case SVt_PVBM:
        SvANY(dstr)     = new_XPVBM();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
-       SvNVX(dstr)     = SvNVX(sstr);
-       SvMAGIC(dstr)   = mg_dup(SvMAGIC(sstr), param);
-       SvSTASH(dstr)   = hv_dup_inc(SvSTASH(sstr), param);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
+       SvNV_set(dstr, SvNVX(sstr));
+       SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
+       SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        BmRARE(dstr)    = BmRARE(sstr);
        BmUSEFUL(dstr)  = BmUSEFUL(sstr);
@@ -10805,12 +10837,12 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        break;
     case SVt_PVLV:
        SvANY(dstr)     = new_XPVLV();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
-       SvNVX(dstr)     = SvNVX(sstr);
-       SvMAGIC(dstr)   = mg_dup(SvMAGIC(sstr), param);
-       SvSTASH(dstr)   = hv_dup_inc(SvSTASH(sstr), param);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
+       SvNV_set(dstr, SvNVX(sstr));
+       SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
+       SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        LvTARGOFF(dstr) = LvTARGOFF(sstr);      /* XXX sometimes holds PMOP* when DEBUGGING */
        LvTARGLEN(dstr) = LvTARGLEN(sstr);
@@ -10837,12 +10869,12 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
             }
        }
        SvANY(dstr)     = new_XPVGV();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
-       SvNVX(dstr)     = SvNVX(sstr);
-       SvMAGIC(dstr)   = mg_dup(SvMAGIC(sstr), param);
-       SvSTASH(dstr)   = hv_dup_inc(SvSTASH(sstr), param);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
+       SvNV_set(dstr, SvNVX(sstr));
+       SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
+       SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        GvNAMELEN(dstr) = GvNAMELEN(sstr);
        GvNAME(dstr)    = SAVEPVN(GvNAME(sstr), GvNAMELEN(sstr));
@@ -10853,12 +10885,12 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        break;
     case SVt_PVIO:
        SvANY(dstr)     = new_XPVIO();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
-       SvNVX(dstr)     = SvNVX(sstr);
-       SvMAGIC(dstr)   = mg_dup(SvMAGIC(sstr), param);
-       SvSTASH(dstr)   = hv_dup_inc(SvSTASH(sstr), param);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
+       SvNV_set(dstr, SvNVX(sstr));
+       SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
+       SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        IoIFP(dstr)     = fp_dup(IoIFP(sstr), IoTYPE(sstr), param);
        if (IoOFP(sstr) == IoIFP(sstr))
@@ -10895,12 +10927,12 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        break;
     case SVt_PVAV:
        SvANY(dstr)     = new_XPVAV();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
-       SvNVX(dstr)     = SvNVX(sstr);
-       SvMAGIC(dstr)   = mg_dup(SvMAGIC(sstr), param);
-       SvSTASH(dstr)   = hv_dup_inc(SvSTASH(sstr), param);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
+       SvNV_set(dstr, SvNVX(sstr));
+       SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
+       SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        AvARYLEN((AV*)dstr) = sv_dup_inc(AvARYLEN((AV*)sstr), param);
        AvFLAGS((AV*)dstr) = AvFLAGS((AV*)sstr);
        if (AvARRAY((AV*)sstr)) {
@@ -10910,7 +10942,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
            src_ary = AvARRAY((AV*)sstr);
            Newz(0, dst_ary, AvMAX((AV*)sstr)+1, SV*);
            ptr_table_store(PL_ptr_table, src_ary, dst_ary);
-           SvPVX(dstr) = (char*)dst_ary;
+           SvPV_set(dstr, (char*)dst_ary);
            AvALLOC((AV*)dstr) = dst_ary;
            if (AvREAL((AV*)sstr)) {
                while (items-- > 0)
@@ -10926,18 +10958,18 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
            }
        }
        else {
-           SvPVX(dstr)         = Nullch;
+           SvPV_set(dstr, Nullch);
            AvALLOC((AV*)dstr)  = (SV**)NULL;
        }
        break;
     case SVt_PVHV:
        SvANY(dstr)     = new_XPVHV();
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
-       SvNVX(dstr)     = SvNVX(sstr);
-       SvMAGIC(dstr)   = mg_dup(SvMAGIC(sstr), param);
-       SvSTASH(dstr)   = hv_dup_inc(SvSTASH(sstr), param);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
+       SvNV_set(dstr, SvNVX(sstr));
+       SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
+       SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        HvRITER((HV*)dstr)      = HvRITER((HV*)sstr);
        if (HvARRAY((HV*)sstr)) {
            STRLEN i = 0;
@@ -10955,7 +10987,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
                                     (bool)!!HvSHAREKEYS(sstr), param);
        }
        else {
-           SvPVX(dstr)         = Nullch;
+           SvPV_set(dstr, Nullch);
            HvEITER((HV*)dstr)  = (HE*)NULL;
        }
        HvPMROOT((HV*)dstr)     = HvPMROOT((HV*)sstr);          /* XXX */
@@ -10972,12 +11004,12 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
     case SVt_PVCV:
        SvANY(dstr)     = new_XPVCV();
         dup_pvcv:
-       SvCUR(dstr)     = SvCUR(sstr);
-       SvLEN(dstr)     = SvLEN(sstr);
-       SvIVX(dstr)     = SvIVX(sstr);
-       SvNVX(dstr)     = SvNVX(sstr);
-       SvMAGIC(dstr)   = mg_dup(SvMAGIC(sstr), param);
-       SvSTASH(dstr)   = hv_dup_inc(SvSTASH(sstr), param);
+       SvCUR_set(dstr, SvCUR(sstr));
+       SvLEN_set(dstr, SvLEN(sstr));
+       SvIV_set(dstr, SvIVX(sstr));
+       SvNV_set(dstr, SvNVX(sstr));
+       SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
+       SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        CvSTASH(dstr)   = hv_dup(CvSTASH(sstr), param); /* NOTE: not refcounted */
        CvSTART(dstr)   = CvSTART(sstr);
@@ -10989,7 +11021,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        if (CvCONST(sstr)) {
            CvXSUBANY(dstr).any_ptr = GvUNIQUE(CvGV(sstr)) ?
                 SvREFCNT_inc(CvXSUBANY(sstr).any_ptr) :
-                sv_dup_inc(CvXSUBANY(sstr).any_ptr, param);
+                sv_dup_inc((SV *)CvXSUBANY(sstr).any_ptr, 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 */
@@ -11458,6 +11490,40 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
     return nss;
 }
 
+
+/* if sv is a stash, call $class->CLONE_SKIP(), and set the SVphv_CLONEABLE
+ * flag to the result. This is done for each stash before cloning starts,
+ * so we know which stashes want their objects cloned */
+
+static void
+do_mark_cloneable_stash(pTHX_ SV *sv)
+{
+    if (HvNAME((HV*)sv)) {
+       GV* cloner = gv_fetchmethod_autoload((HV*)sv, "CLONE_SKIP", 0);
+       SvFLAGS(sv) |= SVphv_CLONEABLE; /* clone objects by default */
+       if (cloner && GvCV(cloner)) {
+           dSP;
+           UV status;
+
+           ENTER;
+           SAVETMPS;
+           PUSHMARK(SP);
+           XPUSHs(sv_2mortal(newSVpv(HvNAME((HV*)sv), 0)));
+           PUTBACK;
+           call_sv((SV*)GvCV(cloner), G_SCALAR);
+           SPAGAIN;
+           status = POPu;
+           PUTBACK;
+           FREETMPS;
+           LEAVE;
+           if (status)
+               SvFLAGS(sv) &= ~SVphv_CLONEABLE;
+       }
+    }
+}
+
+
+
 /*
 =for apidoc perl_clone
 
@@ -11502,6 +11568,7 @@ perl_clone_host(PerlInterpreter* proto_perl, UV flags);
 PerlInterpreter *
 perl_clone(PerlInterpreter *proto_perl, UV flags)
 {
+   dVAR;
 #ifdef PERL_IMPLICIT_SYS
 
    /* perlhost.h so we need to call into it
@@ -11539,10 +11606,14 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     CLONE_PARAMS* param = &clone_params;
 
     PerlInterpreter *my_perl = (PerlInterpreter*)(*ipM->pMalloc)(ipM, sizeof(PerlInterpreter));
+    /* for each stash, determine whether its objects should be cloned */
+    S_visit(proto_perl, do_mark_cloneable_stash, SVt_PVHV, SVTYPEMASK);
     PERL_SET_THX(my_perl);
 
 #  ifdef DEBUGGING
     Poison(my_perl, 1, PerlInterpreter);
+    PL_op = Nullop;
+    PL_curcop = (COP *)Nullop;
     PL_markstack = 0;
     PL_scopestack = 0;
     PL_savestack = 0;
@@ -11569,12 +11640,14 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     CLONE_PARAMS clone_params;
     CLONE_PARAMS* param = &clone_params;
     PerlInterpreter *my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter));
+    /* for each stash, determine whether its objects should be cloned */
+    S_visit(proto_perl, do_mark_cloneable_stash, SVt_PVHV, SVTYPEMASK);
     PERL_SET_THX(my_perl);
 
-
-
 #    ifdef DEBUGGING
     Poison(my_perl, 1, PerlInterpreter);
+    PL_op = Nullop;
+    PL_curcop = (COP *)Nullop;
     PL_markstack = 0;
     PL_scopestack = 0;
     PL_savestack = 0;
@@ -11616,6 +11689,10 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_xpvbm_root      = NULL;
     PL_he_arenaroot    = NULL;
     PL_he_root         = NULL;
+#if defined(USE_ITHREADS)
+    PL_pte_arenaroot   = NULL;
+    PL_pte_root                = NULL;
+#endif
     PL_nice_chunk      = NULL;
     PL_nice_chunk_size = 0;
     PL_sv_count                = 0;
@@ -11646,22 +11723,22 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     SvREFCNT(&PL_sv_no)                = (~(U32)0)/2;
     SvFLAGS(&PL_sv_no)         = SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
                                  |SVp_POK|SVf_POK|SVf_READONLY|SVt_PVNV;
-    SvPVX(&PL_sv_no)           = SAVEPVN(PL_No, 0);
-    SvCUR(&PL_sv_no)           = 0;
-    SvLEN(&PL_sv_no)           = 1;
-    SvIVX(&PL_sv_no)           = 0;
-    SvNVX(&PL_sv_no)           = 0;
+    SvPV_set(&PL_sv_no, SAVEPVN(PL_No, 0));
+    SvCUR_set(&PL_sv_no, 0);
+    SvLEN_set(&PL_sv_no, 1);
+    SvIV_set(&PL_sv_no, 0);
+    SvNV_set(&PL_sv_no, 0);
     ptr_table_store(PL_ptr_table, &proto_perl->Isv_no, &PL_sv_no);
 
     SvANY(&PL_sv_yes)          = new_XPVNV();
     SvREFCNT(&PL_sv_yes)       = (~(U32)0)/2;
     SvFLAGS(&PL_sv_yes)                = SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
                                  |SVp_POK|SVf_POK|SVf_READONLY|SVt_PVNV;
-    SvPVX(&PL_sv_yes)          = SAVEPVN(PL_Yes, 1);
-    SvCUR(&PL_sv_yes)          = 1;
-    SvLEN(&PL_sv_yes)          = 2;
-    SvIVX(&PL_sv_yes)          = 1;
-    SvNVX(&PL_sv_yes)          = 1;
+    SvPV_set(&PL_sv_yes, SAVEPVN(PL_Yes, 1));
+    SvCUR_set(&PL_sv_yes, 1);
+    SvLEN_set(&PL_sv_yes, 2);
+    SvIV_set(&PL_sv_yes, 1);
+    SvNV_set(&PL_sv_yes, 1);
     ptr_table_store(PL_ptr_table, &proto_perl->Isv_yes, &PL_sv_yes);
 
     /* create (a non-shared!) shared string table */
@@ -12278,7 +12355,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
            ENTER;
            SAVETMPS;
            PUSHMARK(SP);
-           XPUSHs(sv_2mortal(newSVpv(HvNAME(stash), 0)));
+           XPUSHs(sv_2mortal(newSVpv(HvNAME(stash), 0)));
            PUTBACK;
            call_sv((SV*)GvCV(cloner), G_DISCARD);
            FREETMPS;
@@ -12314,6 +12391,7 @@ The PV of the sv is returned.
 char *
 Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding)
 {
+    dVAR;
     if (SvPOK(sv) && !SvUTF8(sv) && !IN_BYTES && SvROK(encoding)) {
        SV *uni;
        STRLEN len;
@@ -12375,6 +12453,7 @@ bool
 Perl_sv_cat_decode(pTHX_ SV *dsv, SV *encoding,
                   SV *ssv, int *offset, char *tstr, int tlen)
 {
+    dVAR;
     bool ret = FALSE;
     if (SvPOK(ssv) && SvPOK(dsv) && SvROK(encoding) && offset) {
        SV *offsv;
@@ -12403,3 +12482,12 @@ Perl_sv_cat_decode(pTHX_ SV *dsv, SV *encoding,
     return ret;
 }
 
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set ts=8 sts=4 sw=4 noet:
+ */