Random consting
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index b0571d8..aa07053 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -534,7 +534,7 @@ Perl_sv_free_arenas(pTHX)
            svanext = (SV*) SvANY(svanext);
 
        if (!SvFAKE(sva))
-           Safefree((void *)sva);
+           Safefree(sva);
     }
 
     for (arena = PL_xnv_arenaroot; arena; arena = arenanext) {
@@ -758,19 +758,22 @@ S_varname(pTHX_ GV *gv, const char *gvtype, PADOFFSET targ,
     else {
        U32 u;
        CV *cv = find_runcv(&u);
+       STRLEN len;
+       const char *str;
        if (!cv || !CvPADLIST(cv))
            return Nullsv;;
        av = (AV*)(*av_fetch(CvPADLIST(cv), 0, FALSE));
        sv = *av_fetch(av, targ, FALSE);
        /* SvLEN in a pad name is not to be trusted */
-       sv_setpv(name, SvPV_nolen(sv));
+       str = SvPV(sv,len);
+       sv_setpvn(name, str, len);
     }
 
     if (subscript_type == FUV_SUBSCRIPT_HASH) {
        *SvPVX(name) = '$';
        sv = NEWSV(0,0);
        Perl_sv_catpvf(aTHX_ name, "{%s}",
-           pv_display(sv,SvPVX(keyname), SvCUR(keyname), 0, 32));
+           pv_display(sv,SvPVX_const(keyname), SvCUR(keyname), 0, 32));
        SvREFCNT_dec(sv);
     }
     else if (subscript_type == FUV_SUBSCRIPT_ARRAY) {
@@ -1028,7 +1031,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                                 : DEFSV))
            {
                sv = sv_newmortal();
-               sv_setpv(sv, "$_");
+               sv_setpvn(sv, "$_", 2);
                return sv;
            }
        }
@@ -1173,19 +1176,19 @@ S_more_xpv(pTHX)
 STATIC void
 S_more_xpviv(pTHX)
 {
-    XPVIV* xpviv;
-    XPVIV* xpvivend;
-    New(714, xpviv, PERL_ARENA_SIZE/sizeof(XPVIV), XPVIV);
-    *((XPVIV**)xpviv) = PL_xpviv_arenaroot;
+    xpviv_allocated* xpviv;
+    xpviv_allocated* xpvivend;
+    New(713, xpviv, PERL_ARENA_SIZE/sizeof(xpviv_allocated), xpviv_allocated);
+    *((xpviv_allocated**)xpviv) = PL_xpviv_arenaroot;
     PL_xpviv_arenaroot = xpviv;
 
-    xpvivend = &xpviv[PERL_ARENA_SIZE / sizeof(XPVIV) - 1];
+    xpvivend = &xpviv[PERL_ARENA_SIZE / sizeof(xpviv_allocated) - 1];
     PL_xpviv_root = ++xpviv;
     while (xpviv < xpvivend) {
-       *((XPVIV**)xpviv) = xpviv + 1;
+       *((xpviv_allocated**)xpviv) = xpviv + 1;
        xpviv++;
     }
-    *((XPVIV**)xpviv) = 0;
+    *((xpviv_allocated**)xpviv) = 0;
 }
 
 /* allocate another arena's worth of struct xpvnv */
@@ -1417,14 +1420,20 @@ S_del_xpv(pTHX_ XPV *p)
 STATIC XPVIV*
 S_new_xpviv(pTHX)
 {
-    XPVIV* xpviv;
+    xpviv_allocated* xpviv;
     LOCK_SV_MUTEX;
     if (!PL_xpviv_root)
        S_more_xpviv(aTHX);
     xpviv = PL_xpviv_root;
-    PL_xpviv_root = *(XPVIV**)xpviv;
+    PL_xpviv_root = *(xpviv_allocated**)xpviv;
     UNLOCK_SV_MUTEX;
-    return xpviv;
+    /* If xpviv_allocated is the same structure as XPVIV then the two OFFSETs
+       sum to zero, and the pointer is unchanged. If the allocated structure
+       is smaller (no initial IV actually allocated) then the net effect is
+       to subtract the size of the IV from the pointer, to return a new pointer
+       as if an initial IV were actually allocated.  */
+    return (XPVIV*)((char*)xpviv - STRUCT_OFFSET(XPVIV, xpv_cur)
+                 + STRUCT_OFFSET(xpviv_allocated, xpv_cur));
 }
 
 /* return a struct xpviv to the free list */
@@ -1432,9 +1441,12 @@ S_new_xpviv(pTHX)
 STATIC void
 S_del_xpviv(pTHX_ XPVIV *p)
 {
+    xpviv_allocated* xpviv
+       = (xpviv_allocated*)((char*)(p) + STRUCT_OFFSET(XPVIV, xpv_cur)
+                          - STRUCT_OFFSET(xpviv_allocated, xpv_cur));
     LOCK_SV_MUTEX;
-    *(XPVIV**)p = PL_xpviv_root;
-    PL_xpviv_root = p;
+    *(xpviv_allocated**)xpviv = PL_xpviv_root;
+    PL_xpviv_root = xpviv;
     UNLOCK_SV_MUTEX;
 }
 
@@ -1845,7 +1857,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
     case SVt_NULL:
        Perl_croak(aTHX_ "Can't upgrade to undef");
     case SVt_IV:
-       SvANY(sv) = (XPVIV*)((char*)&(sv->sv_u.sv_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
+       SvANY(sv) = (XPVIV*)((char*)&(sv->sv_u.svu_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
        SvIV_set(sv, iv);
        break;
     case SVt_NV:
@@ -1853,12 +1865,11 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        SvNV_set(sv, nv);
        break;
     case SVt_RV:
-       SvANY(sv) = &sv->sv_u.sv_rv;
+       SvANY(sv) = &sv->sv_u.svu_rv;
        SvRV_set(sv, (SV*)pv);
        break;
     case SVt_PVHV:
        SvANY(sv) = new_XPVHV();
-       ((XPVHV*) SvANY(sv))->xhv_aux = 0;
        HvFILL(sv)      = 0;
        HvMAX(sv)       = 0;
        HvTOTALKEYS(sv) = 0;
@@ -1870,7 +1881,6 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
            AvMAX(sv)   = -1;
            AvFILLp(sv) = -1;
            AvALLOC(sv) = 0;
-           AvARYLEN(sv)= 0;
            AvREAL_only(sv);
        }
        /* to here.  */
@@ -1975,8 +1985,10 @@ int
 Perl_sv_backoff(pTHX_ register SV *sv)
 {
     assert(SvOOK(sv));
+    assert(SvTYPE(sv) != SVt_PVHV);
+    assert(SvTYPE(sv) != SVt_PVAV);
     if (SvIVX(sv)) {
-       char *s = SvPVX(sv);
+       const char *s = SvPVX_const(sv);
        SvLEN_set(sv, SvLEN(sv) + SvIVX(sv));
        SvPV_set(sv, SvPVX(sv) - SvIVX(sv));
        SvIV_set(sv, 0);
@@ -2028,6 +2040,7 @@ Perl_sv_grow(pTHX_ register SV *sv, register STRLEN newlen)
        s = SvPVX(sv);
 
     if (newlen > SvLEN(sv)) {          /* need more room? */
+       newlen = PERL_STRLEN_ROUNDUP(newlen);
        if (SvLEN(sv) && s) {
 #ifdef MYMALLOC
            const STRLEN l = malloced_size((void*)SvPVX(sv));
@@ -2036,12 +2049,12 @@ Perl_sv_grow(pTHX_ register SV *sv, register STRLEN newlen)
                return s;
            } else
 #endif
-           Renew(s,newlen,char);
+           s = saferealloc(s, newlen);
        }
        else {
-           New(703, s, newlen, char);
-           if (SvPVX(sv) && SvCUR(sv)) {
-               Move(SvPVX(sv), s, (newlen < SvCUR(sv)) ? newlen : SvCUR(sv), char);
+           s = safemalloc(newlen);
+           if (SvPVX_const(sv) && SvCUR(sv)) {
+               Move(SvPVX_const(sv), s, (newlen < SvCUR(sv)) ? newlen : SvCUR(sv), char);
            }
        }
        SvPV_set(sv, s);
@@ -2305,7 +2318,7 @@ Perl_looks_like_number(pTHX_ SV *sv)
     STRLEN len;
 
     if (SvPOK(sv)) {
-       sbegin = SvPVX(sv);
+       sbegin = SvPVX_const(sv);
        len = SvCUR(sv);
     }
     else if (SvPOKp(sv))
@@ -2402,7 +2415,7 @@ Perl_looks_like_number(pTHX_ SV *sv)
 STATIC int
 S_sv_2iuv_non_preserve(pTHX_ register SV *sv, I32 numtype)
 {
-    DEBUG_c(PerlIO_printf(Perl_debug_log,"sv_2iuv_non '%s', IV=0x%"UVxf" NV=%"NVgf" inttype=%"UVXf"\n", SvPVX(sv), SvIVX(sv), SvNVX(sv), (UV)numtype));
+    DEBUG_c(PerlIO_printf(Perl_debug_log,"sv_2iuv_non '%s', IV=0x%"UVxf" NV=%"NVgf" inttype=%"UVXf"\n", SvPVX_const(sv), SvIVX(sv), SvNVX(sv), (UV)numtype));
     if (SvNVX(sv) < (NV)IV_MIN) {
        (void)SvIOKp_on(sv);
        (void)SvNOK_on(sv);
@@ -2659,7 +2672,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). */
-           SvNV_set(sv, Atof(SvPVX(sv)));
+           SvNV_set(sv, Atof(SvPVX_const(sv)));
 
            if (! numtype && ckWARN(WARN_NUMERIC))
                not_a_number(sv);
@@ -2958,7 +2971,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. */
-           SvNV_set(sv, Atof(SvPVX(sv)));
+           SvNV_set(sv, Atof(SvPVX_const(sv)));
 
             if (! numtype && ckWARN(WARN_NUMERIC))
                    not_a_number(sv);
@@ -3069,7 +3082,7 @@ Perl_sv_2nv(pTHX_ register SV *sv)
            if (ckWARN(WARN_NUMERIC) && !SvIOKp(sv) &&
                !grok_number(SvPVX_const(sv), SvCUR(sv), NULL))
                not_a_number(sv);
-           return Atof(SvPVX(sv));
+           return Atof(SvPVX_const(sv));
        }
        if (SvIOKp(sv)) {
            if (SvIsUV(sv))
@@ -3145,7 +3158,7 @@ Perl_sv_2nv(pTHX_ register SV *sv)
     }
     else if (SvPOKp(sv) && SvLEN(sv)) {
        UV value;
-       const int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
+       const int numtype = grok_number(SvPVX_const(sv), SvCUR(sv), &value);
        if (ckWARN(WARN_NUMERIC) && !SvIOKp(sv) && !numtype)
            not_a_number(sv);
 #ifdef NV_PRESERVES_UV
@@ -3154,10 +3167,10 @@ Perl_sv_2nv(pTHX_ register SV *sv)
            /* It's definitely an integer */
            SvNV_set(sv, (numtype & IS_NUMBER_NEG) ? -(NV)value : (NV)value);
        } else
-           SvNV_set(sv, Atof(SvPVX(sv)));
+           SvNV_set(sv, Atof(SvPVX_const(sv)));
        SvNOK_on(sv);
 #else
-       SvNV_set(sv, Atof(SvPVX(sv)));
+       SvNV_set(sv, Atof(SvPVX_const(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. */
@@ -3262,7 +3275,7 @@ STATIC IV
 S_asIV(pTHX_ SV *sv)
 {
     UV value;
-    int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
+    int numtype = grok_number(SvPVX_const(sv), SvCUR(sv), &value);
 
     if ((numtype & (IS_NUMBER_IN_UV | IS_NUMBER_NOT_INT))
        == IS_NUMBER_IN_UV) {
@@ -3279,7 +3292,7 @@ S_asIV(pTHX_ SV *sv)
        if (ckWARN(WARN_NUMERIC))
            not_a_number(sv);
     }
-    return I_V(Atof(SvPVX(sv)));
+    return I_V(Atof(SvPVX_const(sv)));
 }
 
 /* asUV(): extract an unsigned integer from the string value of an SV
@@ -3301,7 +3314,7 @@ S_asUV(pTHX_ SV *sv)
        if (ckWARN(WARN_NUMERIC))
            not_a_number(sv);
     }
-    return U_V(Atof(SvPVX(sv)));
+    return U_V(Atof(SvPVX_const(sv)));
 }
 
 /*
@@ -3623,11 +3636,11 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
            sv_upgrade(sv, SVt_PV);
        return (char *)"";
     }
-    *lp = s - SvPVX(sv);
+    *lp = s - SvPVX_const(sv);
     SvCUR_set(sv, *lp);
     SvPOK_on(sv);
     DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2pv(%s)\n",
-                         PTR2UV(sv),SvPVX(sv)));
+                         PTR2UV(sv),SvPVX_const(sv)));
     return SvPVX(sv);
 
   tokensave:
@@ -3648,7 +3661,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
 
        if (tsv) {
            sv_2mortal(tsv);
-           t = SvPVX(tsv);
+           t = SvPVX_const(tsv);
            len = SvCUR(tsv);
        }
        else {
@@ -3797,9 +3810,9 @@ Perl_sv_2bool(pTHX_ register SV *sv)
     if (SvPOKp(sv)) {
        register XPV* Xpvtmp;
        if ((Xpvtmp = (XPV*)SvANY(sv)) &&
-               (*sv->sv_u.sv_pv > '0' ||
+               (*sv->sv_u.svu_pv > '0' ||
                Xpvtmp->xpv_cur > 1 ||
-               (Xpvtmp->xpv_cur && *sv->sv_u.sv_pv != '0')))
+               (Xpvtmp->xpv_cur && *sv->sv_u.svu_pv != '0')))
            return 1;
        else
            return 0;
@@ -4387,7 +4400,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                    SvTAINT(dstr);
                return;
            }
-           if (SvPVX(dstr)) {
+           if (SvPVX_const(dstr)) {
                SvPV_free(dstr);
                SvLEN_set(dstr, 0);
                 SvCUR_set(dstr, 0);
@@ -4421,8 +4434,8 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        /*
         * Check to see if we can just swipe the string.  If so, it's a
         * possible small lose on short strings, but a big win on long ones.
-        * It might even be a win on short strings if SvPVX(dstr)
-        * has to be allocated and SvPVX(sstr) has to be freed.
+        * It might even be a win on short strings if SvPVX_const(dstr)
+        * has to be allocated and SvPVX_const(sstr) has to be freed.
         */
 
        /* Whichever path we take through the next code, we want this true,
@@ -4453,7 +4466,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                Have to copy the string.  */
            STRLEN len = SvCUR(sstr);
             SvGROW(dstr, len + 1);     /* inlined from sv_setpvn */
-            Move(SvPVX(sstr),SvPVX(dstr),len,char);
+            Move(SvPVX_const(sstr),SvPVX(dstr),len,char);
             SvCUR_set(dstr, len);
             *SvEND(dstr) = '\0';
         } else {
@@ -4485,13 +4498,13 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
             }
 #endif
             /* Initial code is common.  */
-           if (SvPVX(dstr)) {          /* we know that dtype >= SVt_PV */
+           if (SvPVX_const(dstr)) {            /* we know that dtype >= SVt_PV */
                if (SvOOK(dstr)) {
                    SvFLAGS(dstr) &= ~SVf_OOK;
-                   Safefree(SvPVX(dstr) - SvIVX(dstr));
+                   Safefree(SvPVX_const(dstr) - SvIVX(dstr));
                }
                else if (SvLEN(dstr))
-                   Safefree(SvPVX(dstr));
+                   Safefree(SvPVX_const(dstr));
            }
 
 #ifdef PERL_COPY_ON_WRITE
@@ -4512,7 +4525,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                     DEBUG_C(PerlIO_printf(Perl_debug_log,
                                           "Copy on write: Sharing hash\n"));
                     SvPV_set(dstr,
-                             sharepvn(SvPVX(sstr),
+                             sharepvn(SvPVX_const(sstr),
                                       (sflags & SVf_UTF8?-cur:cur), hash));
                     SvUV_set(dstr, hash);
                 }
@@ -4635,8 +4648,8 @@ Perl_sv_setsv_cow(pTHX_ SV *dstr, SV *sstr)
     if (dstr) {
        if (SvTHINKFIRST(dstr))
            sv_force_normal_flags(dstr, SV_COW_DROP_PV);
-       else if (SvPVX(dstr))
-           Safefree(SvPVX(dstr));
+       else if (SvPVX_const(dstr))
+           Safefree(SvPVX_const(dstr));
     }
     else
        new_SV(dstr);
@@ -4657,7 +4670,7 @@ Perl_sv_setsv_cow(pTHX_ SV *dstr, SV *sstr)
            DEBUG_C(PerlIO_printf(Perl_debug_log,
                                  "Fast copy on write: Sharing hash\n"));
            SvUV_set(dstr, hash);
-           new_pv = sharepvn(SvPVX(sstr), (SvUTF8(sstr)?-cur:cur), hash);
+           new_pv = sharepvn(SvPVX_const(sstr), (SvUTF8(sstr)?-cur:cur), hash);
            goto common_exit;
        }
        SV_COW_NEXT_SV_SET(dstr, SV_COW_NEXT_SV(sstr));
@@ -4800,18 +4813,21 @@ See C<sv_usepvn_mg>.
 void
 Perl_sv_usepvn(pTHX_ register SV *sv, register char *ptr, register STRLEN len)
 {
+    STRLEN allocate;
     SV_CHECK_THINKFIRST_COW_DROP(sv);
     (void)SvUPGRADE(sv, SVt_PV);
     if (!ptr) {
        (void)SvOK_off(sv);
        return;
     }
-    if (SvPVX(sv))
+    if (SvPVX_const(sv))
        SvPV_free(sv);
-    Renew(ptr, len+1, char);
+
+    allocate = PERL_STRLEN_ROUNDUP(len + 1);
+    ptr = saferealloc (ptr, allocate);
     SvPV_set(sv, ptr);
     SvCUR_set(sv, len);
-    SvLEN_set(sv, len+1);
+    SvLEN_set(sv, allocate);
     *SvEND(sv) = '\0';
     (void)SvPOK_only_UTF8(sv);         /* validate pointer */
     SvTAINT(sv);
@@ -4839,7 +4855,7 @@ Perl_sv_usepvn_mg(pTHX_ register SV *sv, register char *ptr, register STRLEN len
    (which it can do by means other than releasing copy-on-write Svs)
    or by changing the other copy-on-write SVs in the loop.  */
 STATIC void
-S_sv_release_COW(pTHX_ register SV *sv, char *pvx, STRLEN cur, STRLEN len,
+S_sv_release_COW(pTHX_ register SV *sv, const char *pvx, STRLEN cur, STRLEN len,
                  U32 hash, SV *after)
 {
     if (len) { /* this SV was SvIsCOW_normal(sv) */
@@ -4861,7 +4877,7 @@ S_sv_release_COW(pTHX_ register SV *sv, char *pvx, STRLEN cur, STRLEN len,
                  /* don't loop forever if the structure is bust, and we have
                     a pointer into a closed loop.  */
                 assert (current != after);
-                assert (SvPVX(current) == pvx);
+                assert (SvPVX_const(current) == pvx);
             }
             /* Make the SV before us point to the SV after us.  */
             SV_COW_NEXT_SV_SET(current, after);
@@ -4903,7 +4919,7 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
     if (SvREADONLY(sv)) {
         /* At this point I believe I should acquire a global SV mutex.  */
        if (SvFAKE(sv)) {
-            char *pvx = SvPVX(sv);
+            const char *pvx = SvPVX_const(sv);
             STRLEN len = SvLEN(sv);
             STRLEN cur = SvCUR(sv);
             U32 hash = SvUVX(sv);
@@ -4940,8 +4956,8 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
 #else
     if (SvREADONLY(sv)) {
        if (SvFAKE(sv)) {
-           char *pvx = SvPVX(sv);
-           int is_utf8 = SvUTF8(sv);
+           char *pvx = SvPVX_const(sv);
+           const int is_utf8 = SvUTF8(sv);
            STRLEN len = SvCUR(sv);
             U32 hash   = SvUVX(sv);
            SvFAKE_off(sv);
@@ -4949,7 +4965,7 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
             SvPV_set(sv, (char*)0);
             SvLEN_set(sv, 0);
            SvGROW(sv, len + 1);
-           Move(pvx,SvPVX(sv),len,char);
+           Move(pvx,SvPVX_const(sv),len,char);
            *SvEND(sv) = '\0';
            unsharepvn(pvx, is_utf8 ? -(I32)len : len, hash);
        }
@@ -4986,7 +5002,7 @@ Efficient removal of characters from the beginning of the string buffer.
 SvPOK(sv) must be true and the C<ptr> must be a pointer to somewhere inside
 the string buffer.  The C<ptr> becomes the first character of the adjusted
 string. Uses the "OOK hack".
-Beware: after this function returns, C<ptr> and SvPVX(sv) may no longer
+Beware: after this function returns, C<ptr> and SvPVX_const(sv) may no longer
 refer to the same chunk of data.
 
 =cut
@@ -4998,17 +5014,17 @@ Perl_sv_chop(pTHX_ register SV *sv, register const char *ptr)
     register STRLEN delta;
     if (!ptr || !SvPOKp(sv))
        return;
-    delta = ptr - SvPVX(sv);
+    delta = ptr - SvPVX_const(sv);
     SV_CHECK_THINKFIRST(sv);
     if (SvTYPE(sv) < SVt_PVIV)
        sv_upgrade(sv,SVt_PVIV);
 
     if (!SvOOK(sv)) {
        if (!SvLEN(sv)) { /* make copy of shared string */
-           const char *pvx = SvPVX(sv);
+           const char *pvx = SvPVX_const(sv);
            STRLEN len = SvCUR(sv);
            SvGROW(sv, len + 1);
-           Move(pvx,SvPVX(sv),len,char);
+           Move(pvx,SvPVX_const(sv),len,char);
            *SvEND(sv) = '\0';
        }
        SvIV_set(sv, 0);
@@ -5062,7 +5078,7 @@ Perl_sv_catpvn_flags(pTHX_ register SV *dsv, register const char *sstr, register
 
     SvGROW(dsv, dlen + slen + 1);
     if (sstr == dstr)
-       sstr = SvPVX(dsv);
+       sstr = SvPVX_const(dsv);
     Move(sstr, SvPVX(dsv) + dlen, slen, char);
     SvCUR_set(dsv, SvCUR(dsv) + slen);
     *SvEND(dsv) = '\0';
@@ -5126,7 +5142,7 @@ Perl_sv_catsv_flags(pTHX_ SV *dsv, register SV *ssv, I32 flags)
            dsv->sv_flags doesn't have that bit set.
                Andy Dougherty  12 Oct 2001
        */
-       I32 sutf8 = DO_UTF8(ssv);
+       const I32 sutf8 = DO_UTF8(ssv);
        I32 dutf8;
 
        if (SvGMAGICAL(dsv) && (flags & SV_GMAGIC))
@@ -5185,7 +5201,7 @@ Perl_sv_catpv(pTHX_ register SV *sv, register const char *ptr)
     len = strlen(ptr);
     SvGROW(sv, tlen + len + 1);
     if (ptr == junk)
-       ptr = SvPVX(sv);
+       ptr = SvPVX_const(sv);
     Move(ptr,SvPVX(sv)+tlen,len+1,char);
     SvCUR_set(sv, SvCUR(sv) + len);
     (void)SvPOK_only_UTF8(sv);         /* validate pointer */
@@ -5445,6 +5461,7 @@ Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 nam
     case PERL_MAGIC_vec:
        vtable = &PL_vtbl_vec;
        break;
+    case PERL_MAGIC_arylen_p:
     case PERL_MAGIC_rhash:
     case PERL_MAGIC_symtab:
     case PERL_MAGIC_vstring:
@@ -5648,7 +5665,7 @@ Perl_sv_insert(pTHX_ SV *bigstr, STRLEN offset, STRLEN len, const char *little,
     (void)SvPOK_only_UTF8(bigstr);
     if (offset + len > curlen) {
        SvGROW(bigstr, offset+len+1);
-       Zero(SvPVX(bigstr)+curlen, offset+len-curlen, char);
+       Zero(SvPVX_const(bigstr)+curlen, offset+len-curlen, char);
        SvCUR_set(bigstr, offset+len);
     }
 
@@ -5760,9 +5777,9 @@ Perl_sv_replace(pTHX_ register SV *sv, register SV *nsv)
        it would be unclear.  */
     if(SvTYPE(sv) == SVt_IV)
        SvANY(sv)
-           = (XPVIV*)((char*)&(sv->sv_u.sv_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
+           = (XPVIV*)((char*)&(sv->sv_u.svu_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
     else if (SvTYPE(sv) == SVt_RV) {
-       SvANY(sv) = &sv->sv_u.sv_rv;
+       SvANY(sv) = &sv->sv_u.svu_rv;
     }
        
 
@@ -5775,7 +5792,7 @@ Perl_sv_replace(pTHX_ register SV *sv, register SV *nsv)
        while ((next = SV_COW_NEXT_SV(current)) != nsv) {
            assert(next);
            current = next;
-           assert(SvPVX(current) == SvPVX(nsv));
+           assert(SvPVX_const(current) == SvPVX_const(nsv));
        }
        /* Make the SV before us point to the SV after us.  */
        if (DEBUG_C_TEST) {
@@ -5819,11 +5836,8 @@ Perl_sv_clear(pTHX_ register SV *sv)
     if (SvOBJECT(sv)) {
        if (PL_defstash) {              /* Still have a symbol table? */
            dSP;
-           CV* destructor;
-
-
-
            do {        
+               CV* destructor;
                stash = SvSTASH(sv);
                destructor = StashHANDLER(stash,DESTROY);
                if (destructor) {
@@ -5940,7 +5954,7 @@ Perl_sv_clear(pTHX_ register SV *sv)
                SvREFCNT_dec(SvRV(sv));
        }
 #ifdef PERL_COPY_ON_WRITE
-       else if (SvPVX(sv)) {
+       else if (SvPVX_const(sv)) {
             if (SvIsCOW(sv)) {
                 /* I believe I need to grab the global SV mutex here and
                    then recheck the COW status.  */
@@ -5948,19 +5962,19 @@ Perl_sv_clear(pTHX_ register SV *sv)
                     PerlIO_printf(Perl_debug_log, "Copy on write: clear\n");
                     sv_dump(sv);
                 }
-                sv_release_COW(sv, SvPVX(sv), SvCUR(sv), SvLEN(sv),
+                sv_release_COW(sv, SvPVX_const(sv), SvCUR(sv), SvLEN(sv),
                                  SvUVX(sv), SV_COW_NEXT_SV(sv));
                 /* And drop it here.  */
                 SvFAKE_off(sv);
             } else if (SvLEN(sv)) {
-                Safefree(SvPVX(sv));
+                Safefree(SvPVX_const(sv));
             }
        }
 #else
-       else if (SvPVX(sv) && SvLEN(sv))
-           Safefree(SvPVX(sv));
-       else if (SvPVX(sv) && SvREADONLY(sv) && SvFAKE(sv)) {
-           unsharepvn(SvPVX(sv),
+       else if (SvPVX_const(sv) && SvLEN(sv))
+           Safefree(SvPVX_const(sv));
+       else if (SvPVX_const(sv) && SvREADONLY(sv) && SvFAKE(sv)) {
+           unsharepvn(SvPVX_const(sv),
                       SvUTF8(sv) ? -(I32)SvCUR(sv) : SvCUR(sv),
                       SvUVX(sv));
            SvFAKE_off(sv);
@@ -6363,16 +6377,16 @@ void
 Perl_sv_pos_u2b(pTHX_ register SV *sv, I32* offsetp, I32* lenp)
 {
     U8 *start;
-    U8 *s;
     STRLEN len;
-    STRLEN *cache = 0;
-    STRLEN boffset = 0;
 
     if (!sv)
        return;
 
-    start = s = (U8*)SvPV(sv, len);
+    start = (U8*)SvPV(sv, len);
     if (len) {
+       STRLEN boffset = 0;
+       STRLEN *cache = 0;
+       U8 *s = start;
         I32 uoffset = *offsetp;
         U8 *send = s + len;
         MAGIC *mg = 0;
@@ -7029,7 +7043,7 @@ Perl_sv_gets(pTHX_ register SV *sv, register PerlIO *fp, I32 append)
     }
     else
        shortbuffered = 0;
-    bp = (STDCHAR*)SvPVX(sv) + append;  /* move these two too to registers */
+    bp = (STDCHAR*)SvPVX_const(sv) + append;  /* move these two too to registers */
     ptr = (STDCHAR*)PerlIO_get_ptr(fp);
     DEBUG_P(PerlIO_printf(Perl_debug_log,
        "Screamer: entering, ptr=%"UVuf", cnt=%ld\n",PTR2UV(ptr),(long)cnt));
@@ -7058,10 +7072,10 @@ Perl_sv_gets(pTHX_ register SV *sv, register PerlIO *fp, I32 append)
        if (shortbuffered) {            /* oh well, must extend */
            cnt = shortbuffered;
            shortbuffered = 0;
-           bpx = bp - (STDCHAR*)SvPVX(sv); /* box up before relocation */
+           bpx = bp - (STDCHAR*)SvPVX_const(sv); /* box up before relocation */
            SvCUR_set(sv, bpx);
            SvGROW(sv, SvLEN(sv) + append + cnt + 2);
-           bp = (STDCHAR*)SvPVX(sv) + bpx; /* unbox after relocation */
+           bp = (STDCHAR*)SvPVX_const(sv) + bpx; /* unbox after relocation */
            continue;
        }
 
@@ -7093,10 +7107,10 @@ Perl_sv_gets(pTHX_ register SV *sv, register PerlIO *fp, I32 append)
        if (i == EOF)                   /* all done for ever? */
            goto thats_really_all_folks;
 
-       bpx = bp - (STDCHAR*)SvPVX(sv); /* box up before relocation */
+       bpx = bp - (STDCHAR*)SvPVX_const(sv);   /* box up before relocation */
        SvCUR_set(sv, bpx);
        SvGROW(sv, bpx + cnt + 2);
-       bp = (STDCHAR*)SvPVX(sv) + bpx; /* unbox after relocation */
+       bp = (STDCHAR*)SvPVX_const(sv) + bpx;   /* unbox after relocation */
 
        *bp++ = (STDCHAR)i;             /* store character from PerlIO_getc */
 
@@ -7105,7 +7119,7 @@ Perl_sv_gets(pTHX_ register SV *sv, register PerlIO *fp, I32 append)
     }
 
 thats_all_folks:
-    if ((rslen > 1 && (STRLEN)(bp - (STDCHAR*)SvPVX(sv)) < rslen) ||
+    if ((rslen > 1 && (STRLEN)(bp - (STDCHAR*)SvPVX_const(sv)) < rslen) ||
          memNE((char*)bp - rslen, rsptr, rslen))
        goto screamer;                          /* go back to the fray */
 thats_really_all_folks:
@@ -7119,10 +7133,10 @@ thats_really_all_folks:
        PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
        PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0)));
     *bp = '\0';
-    SvCUR_set(sv, bp - (STDCHAR*)SvPVX(sv));   /* set length */
+    SvCUR_set(sv, bp - (STDCHAR*)SvPVX_const(sv));     /* set length */
     DEBUG_P(PerlIO_printf(Perl_debug_log,
        "Screamer: done, len=%ld, string=|%.*s|\n",
-       (long)SvCUR(sv),(int)SvCUR(sv),SvPVX(sv)));
+       (long)SvCUR(sv),(int)SvCUR(sv),SvPVX_const(sv)));
     }
    else
     {
@@ -7164,7 +7178,7 @@ screamer2:
        if (i != EOF &&                 /* joy */
            (!rslen ||
             SvCUR(sv) < rslen ||
-            memNE(SvPVX(sv) + SvCUR(sv) - rslen, rsptr, rslen)))
+            memNE(SvPVX_const(sv) + SvCUR(sv) - rslen, rsptr, rslen)))
        {
            append = -1;
            /*
@@ -7270,7 +7284,7 @@ Perl_sv_inc(pTHX_ register SV *sv)
        return;
     }
 
-    if (!(flags & SVp_POK) || !*SvPVX(sv)) {
+    if (!(flags & SVp_POK) || !*SvPVX_const(sv)) {
        if ((flags & SVTYPEMASK) < SVt_PVIV)
            sv_upgrade(sv, SVt_IV);
        (void)SvIOK_only(sv);
@@ -7309,18 +7323,18 @@ Perl_sv_inc(pTHX_ register SV *sv)
               Fall through. */
 #if defined(USE_LONG_DOUBLE)
            DEBUG_c(PerlIO_printf(Perl_debug_log,"sv_inc punt failed to convert '%s' to IOK or NOKp, UV=0x%"UVxf" NV=%"PERL_PRIgldbl"\n",
-                                 SvPVX(sv), SvIVX(sv), SvNVX(sv)));
+                                 SvPVX_const(sv), SvIVX(sv), SvNVX(sv)));
 #else
            DEBUG_c(PerlIO_printf(Perl_debug_log,"sv_inc punt failed to convert '%s' to IOK or NOKp, UV=0x%"UVxf" NV=%"NVgf"\n",
-                                 SvPVX(sv), SvIVX(sv), SvNVX(sv)));
+                                 SvPVX_const(sv), SvIVX(sv), SvNVX(sv)));
 #endif
        }
 #endif /* PERL_PRESERVE_IVUV */
-       sv_setnv(sv,Atof(SvPVX(sv)) + 1.0);
+       sv_setnv(sv,Atof(SvPVX_const(sv)) + 1.0);
        return;
     }
     d--;
-    while (d >= SvPVX(sv)) {
+    while (d >= SvPVX_const(sv)) {
        if (isDIGIT(*d)) {
            if (++*d <= '9')
                return;
@@ -7350,7 +7364,7 @@ Perl_sv_inc(pTHX_ register SV *sv)
     /* oh,oh, the number grew */
     SvGROW(sv, SvCUR(sv) + 2);
     SvCUR_set(sv, SvCUR(sv) + 1);
-    for (d = SvPVX(sv) + SvCUR(sv); d > SvPVX(sv); d--)
+    for (d = SvPVX(sv) + SvCUR(sv); d > SvPVX_const(sv); d--)
        *d = d[-1];
     if (isDIGIT(d[1]))
        *d = '1';
@@ -7457,15 +7471,15 @@ Perl_sv_dec(pTHX_ register SV *sv)
               Fall through. */
 #if defined(USE_LONG_DOUBLE)
            DEBUG_c(PerlIO_printf(Perl_debug_log,"sv_dec punt failed to convert '%s' to IOK or NOKp, UV=0x%"UVxf" NV=%"PERL_PRIgldbl"\n",
-                                 SvPVX(sv), SvIVX(sv), SvNVX(sv)));
+                                 SvPVX_const(sv), SvIVX(sv), SvNVX(sv)));
 #else
            DEBUG_c(PerlIO_printf(Perl_debug_log,"sv_dec punt failed to convert '%s' to IOK or NOKp, UV=0x%"UVxf" NV=%"NVgf"\n",
-                                 SvPVX(sv), SvIVX(sv), SvNVX(sv)));
+                                 SvPVX_const(sv), SvIVX(sv), SvNVX(sv)));
 #endif
        }
     }
 #endif /* PERL_PRESERVE_IVUV */
-    sv_setnv(sv,Atof(SvPVX(sv)) - 1.0);        /* punt */
+    sv_setnv(sv,Atof(SvPVX_const(sv)) - 1.0);  /* punt */
 }
 
 /*
@@ -7562,9 +7576,7 @@ Perl_newSVpv(pTHX_ const char *s, STRLEN len)
     register SV *sv;
 
     new_SV(sv);
-    if (!len)
-       len = strlen(s);
-    sv_setpvn(sv,s,len);
+    sv_setpvn(sv,s,len ? len : strlen(s));
     return sv;
 }
 
@@ -7592,12 +7604,12 @@ Perl_newSVpvn(pTHX_ const char *s, STRLEN len)
 /*
 =for apidoc newSVpvn_share
 
-Creates a new SV with its SvPVX pointing to a shared string in the string
+Creates a new SV with its SvPVX_const pointing to a shared string in the string
 table. If the string does not already exist in the table, it is created
 first.  Turns on READONLY and FAKE.  The string's hash is stored in the UV
 slot of the SV; if the C<hash> parameter is non-zero, that value is used;
 otherwise the hash is computed.  The idea here is that as the string table
-is used for shared hash keys these strings will have SvPVX == HeKEY and
+is used for shared hash keys these strings will have SvPVX_const == HeKEY and
 hash lookup will avoid string compare.
 
 =cut
@@ -7814,11 +7826,6 @@ void
 Perl_sv_reset(pTHX_ register const char *s, HV *stash)
 {
     dVAR;
-    register HE *entry;
-    register GV *gv;
-    register SV *sv;
-    register I32 i;
-    register I32 max;
     char todo[PERL_UCHAR_MAX+1];
 
     if (!stash)
@@ -7843,7 +7850,8 @@ Perl_sv_reset(pTHX_ register const char *s, HV *stash)
 
     Zero(todo, 256, char);
     while (*s) {
-       i = (unsigned char)*s;
+       I32 max;
+       I32 i = (unsigned char)*s;
        if (s[1] == '-') {
            s += 2;
        }
@@ -7852,10 +7860,14 @@ Perl_sv_reset(pTHX_ register const char *s, HV *stash)
            todo[i] = 1;
        }
        for (i = 0; i <= (I32) HvMAX(stash); i++) {
+           HE *entry;
            for (entry = HvARRAY(stash)[i];
                 entry;
                 entry = HeNEXT(entry))
            {
+               register GV *gv;
+               register SV *sv;
+
                if (!todo[(U8)*HeKEY(entry)])
                    continue;
                gv = (GV*)HeVAL(entry);
@@ -7868,7 +7880,7 @@ Perl_sv_reset(pTHX_ register const char *s, HV *stash)
                SvOK_off(sv);
                if (SvTYPE(sv) >= SVt_PV) {
                    SvCUR_set(sv, 0);
-                   if (SvPVX(sv) != Nullch)
+                   if (SvPVX_const(sv) != Nullch)
                        *SvPVX(sv) = '\0';
                    SvTAINT(sv);
                }
@@ -8039,7 +8051,7 @@ Perl_sv_true(pTHX_ register SV *sv)
        const register XPV* tXpv;
        if ((tXpv = (XPV*)SvANY(sv)) &&
                (tXpv->xpv_cur > 1 ||
-               (tXpv->xpv_cur && *sv->sv_u.sv_pv != '0')))
+               (tXpv->xpv_cur && *sv->sv_u.svu_pv != '0')))
            return 1;
        else
            return 0;
@@ -8209,14 +8221,14 @@ Perl_sv_pvn_force_flags(pTHX_ SV *sv, STRLEN *lp, I32 flags)
        }
        else
            s = sv_2pv_flags(sv, lp, flags);
-       if (s != SvPVX(sv)) {   /* Almost, but not quite, sv_setpvn() */
+       if (s != SvPVX_const(sv)) {     /* Almost, but not quite, sv_setpvn() */
            const STRLEN len = *lp;
        
            if (SvROK(sv))
                sv_unref(sv);
            (void)SvUPGRADE(sv, SVt_PV);                /* Never FALSE */
            SvGROW(sv, len + 1);
-           Move(s,SvPVX(sv),len,char);
+           Move(s,SvPVX_const(sv),len,char);
            SvCUR_set(sv, len);
            *SvEND(sv) = '\0';
        }
@@ -8224,7 +8236,7 @@ Perl_sv_pvn_force_flags(pTHX_ SV *sv, STRLEN *lp, I32 flags)
            SvPOK_on(sv);               /* validate pointer */
            SvTAINT(sv);
            DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2pv(%s)\n",
-                                 PTR2UV(sv),SvPVX(sv)));
+                                 PTR2UV(sv),SvPVX_const(sv)));
        }
     }
     return SvPVX(sv);
@@ -9057,11 +9069,11 @@ F0convert(NV nv, char *endbuf, STRLEN *len)
 {
     const int neg = nv < 0;
     UV uv;
-    char *p = endbuf;
 
     if (neg)
        nv = -nv;
     if (nv < UV_MAX) {
+       char *p = endbuf;
        nv += 0.5;
        uv = (UV)nv;
        if (uv & 1 && uv == nv)
@@ -9105,8 +9117,8 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     I32 svix = 0;
     static const char nullstr[] = "(null)";
     SV *argsv = Nullsv;
-    bool has_utf8; /* has the result utf8? */
-    bool pat_utf8; /* the pattern is in utf8? */
+    bool has_utf8 = DO_UTF8(sv);    /* has the result utf8? */
+    const bool pat_utf8 = has_utf8; /* the pattern is in utf8? */
     SV *nsv = Nullsv;
     /* Times 4: a decimal digit takes more than 3 binary digits.
      * NV_DIG: mantissa takes than many decimal digits.
@@ -9115,8 +9127,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     /* large enough for "%#.#f" --chip */
     /* what about long double NVs? --jhi */
 
-    has_utf8 = pat_utf8 = DO_UTF8(sv);
-
     /* no matter what, this is a string now */
     (void)SvPV_force(sv, origlen);
 
@@ -9354,7 +9364,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                vecstr = (U8*)SvPVx(vecsv,veclen);
                vec_utf8 = DO_UTF8(vecsv);
                /* if this is a version object, we need to return the
-                * stringified representation (which the SvPVX has
+                * stringified representation (which the SvPVX_const has
                 * already done for us), but not vectorize the args
                 */
                if ( *q == 'd' && sv_derived_from(vecsv,"version") )
@@ -9994,7 +10004,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_set(sv, p - SvPVX(sv));
+           SvCUR_set(sv, p - SvPVX_const(sv));
            svix = osvix;
            continue;   /* not "break" */
        }
@@ -10060,7 +10070,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_set(sv, p - SvPVX(sv));
+       SvCUR_set(sv, p - SvPVX_const(sv));
        if (vectorize) {
            esignlen = 0;
            goto vector;
@@ -10614,11 +10624,11 @@ Perl_rvpv_dup(pTHX_ SV *dstr, SV *sstr, CLONE_PARAMS* param)
                       : sv_dup_inc(SvRV(sstr), param));
 
     }
-    else if (SvPVX(sstr)) {
+    else if (SvPVX_const(sstr)) {
        /* Has something there */
        if (SvLEN(sstr)) {
            /* Normal PV - clone whole allocated space */
-           SvPV_set(dstr, SAVEPVN(SvPVX(sstr), SvLEN(sstr)-1));
+           SvPV_set(dstr, SAVEPVN(SvPVX_const(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:  */
@@ -10635,12 +10645,12 @@ Perl_rvpv_dup(pTHX_ SV *dstr, SV *sstr, CLONE_PARAMS* param)
                        and they should not have these flags
                        turned off */
 
-                    SvPV_set(dstr, sharepvn(SvPVX(sstr), SvCUR(sstr),
+                    SvPV_set(dstr, sharepvn(SvPVX_const(sstr), SvCUR(sstr),
                                            SvUVX(sstr)));
                     SvUV_set(dstr, SvUVX(sstr));
                 } else {
 
-                    SvPV_set(dstr, SAVEPVN(SvPVX(sstr), SvCUR(sstr)));
+                    SvPV_set(dstr, SAVEPVN(SvPVX_const(sstr), SvCUR(sstr)));
                     SvFAKE_off(dstr);
                     SvREADONLY_off(dstr);
                 }
@@ -10709,9 +10719,9 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
     SvREFCNT(dstr)     = 0;                    /* must be before any other dups! */
 
 #ifdef DEBUGGING
-    if (SvANY(sstr) && PL_watch_pvx && SvPVX(sstr) == PL_watch_pvx)
+    if (SvANY(sstr) && PL_watch_pvx && SvPVX_const(sstr) == PL_watch_pvx)
        PerlIO_printf(Perl_debug_log, "watch at %p hit, found string \"%s\"\n",
-                     PL_watch_pvx, SvPVX(sstr));
+                     PL_watch_pvx, SvPVX_const(sstr));
 #endif
 
     /* don't clone objects whose class has asked us not to */
@@ -10726,7 +10736,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvANY(dstr)     = NULL;
        break;
     case SVt_IV:
-       SvANY(dstr)     = (XPVIV*)((char*)&(dstr->sv_u.sv_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
+       SvANY(dstr)     = (XPVIV*)((char*)&(dstr->sv_u.svu_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
        SvIV_set(dstr, SvIVX(sstr));
        break;
     case SVt_NV:
@@ -10734,7 +10744,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvNV_set(dstr, SvNVX(sstr));
        break;
     case SVt_RV:
-       SvANY(dstr)     = &(dstr->sv_u.sv_rv);
+       SvANY(dstr)     = &(dstr->sv_u.svu_rv);
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        break;
     case SVt_PV:
@@ -10877,7 +10887,6 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvLEN_set(dstr, SvLEN(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);
        if (AvARRAY((AV*)sstr)) {
            SV **dst_ary, **src_ary;
            SSize_t items = AvFILLp((AV*)sstr) + 1;
@@ -10909,41 +10918,46 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvANY(dstr)     = new_XPVHV();
        SvCUR_set(dstr, SvCUR(sstr));
        SvLEN_set(dstr, SvLEN(sstr));
+       HvTOTALKEYS(dstr) = HvTOTALKEYS(sstr);
        SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
        SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        {
-           const char *hvname = HvNAME_get((HV*)sstr);
-           struct xpvhv_aux *aux = ((XPVHV *)SvANY(sstr))->xhv_aux;
-
-           ((XPVHV *)SvANY(dstr))->xhv_aux = 0;
-           if (aux) {
-               HvRITER_set((HV*)dstr, HvRITER_get((HV*)sstr));
-               /* FIXME strlen HvNAME  */
-               Perl_hv_name_set(aTHX_ (HV*) dstr, hvname,
-                                hvname ? strlen(hvname) : 0,
-                                0);
-           }
+           HEK *hvname = 0;
+
            if (HvARRAY((HV*)sstr)) {
                STRLEN i = 0;
-               XPVHV *dxhv = (XPVHV*)SvANY(dstr);
-               XPVHV *sxhv = (XPVHV*)SvANY(sstr);
+               const bool sharekeys = !!HvSHAREKEYS(sstr);
+               XPVHV * const dxhv = (XPVHV*)SvANY(dstr);
+               XPVHV * const sxhv = (XPVHV*)SvANY(sstr);
                char *darray;
-               /* FIXME - surely this doesn't need to be zeroed?  */
-               Newz(0, darray,
-                    PERL_HV_ARRAY_ALLOC_BYTES(dxhv->xhv_max+1), char);
+               New(0, darray,
+                    PERL_HV_ARRAY_ALLOC_BYTES(dxhv->xhv_max+1)
+                    + (SvOOK(sstr) ? sizeof(struct xpvhv_aux) : 0), char);
                HvARRAY(dstr) = (HE**)darray;
                while (i <= sxhv->xhv_max) {
+                   HE *source = HvARRAY(sstr)[i];
                    HvARRAY(dstr)[i]
-                       = he_dup(HvARRAY(sstr)[i],
-                                (bool)!!HvSHAREKEYS(sstr), param);
+                       = source ? he_dup(source, sharekeys, param) : 0;
                    ++i;
                }
-               HvEITER_set(dstr, he_dup(HvEITER_get(sstr),
-                                        (bool)!!HvSHAREKEYS(sstr), param));
+               if (SvOOK(sstr)) {
+                   struct xpvhv_aux *saux = HvAUX(sstr);
+                   struct xpvhv_aux *daux = HvAUX(dstr);
+                   /* This flag isn't copied.  */
+                   /* SvOOK_on(hv) attacks the IV flags.  */
+                   SvFLAGS(dstr) |= SVf_OOK;
+
+                   hvname = saux->xhv_name;
+                   daux->xhv_name = hvname ? hek_dup(hvname, param) : hvname;
+
+                   daux->xhv_riter = saux->xhv_riter;
+                   daux->xhv_eiter = saux->xhv_eiter
+                       ? he_dup(saux->xhv_eiter, (bool)!!HvSHAREKEYS(sstr),
+                                param) : 0;
+               }
            }
            else {
                SvPV_set(dstr, Nullch);
-               HvEITER_set((HV*)dstr, (HE*)NULL);
            }
            /* Record stashes for possible cloning in Perl_clone(). */
            if(hvname)
@@ -11192,16 +11206,18 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
     long longval;
     GP *gp;
     IV iv;
-    I32 i;
     char *c = NULL;
     void (*dptr) (void*);
     void (*dxptr) (pTHX_ void*);
     OP *o;
+    /* Unions for circumventing strict ANSI C89 casting rules. */
+    union { void *vptr; void (*dptr)(void*); } u1, u2;
+    union { void *vptr; void (*dxptr)(pTHX_ void*); } u3, u4;
 
     Newz(54, nss, max, ANY);
 
     while (ix > 0) {
-       i = POPINT(ss,ix);
+       I32 i = POPINT(ss,ix);
        TOPINT(nss,ix) = i;
        switch (i) {
        case SAVEt_ITEM:                        /* normal string */
@@ -11368,13 +11384,17 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = any_dup(ptr, proto_perl);  /* XXX quite arbitrary */
            dptr = POPDPTR(ss,ix);
-           TOPDPTR(nss,ix) = (void (*)(void*))any_dup((void *)dptr, proto_perl);
+           u1.dptr = dptr;
+           u2.vptr = any_dup(u1.vptr, proto_perl);
+           TOPDPTR(nss,ix) = u2.dptr;
            break;
        case SAVEt_DESTRUCTOR_X:
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = any_dup(ptr, proto_perl);  /* XXX quite arbitrary */
            dxptr = POPDXPTR(ss,ix);
-           TOPDXPTR(nss,ix) = (void (*)(pTHX_ void*))any_dup((void *)dxptr, proto_perl);
+           u3.dxptr = dxptr;
+           u4.vptr = any_dup(u3.vptr, proto_perl);;
+           TOPDXPTR(nss,ix) = u4.dxptr;
            break;
        case SAVEt_REGCONTEXT:
        case SAVEt_ALLOC:
@@ -11455,6 +11475,7 @@ do_mark_cloneable_stash(pTHX_ SV *sv)
     const char *hvname = HvNAME_get((HV*)sv);
     if (hvname) {
        GV* cloner = gv_fetchmethod_autoload((HV*)sv, "CLONE_SKIP", 0);
+       STRLEN len = HvNAMELEN_get((HV*)sv);
        SvFLAGS(sv) |= SVphv_CLONEABLE; /* clone objects by default */
        if (cloner && GvCV(cloner)) {
            dSP;
@@ -11463,7 +11484,7 @@ do_mark_cloneable_stash(pTHX_ SV *sv)
            ENTER;
            SAVETMPS;
            PUSHMARK(SP);
-           XPUSHs(sv_2mortal(newSVpv(hvname, 0)));
+           XPUSHs(sv_2mortal(newSVpvn(hvname, len)));
            PUTBACK;
            call_sv((SV*)GvCV(cloner), G_SCALAR);
            SPAGAIN;
@@ -11556,7 +11577,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
      * constants; they need to be allocated as common memory and just
      * their pointers copied. */
 
-    IV i;
     CLONE_PARAMS clone_params;
     CLONE_PARAMS* param = &clone_params;
 
@@ -11702,7 +11722,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     /* create (a non-shared!) shared string table */
     PL_strtab          = newHV();
     HvSHAREKEYS_off(PL_strtab);
-    hv_ksplit(PL_strtab, 512);
+    hv_ksplit(PL_strtab, HvTOTALKEYS(proto_perl->Istrtab));
     ptr_table_store(PL_ptr_table, proto_perl->Istrtab, PL_strtab);
 
     PL_compiling = proto_perl->Icompiling;
@@ -11783,6 +11803,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     {
        const I32 len = av_len((AV*)proto_perl->Iregex_padav);
        SV** regexen = AvARRAY((AV*)proto_perl->Iregex_padav);
+       IV i;
        av_push(PL_regex_padav,
                sv_dup_inc(regexen[0],param));
        for(i = 1; i <= len; i++) {
@@ -11967,13 +11988,13 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
      */
     if (SvANY(proto_perl->Ilinestr)) {
        PL_linestr              = sv_dup_inc(proto_perl->Ilinestr, param);
-       i = proto_perl->Ibufptr - SvPVX(proto_perl->Ilinestr);
+       i = proto_perl->Ibufptr - SvPVX_const(proto_perl->Ilinestr);
        PL_bufptr               = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-       i = proto_perl->Ioldbufptr - SvPVX(proto_perl->Ilinestr);
+       i = proto_perl->Ioldbufptr - SvPVX_const(proto_perl->Ilinestr);
        PL_oldbufptr    = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-       i = proto_perl->Ioldoldbufptr - SvPVX(proto_perl->Ilinestr);
+       i = proto_perl->Ioldoldbufptr - SvPVX_const(proto_perl->Ilinestr);
        PL_oldoldbufptr = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-       i = proto_perl->Ilinestart - SvPVX(proto_perl->Ilinestr);
+       i = proto_perl->Ilinestart - SvPVX_const(proto_perl->Ilinestr);
        PL_linestart    = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
     }
     else {
@@ -11999,9 +12020,9 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* XXX See comment on SvANY(proto_perl->Ilinestr) above */
     if (SvANY(proto_perl->Ilinestr)) {
-       i = proto_perl->Ilast_uni - SvPVX(proto_perl->Ilinestr);
+       i = proto_perl->Ilast_uni - SvPVX_const(proto_perl->Ilinestr);
        PL_last_uni             = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-       i = proto_perl->Ilast_lop - SvPVX(proto_perl->Ilinestr);
+       i = proto_perl->Ilast_lop - SvPVX_const(proto_perl->Ilinestr);
        PL_last_lop             = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
        PL_last_lop_op  = proto_perl->Ilast_lop_op;
     }
@@ -12313,7 +12334,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
            ENTER;
            SAVETMPS;
            PUSHMARK(SP);
-           XPUSHs(sv_2mortal(newSVpv(HvNAME_get(stash), 0)));
+           XPUSHs(sv_2mortal(newSVpvn(HvNAME_get(stash), HvNAMELEN_get(stash))));
            PUTBACK;
            call_sv((SV*)GvCV(cloner), G_DISCARD);
            FREETMPS;
@@ -12384,9 +12405,9 @@ Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding)
        uni = POPs;
        PUTBACK;
        s = SvPV(uni, len);
-       if (s != SvPVX(sv)) {
+       if (s != SvPVX_const(sv)) {
            SvGROW(sv, len + 1);
-           Move(s, SvPVX(sv), len, char);
+           Move(s, SvPVX_const(sv), len, char);
            SvCUR_set(sv, len);
            SvPVX(sv)[len] = 0; 
        }