This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add SS_ADD_* macros and replace most SSPUSH* uses
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index 2a4eb6b..397d992 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -66,8 +66,6 @@
 #ifdef PERL_OLD_COPY_ON_WRITE
 #define SV_COW_NEXT_SV(sv)     INT2PTR(SV *,SvUVX(sv))
 #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
 
 /* ============================================================================
@@ -133,10 +131,12 @@ called by visit() for each SV]):
                        dump all remaining SVs (debugging aid)
 
     sv_clean_objs() / do_clean_objs(),do_clean_named_objs(),
-                     do_clean_named_io_objs()
+                     do_clean_named_io_objs(),do_curse()
                        Attempt to free all objects pointed to by RVs,
-                       and try to do the same for all objects indirectly
-                       referenced by typeglobs too.  Called once from
+                       try to do the same for all objects indir-
+                       ectly referenced by typeglobs too, and
+                       then do a final sweep, cursing any
+                       objects that remain.  Called once from
                        perl_destruct(), prior to calling sv_clean_all()
                        below.
 
@@ -182,7 +182,9 @@ Public API:
 #endif
 
 #ifdef DEBUG_LEAKING_SCALARS
-#  define FREE_SV_DEBUG_FILE(sv) Safefree((sv)->sv_debug_file)
+#  define FREE_SV_DEBUG_FILE(sv) STMT_START { \
+       if ((sv)->sv_debug_file) PerlMemShared_free((sv)->sv_debug_file); \
+    } STMT_END
 #  define DEBUG_SV_SERIAL(sv)                                              \
     DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) del_SV\n",    \
            PTR2UV(sv), (long)(sv)->sv_debug_serial))
@@ -275,7 +277,7 @@ S_new_SV(pTHX_ const char *file, int line, const char *func)
            );
     sv->sv_debug_inpad = 0;
     sv->sv_debug_parent = NULL;
-    sv->sv_debug_file = PL_curcop ? savepv(CopFILE(PL_curcop)): NULL;
+    sv->sv_debug_file = PL_curcop ? savesharedpv(CopFILE(PL_curcop)): NULL;
 
     sv->sv_debug_serial = PL_sv_serial++;
 
@@ -479,8 +481,6 @@ do_clean_objs(pTHX_ SV *const ref)
            }
        }
     }
-
-    /* XXX Might want to check arrays, etc. */
 }
 
 
@@ -1136,7 +1136,7 @@ C<svtype>.
 */
 
 void
-Perl_sv_upgrade(pTHX_ register SV *const sv, svtype new_type)
+Perl_sv_upgrade(pTHX_ SV *const sv, svtype new_type)
 {
     dVAR;
     void*      old_body;
@@ -1399,7 +1399,9 @@ Perl_sv_upgrade(pTHX_ register SV *const sv, svtype new_type)
            SvSTASH_set(io, MUTABLE_HV(SvREFCNT_inc(GvHV(iogv))));
            IoPAGE_LEN(sv) = 60;
        }
-       if (old_type < SVt_PV) {
+       if (new_type == SVt_REGEXP)
+           sv->sv_u.svu_rx = (regexp *)new_body;
+       else if (old_type < SVt_PV) {
            /* referant will be NULL unless the old type was SVt_IV emulating
               SVt_RV */
            sv->sv_u.svu_rv = referant;
@@ -1434,7 +1436,7 @@ wrapper instead.
 */
 
 int
-Perl_sv_backoff(pTHX_ register SV *const sv)
+Perl_sv_backoff(pTHX_ SV *const sv)
 {
     STRLEN delta;
     const char * const s = SvPVX_const(sv);
@@ -1466,7 +1468,7 @@ Use the C<SvGROW> wrapper instead.
 */
 
 char *
-Perl_sv_grow(pTHX_ register SV *const sv, register STRLEN newlen)
+Perl_sv_grow(pTHX_ SV *const sv, STRLEN newlen)
 {
     char *s;
 
@@ -1500,7 +1502,10 @@ Perl_sv_grow(pTHX_ register SV *const sv, register STRLEN newlen)
 #endif
     }
     else
+    {
+       if (SvIsCOW(sv)) sv_force_normal(sv);
        s = SvPVX_mutable(sv);
+    }
 
     if (newlen > SvLEN(sv)) {          /* need more room? */
        STRLEN minlen = SvCUR(sv);
@@ -1542,7 +1547,7 @@ Does not handle 'set' magic.  See also C<sv_setiv_mg>.
 */
 
 void
-Perl_sv_setiv(pTHX_ register SV *const sv, const IV i)
+Perl_sv_setiv(pTHX_ SV *const sv, const IV i)
 {
     dVAR;
 
@@ -1585,7 +1590,7 @@ Like C<sv_setiv>, but also handles 'set' magic.
 */
 
 void
-Perl_sv_setiv_mg(pTHX_ register SV *const sv, const IV i)
+Perl_sv_setiv_mg(pTHX_ SV *const sv, const IV i)
 {
     PERL_ARGS_ASSERT_SV_SETIV_MG;
 
@@ -1603,7 +1608,7 @@ Does not handle 'set' magic.  See also C<sv_setuv_mg>.
 */
 
 void
-Perl_sv_setuv(pTHX_ register SV *const sv, const UV u)
+Perl_sv_setuv(pTHX_ SV *const sv, const UV u)
 {
     PERL_ARGS_ASSERT_SV_SETUV;
 
@@ -1636,7 +1641,7 @@ Like C<sv_setuv>, but also handles 'set' magic.
 */
 
 void
-Perl_sv_setuv_mg(pTHX_ register SV *const sv, const UV u)
+Perl_sv_setuv_mg(pTHX_ SV *const sv, const UV u)
 {
     PERL_ARGS_ASSERT_SV_SETUV_MG;
 
@@ -1654,7 +1659,7 @@ Does not handle 'set' magic.  See also C<sv_setnv_mg>.
 */
 
 void
-Perl_sv_setnv(pTHX_ register SV *const sv, const NV num)
+Perl_sv_setnv(pTHX_ SV *const sv, const NV num)
 {
     dVAR;
 
@@ -1698,7 +1703,7 @@ Like C<sv_setnv>, but also handles 'set' magic.
 */
 
 void
-Perl_sv_setnv_mg(pTHX_ register SV *const sv, const NV num)
+Perl_sv_setnv_mg(pTHX_ SV *const sv, const NV num)
 {
     PERL_ARGS_ASSERT_SV_SETNV_MG;
 
@@ -1915,7 +1920,7 @@ S_glob_2number(pTHX_ GV * const gv)
 
 /* For sv_2nv these three cases are "SvNOK and don't bother casting"  */
 STATIC int
-S_sv_2iuv_non_preserve(pTHX_ register SV *const sv
+S_sv_2iuv_non_preserve(pTHX_ SV *const sv
 #  ifdef DEBUGGING
                       , I32 numtype
 #  endif
@@ -2250,7 +2255,7 @@ Normally used via the C<SvIV(sv)> and C<SvIVx(sv)> macros.
 */
 
 IV
-Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags)
+Perl_sv_2iv_flags(pTHX_ SV *const sv, const I32 flags)
 {
     dVAR;
 
@@ -2273,7 +2278,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags)
        return PTR2IV(SvRV(sv));
     }
 
-    if (SvVALID(sv) || SvTYPE(sv) == SVt_REGEXP) {
+    if (SvVALID(sv) || isREGEXP(sv)) {
        /* FBMs use the space for SvIVX and SvNVX for other purposes, and use
           the same flag bit as SVf_IVisUV, so must not let them cache IVs.
           In practice they are extremely unlikely to actually get anywhere
@@ -2282,11 +2287,13 @@ Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags)
 
           Regexps have no SvIVX and SvNVX fields.
        */
-       assert(SvPOKp(sv));
+       assert(isREGEXP(sv) || SvPOKp(sv));
        {
            UV value;
+           const char * const ptr =
+               isREGEXP(sv) ? RX_WRAPPED((REGEXP*)sv) : SvPVX_const(sv);
            const int numtype
-               = grok_number(SvPVX_const(sv), SvCUR(sv), &value);
+               = grok_number(ptr, SvCUR(sv), &value);
 
            if ((numtype & (IS_NUMBER_IN_UV | IS_NUMBER_NOT_INT))
                == IS_NUMBER_IN_UV) {
@@ -2303,7 +2310,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags)
                if (ckWARN(WARN_NUMERIC))
                    not_a_number(sv);
            }
-           return I_V(Atof(SvPVX_const(sv)));
+           return I_V(Atof(ptr));
        }
     }
 
@@ -2341,7 +2348,7 @@ Normally used via the C<SvUV(sv)> and C<SvUVx(sv)> macros.
 */
 
 UV
-Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags)
+Perl_sv_2uv_flags(pTHX_ SV *const sv, const I32 flags)
 {
     dVAR;
 
@@ -2364,15 +2371,17 @@ Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags)
        return PTR2UV(SvRV(sv));
     }
 
-    if (SvVALID(sv) || SvTYPE(sv) == SVt_REGEXP) {
+    if (SvVALID(sv) || isREGEXP(sv)) {
        /* FBMs use the space for SvIVX and SvNVX for other purposes, and use
           the same flag bit as SVf_IVisUV, so must not let them cache IVs.  
           Regexps have no SvIVX and SvNVX fields. */
-       assert(SvPOKp(sv));
+       assert(isREGEXP(sv) || SvPOKp(sv));
        {
            UV value;
+           const char * const ptr =
+               isREGEXP(sv) ? RX_WRAPPED((REGEXP*)sv) : SvPVX_const(sv);
            const int numtype
-               = grok_number(SvPVX_const(sv), SvCUR(sv), &value);
+               = grok_number(ptr, SvCUR(sv), &value);
 
            if ((numtype & (IS_NUMBER_IN_UV | IS_NUMBER_NOT_INT))
                == IS_NUMBER_IN_UV) {
@@ -2384,7 +2393,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags)
                if (ckWARN(WARN_NUMERIC))
                    not_a_number(sv);
            }
-           return U_V(Atof(SvPVX_const(sv)));
+           return U_V(Atof(ptr));
        }
     }
 
@@ -2422,24 +2431,27 @@ Normally used via the C<SvNV(sv)> and C<SvNVx(sv)> macros.
 */
 
 NV
-Perl_sv_2nv_flags(pTHX_ register SV *const sv, const I32 flags)
+Perl_sv_2nv_flags(pTHX_ SV *const sv, const I32 flags)
 {
     dVAR;
     if (!sv)
        return 0.0;
-    if (SvGMAGICAL(sv) || SvVALID(sv) || SvTYPE(sv) == SVt_REGEXP) {
+    if (SvGMAGICAL(sv) || SvVALID(sv) || isREGEXP(sv)) {
        /* FBMs use the space for SvIVX and SvNVX for other purposes, and use
           the same flag bit as SVf_IVisUV, so must not let them cache NVs.
           Regexps have no SvIVX and SvNVX fields.  */
+       const char *ptr;
        if (flags & SV_GMAGIC)
            mg_get(sv);
        if (SvNOKp(sv))
            return SvNVX(sv);
        if (SvPOKp(sv) && !SvIOKp(sv)) {
+           ptr = SvPVX_const(sv);
+         grokpv:
            if (!SvIOKp(sv) && ckWARN(WARN_NUMERIC) &&
-               !grok_number(SvPVX_const(sv), SvCUR(sv), NULL))
+               !grok_number(ptr, SvCUR(sv), NULL))
                not_a_number(sv);
-           return Atof(SvPVX_const(sv));
+           return Atof(ptr);
        }
        if (SvIOKp(sv)) {
            if (SvIsUV(sv))
@@ -2450,6 +2462,10 @@ Perl_sv_2nv_flags(pTHX_ register SV *const sv, const I32 flags)
         if (SvROK(sv)) {
            goto return_rok;
        }
+       if (isREGEXP(sv)) {
+           ptr = RX_WRAPPED((REGEXP *)sv);
+           goto grokpv;
+       }
        assert(SvTYPE(sv) >= SVt_PVMG);
        /* This falls through to the report_uninit near the end of the
           function. */
@@ -2654,7 +2670,7 @@ access this function.
 */
 
 SV *
-Perl_sv_2num(pTHX_ register SV *const sv)
+Perl_sv_2num(pTHX_ SV *const sv)
 {
     PERL_ARGS_ASSERT_SV_2NUM;
 
@@ -2715,7 +2731,7 @@ C<sv_2pv()> and C<sv_2pv_nomg> usually end up here too.
 */
 
 char *
-Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags)
+Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
 {
     dVAR;
     char *s;
@@ -2913,6 +2929,10 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
            *lp = SvCUR(buffer);
        return SvPVX(buffer);
     }
+    else if (isREGEXP(sv)) {
+       if (lp) *lp = RX_WRAPLEN((REGEXP *)sv);
+       return RX_WRAPPED((REGEXP *)sv);
+    }
     else {
        if (lp)
            *lp = 0;
@@ -2966,7 +2986,7 @@ include SV_GMAGIC.
 */
 
 void
-Perl_sv_copypv(pTHX_ SV *const dsv, register SV *const ssv)
+Perl_sv_copypv(pTHX_ SV *const dsv, SV *const ssv)
 {
     PERL_ARGS_ASSERT_SV_COPYPV;
 
@@ -2974,7 +2994,7 @@ Perl_sv_copypv(pTHX_ SV *const dsv, register SV *const ssv)
 }
 
 void
-Perl_sv_copypv_flags(pTHX_ SV *const dsv, register SV *const ssv, const I32 flags)
+Perl_sv_copypv_flags(pTHX_ SV *const dsv, SV *const ssv, const I32 flags)
 {
     STRLEN len;
     const char *s;
@@ -3004,7 +3024,7 @@ Usually accessed via the C<SvPVbyte> macro.
 */
 
 char *
-Perl_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *const lp)
+Perl_sv_2pvbyte(pTHX_ SV *sv, STRLEN *const lp)
 {
     PERL_ARGS_ASSERT_SV_2PVBYTE;
 
@@ -3031,7 +3051,7 @@ Usually accessed via the C<SvPVutf8> macro.
 */
 
 char *
-Perl_sv_2pvutf8(pTHX_ register SV *sv, STRLEN *const lp)
+Perl_sv_2pvutf8(pTHX_ SV *sv, STRLEN *const lp)
 {
     PERL_ARGS_ASSERT_SV_2PVUTF8;
 
@@ -3063,7 +3083,7 @@ contain SV_GMAGIC, then it does an mg_get() first.
 */
 
 bool
-Perl_sv_2bool_flags(pTHX_ register SV *const sv, const I32 flags)
+Perl_sv_2bool_flags(pTHX_ SV *const sv, const I32 flags)
 {
     dVAR;
 
@@ -3150,7 +3170,7 @@ especially if it could return the position of the first one.
 */
 
 STRLEN
-Perl_sv_utf8_upgrade_flags_grow(pTHX_ register SV *const sv, const I32 flags, STRLEN extra)
+Perl_sv_utf8_upgrade_flags_grow(pTHX_ SV *const sv, const I32 flags, STRLEN extra)
 {
     dVAR;
 
@@ -3423,7 +3443,7 @@ use the Encode extension for that.
 */
 
 bool
-Perl_sv_utf8_downgrade(pTHX_ register SV *const sv, const bool fail_ok)
+Perl_sv_utf8_downgrade(pTHX_ SV *const sv, const bool fail_ok)
 {
     dVAR;
 
@@ -3483,7 +3503,7 @@ flag off so that it looks like octets again.
 */
 
 void
-Perl_sv_utf8_encode(pTHX_ register SV *const sv)
+Perl_sv_utf8_encode(pTHX_ SV *const sv)
 {
     PERL_ARGS_ASSERT_SV_UTF8_ENCODE;
 
@@ -3507,7 +3527,7 @@ Scans PV for validity and returns false if the PV is invalid UTF-8.
 */
 
 bool
-Perl_sv_utf8_decode(pTHX_ register SV *const sv)
+Perl_sv_utf8_decode(pTHX_ SV *const sv)
 {
     PERL_ARGS_ASSERT_SV_UTF8_DECODE;
 
@@ -3720,8 +3740,8 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
 static void
 S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
 {
-    SV * const sref = SvREFCNT_inc(SvRV(sstr));
-    SV *dref = NULL;
+    SV * const sref = SvRV(sstr);
+    SV *dref;
     const int intro = GvINTRO(dstr);
     SV **location;
     U8 import_flag = 0;
@@ -3767,10 +3787,26 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
                    GvCVGEN(dstr) = 0; /* Switch off cacheness. */
                }
            }
-           SAVEGENERICSV(*location);
-       }
-       else
-           dref = *location;
+           /* SAVEt_GVSLOT takes more room on the savestack and has more
+              overhead in leave_scope than SAVEt_GENERIC_SV.  But for CVs
+              leave_scope needs access to the GV so it can reset method
+              caches.  We must use SAVEt_GVSLOT whenever the type is
+              SVt_PVCV, even if the stash is anonymous, as the stash may
+              gain a name somehow before leave_scope. */
+           if (stype == SVt_PVCV) {
+               /* There is no save_pushptrptrptr.  Creating it for this
+                  one call site would be overkill.  So inline the ss add
+                  routines here. */
+                dSS_ADD;
+               SS_ADD_PTR(dstr);
+               SS_ADD_PTR(location);
+               SS_ADD_PTR(SvREFCNT_inc(*location));
+               SS_ADD_UV(SAVEt_GVSLOT);
+               SS_ADD_END(4);
+           }
+           else SAVEGENERICSV(*location);
+       }
+       dref = *location;
        if (stype == SVt_PVCV && (*location != sref || GvCVGEN(dstr))) {
            CV* const cv = MUTABLE_CV(*location);
            if (cv) {
@@ -3804,9 +3840,9 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
            }
            GvCVGEN(dstr) = 0; /* Switch off cacheness. */
            GvASSUMECV_on(dstr);
-           if(GvSTASH(dstr)) mro_method_changed_in(GvSTASH(dstr)); /* sub foo { 1 } sub bar { 2 } *bar = \&foo */
+           if(GvSTASH(dstr)) gv_method_changed(dstr); /* sub foo { 1 } sub bar { 2 } *bar = \&foo */
        }
-       *location = sref;
+       *location = SvREFCNT_inc_simple_NN(sref);
        if (import_flag && !(GvFLAGS(dstr) & import_flag)
            && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) {
            GvFLAGS(dstr) |= import_flag;
@@ -3887,14 +3923,27 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
         }
        break;
     }
-    SvREFCNT_dec(dref);
+    if (!intro) SvREFCNT_dec(dref);
     if (SvTAINTED(sstr))
        SvTAINT(dstr);
     return;
 }
 
+/* Work around compiler warnings about unsigned >= THRESHOLD when thres-
+   hold is 0. */
+#if SV_COW_THRESHOLD
+# define GE_COW_THRESHOLD(len)         ((len) >= SV_COW_THRESHOLD)
+#else
+# define GE_COW_THRESHOLD(len)         1
+#endif
+#if SV_COWBUF_THRESHOLD
+# define GE_COWBUF_THRESHOLD(len)      ((len) >= SV_COWBUF_THRESHOLD)
+#else
+# define GE_COWBUF_THRESHOLD(len)      1
+#endif
+
 void
-Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
+Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags)
 {
     dVAR;
     U32 sflags;
@@ -4011,8 +4060,17 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
        break;
 
     case SVt_REGEXP:
+      upgregexp:
        if (dtype < SVt_REGEXP)
+       {
+           if (dtype >= SVt_PV) {
+               SvPV_free(dstr);
+               SvPV_set(dstr, 0);
+               SvLEN_set(dstr, 0);
+               SvCUR_set(dstr, 0);
+           }
            sv_upgrade(dstr, SVt_REGEXP);
+       }
        break;
 
        /* case SVt_BIND: */
@@ -4029,7 +4087,10 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
                    return;
        }
        if (stype == SVt_PVLV)
+       {
+           if (isREGEXP(sstr)) goto upgregexp;
            SvUPGRADE(dstr, SVt_PVNV);
+       }
        else
            SvUPGRADE(dstr, (svtype)stype);
     }
@@ -4140,11 +4201,14 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
            }
        }
     }
-    else if (dtype == SVt_REGEXP && stype == SVt_REGEXP) {
+    else if ((dtype == SVt_REGEXP || dtype == SVt_PVLV)
+         && (stype == SVt_REGEXP || isREGEXP(sstr))) {
        reg_temp_copy((REGEXP*)dstr, (REGEXP*)sstr);
     }
     else if (sflags & SVp_POK) {
         bool isSwipe = 0;
+       const STRLEN cur = SvCUR(sstr);
+       const STRLEN len = SvLEN(sstr);
 
        /*
         * Check to see if we can just swipe the string.  If so, it's a
@@ -4167,13 +4231,20 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
               shared hash keys then we don't do the COW setup, even if the
               source scalar is a shared hash key scalar.  */
             (((flags & SV_COW_SHARED_HASH_KEYS)
-              ? (sflags & (SVf_FAKE|SVf_READONLY)) != (SVf_FAKE|SVf_READONLY)
+              ? !(sflags & SVf_IsCOW)
+#ifdef PERL_NEW_COPY_ON_WRITE
+               || (len &&
+                   ((!GE_COWBUF_THRESHOLD(cur) && SvLEN(dstr) > cur)
+                  /* If this is a regular (non-hek) COW, only so many COW
+                     "copies" are possible. */
+                   || CowREFCNT(sstr) == SV_COW_REFCNT_MAX))
+#endif
               : 1 /* If making a COW copy is forbidden then the behaviour we
                       desire is as if the source SV isn't actually already
                       COW, even if it is.  So we act as if the source flags
                       are not COW, rather than actually testing them.  */
              )
-#ifndef PERL_OLD_COPY_ON_WRITE
+#ifndef PERL_ANY_COW
             /* The change that added SV_COW_SHARED_HASH_KEYS makes the logic
                when PERL_OLD_COPY_ON_WRITE is defined a little wrong.
                Conceptually PERL_OLD_COPY_ON_WRITE being defined should
@@ -4188,26 +4259,38 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
             )
             &&
             !(isSwipe =
+#ifdef PERL_NEW_COPY_ON_WRITE
+                               /* slated for free anyway (and not COW)? */
+                 (sflags & (SVs_TEMP|SVf_IsCOW)) == SVs_TEMP &&
+#else
                  (sflags & SVs_TEMP) &&   /* slated for free anyway? */
+#endif
                  !(sflags & SVf_OOK) &&   /* and not involved in OOK hack? */
                 (!(flags & SV_NOSTEAL)) &&
                                        /* and we're allowed to steal temps */
                  SvREFCNT(sstr) == 1 &&   /* and no other references to it? */
-                 SvLEN(sstr))             /* and really is a string */
-#ifdef PERL_OLD_COPY_ON_WRITE
+                 len)             /* and really is a string */
+#ifdef PERL_ANY_COW
             && ((flags & SV_COW_SHARED_HASH_KEYS)
                ? (!((sflags & CAN_COW_MASK) == CAN_COW_FLAGS
+# ifdef PERL_OLD_COPY_ON_WRITE
                     && (SvFLAGS(dstr) & CAN_COW_MASK) == CAN_COW_FLAGS
-                    && SvTYPE(sstr) >= SVt_PVIV))
+                    && SvTYPE(sstr) >= SVt_PVIV
+# else
+                    && !(SvFLAGS(dstr) & SVf_BREAK)
+                    && !(sflags & SVf_IsCOW)
+                    && GE_COW_THRESHOLD(cur) && cur+1 < len
+                    && (GE_COWBUF_THRESHOLD(cur) || SvLEN(dstr) < cur+1)
+# endif
+                   ))
                : 1)
 #endif
             ) {
             /* Failed the swipe test, and it's not a shared hash key either.
                Have to copy the string.  */
-           STRLEN len = SvCUR(sstr);
-            SvGROW(dstr, len + 1);     /* inlined from sv_setpvn */
-            Move(SvPVX_const(sstr),SvPVX(dstr),len,char);
-            SvCUR_set(dstr, len);
+            SvGROW(dstr, cur + 1);     /* inlined from sv_setpvn */
+            Move(SvPVX_const(sstr),SvPVX(dstr),cur,char);
+            SvCUR_set(dstr, cur);
             *SvEND(dstr) = '\0';
         } else {
             /* If PERL_OLD_COPY_ON_WRITE is not defined, then isSwipe will always
@@ -4219,15 +4302,17 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
                 sv_dump(sstr);
                 sv_dump(dstr);
             }
-#ifdef PERL_OLD_COPY_ON_WRITE
+#ifdef PERL_ANY_COW
             if (!isSwipe) {
-                if ((sflags & (SVf_FAKE | SVf_READONLY))
-                    != (SVf_FAKE | SVf_READONLY)) {
-                    SvREADONLY_on(sstr);
-                    SvFAKE_on(sstr);
+                if (!(sflags & SVf_IsCOW)) {
+                    SvIsCOW_on(sstr);
+# ifdef PERL_OLD_COPY_ON_WRITE
                     /* Make the source SV into a loop of 1.
                        (about to become 2) */
                     SV_COW_NEXT_SV_SET(sstr, sstr);
+# else
+                   CowREFCNT(sstr) = 0;
+# endif
                 }
             }
 #endif
@@ -4238,15 +4323,17 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
 
             if (!isSwipe) {
                 /* making another shared SV.  */
-                STRLEN cur = SvCUR(sstr);
-                STRLEN len = SvLEN(sstr);
-#ifdef PERL_OLD_COPY_ON_WRITE
+#ifdef PERL_ANY_COW
                 if (len) {
+# ifdef PERL_OLD_COPY_ON_WRITE
                    assert (SvTYPE(dstr) >= SVt_PVIV);
                     /* SvIsCOW_normal */
                     /* splice us in between source and next-after-source.  */
                     SV_COW_NEXT_SV_SET(dstr, SV_COW_NEXT_SV(sstr));
                     SV_COW_NEXT_SV_SET(sstr, dstr);
+# else
+                   CowREFCNT(sstr)++;
+# endif
                     SvPV_set(dstr, SvPVX_mutable(sstr));
                 } else
 #endif
@@ -4261,8 +4348,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
                }
                 SvLEN_set(dstr, len);
                 SvCUR_set(dstr, cur);
-                SvREADONLY_on(dstr);
-                SvFAKE_on(dstr);
+                SvIsCOW_on(dstr);
             }
             else
                 {      /* Passes the swipe test.  */
@@ -4329,7 +4415,7 @@ Like C<sv_setsv>, but also handles 'set' magic.
 */
 
 void
-Perl_sv_setsv_mg(pTHX_ SV *const dstr, register SV *const sstr)
+Perl_sv_setsv_mg(pTHX_ SV *const dstr, SV *const sstr)
 {
     PERL_ARGS_ASSERT_SV_SETSV_MG;
 
@@ -4337,7 +4423,12 @@ Perl_sv_setsv_mg(pTHX_ SV *const dstr, register SV *const sstr)
     SvSETMAGIC(dstr);
 }
 
-#ifdef PERL_OLD_COPY_ON_WRITE
+#ifdef PERL_ANY_COW
+# ifdef PERL_OLD_COPY_ON_WRITE
+#  define SVt_COW SVt_PVIV
+# else
+#  define SVt_COW SVt_PV
+# endif
 SV *
 Perl_sv_setsv_cow(pTHX_ SV *dstr, SV *sstr)
 {
@@ -4363,14 +4454,16 @@ Perl_sv_setsv_cow(pTHX_ SV *dstr, SV *sstr)
     }
     else
        new_SV(dstr);
-    SvUPGRADE(dstr, SVt_PVIV);
+    SvUPGRADE(dstr, SVt_COW);
 
     assert (SvPOK(sstr));
     assert (SvPOKp(sstr));
+# ifdef PERL_OLD_COPY_ON_WRITE
     assert (!SvIOK(sstr));
     assert (!SvIOKp(sstr));
     assert (!SvNOK(sstr));
     assert (!SvNOKp(sstr));
+# endif
 
     if (SvIsCOW(sstr)) {
 
@@ -4381,22 +4474,34 @@ Perl_sv_setsv_cow(pTHX_ SV *dstr, SV *sstr)
            new_pv = HEK_KEY(share_hek_hek(SvSHARED_HEK_FROM_PV(SvPVX_const(sstr))));
            goto common_exit;
        }
+# ifdef PERL_OLD_COPY_ON_WRITE
        SV_COW_NEXT_SV_SET(dstr, SV_COW_NEXT_SV(sstr));
+# else
+       assert(SvCUR(sstr)+1 < SvLEN(sstr));
+       assert(CowREFCNT(sstr) < SV_COW_REFCNT_MAX);
+# endif
     } else {
        assert ((SvFLAGS(sstr) & CAN_COW_MASK) == CAN_COW_FLAGS);
-       SvUPGRADE(sstr, SVt_PVIV);
-       SvREADONLY_on(sstr);
-       SvFAKE_on(sstr);
+       SvUPGRADE(sstr, SVt_COW);
+       SvIsCOW_on(sstr);
        DEBUG_C(PerlIO_printf(Perl_debug_log,
                              "Fast copy on write: Converting sstr to COW\n"));
+# ifdef PERL_OLD_COPY_ON_WRITE
        SV_COW_NEXT_SV_SET(dstr, sstr);
+# else
+       CowREFCNT(sstr) = 0;    
+# endif
     }
+# ifdef PERL_OLD_COPY_ON_WRITE
     SV_COW_NEXT_SV_SET(sstr, dstr);
+# else
+    CowREFCNT(sstr)++; 
+# endif
     new_pv = SvPVX_mutable(sstr);
 
   common_exit:
     SvPV_set(dstr, new_pv);
-    SvFLAGS(dstr) = (SVt_PVIV|SVf_POK|SVp_POK|SVf_FAKE|SVf_READONLY);
+    SvFLAGS(dstr) = (SVt_COW|SVf_POK|SVp_POK|SVf_IsCOW);
     if (SvUTF8(sstr))
        SvUTF8_on(dstr);
     SvLEN_set(dstr, len);
@@ -4419,7 +4524,7 @@ undefined.  Does not handle 'set' magic.  See C<sv_setpvn_mg>.
 */
 
 void
-Perl_sv_setpvn(pTHX_ register SV *const sv, register const char *const ptr, register const STRLEN len)
+Perl_sv_setpvn(pTHX_ SV *const sv, const char *const ptr, const STRLEN len)
 {
     dVAR;
     char *dptr;
@@ -4458,7 +4563,7 @@ Like C<sv_setpvn>, but also handles 'set' magic.
 */
 
 void
-Perl_sv_setpvn_mg(pTHX_ register SV *const sv, register const char *const ptr, register const STRLEN len)
+Perl_sv_setpvn_mg(pTHX_ SV *const sv, const char *const ptr, const STRLEN len)
 {
     PERL_ARGS_ASSERT_SV_SETPVN_MG;
 
@@ -4476,7 +4581,7 @@ handle 'set' magic.  See C<sv_setpv_mg>.
 */
 
 void
-Perl_sv_setpv(pTHX_ register SV *const sv, register const char *const ptr)
+Perl_sv_setpv(pTHX_ SV *const sv, const char *const ptr)
 {
     dVAR;
     STRLEN len;
@@ -4508,7 +4613,7 @@ Like C<sv_setpv>, but also handles 'set' magic.
 */
 
 void
-Perl_sv_setpv_mg(pTHX_ register SV *const sv, register const char *const ptr)
+Perl_sv_setpv_mg(pTHX_ SV *const sv, const char *const ptr)
 {
     PERL_ARGS_ASSERT_SV_SETPV_MG;
 
@@ -4517,7 +4622,7 @@ Perl_sv_setpv_mg(pTHX_ register SV *const sv, register const char *const ptr)
 }
 
 void
-Perl_sv_sethek(pTHX_ register SV *const sv, const HEK *const hek)
+Perl_sv_sethek(pTHX_ SV *const sv, const HEK *const hek)
 {
     dVAR;
 
@@ -4538,7 +4643,7 @@ Perl_sv_sethek(pTHX_ register SV *const sv, const HEK *const hek)
            sv_usepvn_flags(sv, as_utf8, utf8_len, SV_HAS_TRAILING_NUL);
            SvUTF8_on(sv);
             return;
-       } else if (flags & (HVhek_REHASH|HVhek_UNSHARED)) {
+        } else if (flags & HVhek_UNSHARED) {
            sv_setpvn(sv, HEK_KEY(hek), HEK_LEN(hek));
            if (HEK_UTF8(hek))
                SvUTF8_on(sv);
@@ -4552,8 +4657,7 @@ Perl_sv_sethek(pTHX_ register SV *const sv, const HEK *const hek)
            SvPV_set(sv,(char *)HEK_KEY(share_hek_hek(hek)));
            SvCUR_set(sv, HEK_LEN(hek));
            SvLEN_set(sv, 0);
-           SvREADONLY_on(sv);
-           SvFAKE_on(sv);
+           SvIsCOW_on(sv);
            SvPOK_on(sv);
            if (HEK_UTF8(hek))
                SvUTF8_on(sv);
@@ -4655,7 +4759,7 @@ Perl_sv_usepvn_flags(pTHX_ SV *const sv, char *ptr, const STRLEN len, const U32
    (which it can do by means other than releasing copy-on-write Svs)
    or by changing the other copy-on-write SVs in the loop.  */
 STATIC void
-S_sv_release_COW(pTHX_ register SV *sv, const char *pvx, SV *after)
+S_sv_release_COW(pTHX_ SV *sv, const char *pvx, SV *after)
 {
     PERL_ARGS_ASSERT_SV_RELEASE_COW;
 
@@ -4667,8 +4771,7 @@ S_sv_release_COW(pTHX_ register SV *sv, const char *pvx, SV *after)
             /* The SV we point to points back to us (there were only two of us
                in the loop.)
                Hence other SV is no longer copy on write either.  */
-            SvFAKE_off(after);
-            SvREADONLY_off(after);
+            SvIsCOW_off(after);
         } else {
             /* We need to follow the pointers around the loop.  */
             SV *next;
@@ -4706,32 +4809,48 @@ with flags set to 0.
 */
 
 void
-Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
+Perl_sv_force_normal_flags(pTHX_ SV *const sv, const U32 flags)
 {
     dVAR;
 
     PERL_ARGS_ASSERT_SV_FORCE_NORMAL_FLAGS;
 
-#ifdef PERL_OLD_COPY_ON_WRITE
+#ifdef PERL_ANY_COW
     if (SvREADONLY(sv)) {
-       if (SvIsCOW(sv)) {
-           const char * const pvx = SvPVX_const(sv);
-           const STRLEN len = SvLEN(sv);
-           const STRLEN cur = SvCUR(sv);
-           /* next COW sv in the loop.  If len is 0 then this is a shared-hash
-              key scalar, so we mustn't attempt to call SV_COW_NEXT_SV(), as
-              we'll fail an assertion.  */
-           SV * const next = len ? SV_COW_NEXT_SV(sv) : 0;
+       if (IN_PERL_RUNTIME)
+           Perl_croak_no_modify();
+    }
+    else if (SvIsCOW(sv)) {
+       const char * const pvx = SvPVX_const(sv);
+       const STRLEN len = SvLEN(sv);
+       const STRLEN cur = SvCUR(sv);
+# ifdef PERL_OLD_COPY_ON_WRITE
+       /* next COW sv in the loop.  If len is 0 then this is a shared-hash
+          key scalar, so we mustn't attempt to call SV_COW_NEXT_SV(), as
+          we'll fail an assertion.  */
+       SV * const next = len ? SV_COW_NEXT_SV(sv) : 0;
+# endif
 
-            if (DEBUG_C_TEST) {
+        if (DEBUG_C_TEST) {
                 PerlIO_printf(Perl_debug_log,
                               "Copy on write: Force normal %ld\n",
                               (long) flags);
                 sv_dump(sv);
-            }
-            SvFAKE_off(sv);
-            SvREADONLY_off(sv);
+        }
+        SvIsCOW_off(sv);
+# ifdef PERL_NEW_COPY_ON_WRITE
+       if (len && CowREFCNT(sv) == 0)
+           /* We own the buffer ourselves. */
+           NOOP;
+       else
+# endif
+       {
+               
             /* This SV doesn't own the buffer, so need to Newx() a new one:  */
+# ifdef PERL_NEW_COPY_ON_WRITE
+           /* Must do this first, since the macro uses SvPVX. */
+           if (len) CowREFCNT(sv)--;
+# endif
             SvPV_set(sv, NULL);
             SvLEN_set(sv, 0);
             if (flags & SV_COW_DROP_PV) {
@@ -4744,7 +4863,9 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
                 *SvEND(sv) = '\0';
             }
            if (len) {
+# ifdef PERL_OLD_COPY_ON_WRITE
                sv_release_COW(sv, pvx, next);
+# endif
            } else {
                unshare_hek(SvSHARED_HEK_FROM_PV(pvx));
            }
@@ -4752,16 +4873,17 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
                 sv_dump(sv);
             }
        }
-       else if (IN_PERL_RUNTIME)
-           Perl_croak_no_modify(aTHX);
     }
 #else
     if (SvREADONLY(sv)) {
+       if (IN_PERL_RUNTIME)
+           Perl_croak_no_modify();
+    }
+    else
        if (SvIsCOW(sv)) {
            const char * const pvx = SvPVX_const(sv);
            const STRLEN len = SvCUR(sv);
-           SvFAKE_off(sv);
-           SvREADONLY_off(sv);
+           SvIsCOW_off(sv);
            SvPV_set(sv, NULL);
            SvLEN_set(sv, 0);
            if (flags & SV_COW_DROP_PV) {
@@ -4774,20 +4896,19 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
            }
            unshare_hek(SvSHARED_HEK_FROM_PV(pvx));
        }
-       else if (IN_PERL_RUNTIME)
-           Perl_croak_no_modify(aTHX);
-    }
 #endif
     if (SvROK(sv))
        sv_unref_flags(sv, flags);
     else if (SvFAKE(sv) && isGV_with_GP(sv))
        sv_unglob(sv, flags);
-    else if (SvFAKE(sv) && SvTYPE(sv) == SVt_REGEXP) {
+    else if (SvFAKE(sv) && isREGEXP(sv)) {
        /* Need to downgrade the REGEXP to a simple(r) scalar. This is analogous
           to sv_unglob. We only need it here, so inline it.  */
-       const svtype new_type = SvMAGIC(sv) || SvSTASH(sv) ? SVt_PVMG : SVt_PV;
+       const bool islv = SvTYPE(sv) == SVt_PVLV;
+       const svtype new_type =
+         islv ? SVt_NULL : SvMAGIC(sv) || SvSTASH(sv) ? SVt_PVMG : SVt_PV;
        SV *const temp = newSV_type(new_type);
-       void *const temp_p = SvANY(sv);
+       regexp *const temp_p = ReANY((REGEXP *)sv);
 
        if (new_type == SVt_PVMG) {
            SvMAGIC_set(temp, SvMAGIC(sv));
@@ -4795,29 +4916,37 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
            SvSTASH_set(temp, SvSTASH(sv));
            SvSTASH_set(sv, NULL);
        }
-       SvCUR_set(temp, SvCUR(sv));
-       /* Remember that SvPVX is in the head, not the body. */
-       if (SvLEN(temp)) {
-           SvLEN_set(temp, SvLEN(sv));
-           /* This signals "buffer is owned by someone else" in sv_clear,
-              which is the least effort way to stop it freeing the buffer.
-           */
-           SvLEN_set(sv, SvLEN(sv)+1);
-       } else {
-           /* Their buffer is already owned by someone else. */
-           SvPVX(sv) = savepvn(SvPVX(sv), SvCUR(sv));
-           SvLEN_set(temp, SvCUR(sv)+1);
+       if (!islv) SvCUR_set(temp, SvCUR(sv));
+       /* Remember that SvPVX is in the head, not the body.  But
+          RX_WRAPPED is in the body. */
+       assert(ReANY((REGEXP *)sv)->mother_re);
+       /* Their buffer is already owned by someone else. */
+       if (flags & SV_COW_DROP_PV) {
+           /* SvLEN is already 0.  For SVt_REGEXP, we have a brand new
+              zeroed body.  For SVt_PVLV, it should have been set to 0
+              before turning into a regexp. */
+           assert(!SvLEN(islv ? sv : temp));
+           sv->sv_u.svu_pv = 0;
+       }
+       else {
+           sv->sv_u.svu_pv = savepvn(RX_WRAPPED((REGEXP *)sv), SvCUR(sv));
+           SvLEN_set(islv ? sv : temp, SvCUR(sv)+1);
+           SvPOK_on(sv);
        }
 
        /* Now swap the rest of the bodies. */
 
-       SvFLAGS(sv) &= ~(SVf_FAKE|SVTYPEMASK);
-       SvFLAGS(sv) |= new_type;
-       SvANY(sv) = SvANY(temp);
+       SvFAKE_off(sv);
+       if (!islv) {
+           SvFLAGS(sv) &= ~SVTYPEMASK;
+           SvFLAGS(sv) |= new_type;
+           SvANY(sv) = SvANY(temp);
+       }
 
        SvFLAGS(temp) &= ~(SVTYPEMASK);
        SvFLAGS(temp) |= SVt_REGEXP|SVf_FAKE;
        SvANY(temp) = temp_p;
+       temp->sv_u.svu_rx = (regexp *)temp_p;
 
        SvREFCNT_dec(temp);
     }
@@ -4844,7 +4973,7 @@ C<chop> works from the right.
 */
 
 void
-Perl_sv_chop(pTHX_ register SV *const sv, register const char *const ptr)
+Perl_sv_chop(pTHX_ SV *const sv, const char *const ptr)
 {
     STRLEN delta;
     STRLEN old_delta;
@@ -4944,7 +5073,7 @@ in terms of this function.
 */
 
 void
-Perl_sv_catpvn_flags(pTHX_ register SV *const dsv, register const char *sstr, register const STRLEN slen, const I32 flags)
+Perl_sv_catpvn_flags(pTHX_ SV *const dsv, const char *sstr, const STRLEN slen, const I32 flags)
 {
     dVAR;
     STRLEN dlen;
@@ -5015,7 +5144,7 @@ and C<sv_catsv_mg> are implemented in terms of this function.
 =cut */
 
 void
-Perl_sv_catsv_flags(pTHX_ SV *const dsv, register SV *const ssv, const I32 flags)
+Perl_sv_catsv_flags(pTHX_ SV *const dsv, SV *const ssv, const I32 flags)
 {
     dVAR;
  
@@ -5045,7 +5174,7 @@ valid UTF-8.  Handles 'get' magic, but not 'set' magic.  See C<sv_catpv_mg>.
 =cut */
 
 void
-Perl_sv_catpv(pTHX_ register SV *const sv, register const char *ptr)
+Perl_sv_catpv(pTHX_ SV *const sv, const char *ptr)
 {
     dVAR;
     STRLEN len;
@@ -5094,7 +5223,7 @@ Like C<sv_catpv>, but also handles 'set' magic.
 */
 
 void
-Perl_sv_catpv_mg(pTHX_ register SV *const sv, register const char *const ptr)
+Perl_sv_catpv_mg(pTHX_ SV *const sv, const char *const ptr)
 {
     PERL_ARGS_ASSERT_SV_CATPV_MG;
 
@@ -5240,7 +5369,7 @@ to add more than one instance of the same 'how'.
 */
 
 void
-Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how, 
+Perl_sv_magic(pTHX_ SV *const sv, SV *const obj, const int how,
              const char *const name, const I32 namlen)
 {
     dVAR;
@@ -5265,7 +5394,7 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how,
     vtable = (vtable_index == magic_vtable_max)
        ? NULL : PL_magic_vtables + vtable_index;
 
-#ifdef PERL_OLD_COPY_ON_WRITE
+#ifdef PERL_ANY_COW
     if (SvIsCOW(sv))
         sv_force_normal_flags(sv, 0);
 #endif
@@ -5278,7 +5407,7 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how,
            && !PERL_MAGIC_TYPE_READONLY_ACCEPTABLE(how)
           )
        {
-           Perl_croak_no_modify(aTHX);
+           Perl_croak_no_modify();
        }
     }
     if (SvMAGICAL(sv) || (how == PERL_MAGIC_taint && SvTYPE(sv) >= SVt_PVMG)) {
@@ -5824,7 +5953,7 @@ time you'll want to use C<sv_setsv> or one of its many macro front-ends.
 */
 
 void
-Perl_sv_replace(pTHX_ register SV *const sv, register SV *const nsv)
+Perl_sv_replace(pTHX_ SV *const sv, SV *const nsv)
 {
     dVAR;
     const U32 refcnt = SvREFCNT(sv);
@@ -6028,6 +6157,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
            goto freescalar;
        case SVt_REGEXP:
            /* FIXME for plugins */
+         freeregexp:
            pregfree2((REGEXP*) sv);
            goto freescalar;
        case SVt_PVCV:
@@ -6104,6 +6234,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
            }
            else if (LvTYPE(sv) != 't') /* unless tie: unrefcnted fake SV**  */
                SvREFCNT_dec(LvTARG(sv));
+           if (isREGEXP(sv)) goto freeregexp;
        case SVt_PVGV:
            if (isGV_with_GP(sv)) {
                if(GvCVu((const GV *)sv) && (stash = GvSTASH(MUTABLE_GV(sv)))
@@ -6149,7 +6280,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                        next_sv = target;
                }
            }
-#ifdef PERL_OLD_COPY_ON_WRITE
+#ifdef PERL_ANY_COW
            else if (SvPVX_const(sv)
                     && !(SvTYPE(sv) == SVt_PVIO
                     && !(IoFLAGS(sv) & IOf_FAKE_DIRP)))
@@ -6160,13 +6291,23 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                        sv_dump(sv);
                    }
                    if (SvLEN(sv)) {
+# ifdef PERL_OLD_COPY_ON_WRITE
                        sv_release_COW(sv, SvPVX_const(sv), SV_COW_NEXT_SV(sv));
+# else
+                       if (CowREFCNT(sv)) {
+                           CowREFCNT(sv)--;
+                           SvLEN_set(sv, 0);
+                       }
+# endif
                    } else {
                        unshare_hek(SvSHARED_HEK_FROM_PV(SvPVX_const(sv)));
                    }
 
-                   SvFAKE_off(sv);
-               } else if (SvLEN(sv)) {
+               }
+# ifdef PERL_OLD_COPY_ON_WRITE
+               else
+# endif
+               if (SvLEN(sv)) {
                    Safefree(SvPVX_mutable(sv));
                }
            }
@@ -6177,7 +6318,6 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                Safefree(SvPVX_mutable(sv));
            else if (SvPVX_const(sv) && SvIsCOW(sv)) {
                unshare_hek(SvSHARED_HEK_FROM_PV(SvPVX_const(sv)));
-               SvFAKE_off(sv);
            }
 #endif
            break;
@@ -6296,10 +6436,22 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
        dSP;
        HV* stash;
        do {
-           CV* destructor;
-           stash = SvSTASH(sv);
-           destructor = StashHANDLER(stash,DESTROY);
-           if (destructor
+         stash = SvSTASH(sv);
+         assert(SvTYPE(stash) == SVt_PVHV);
+         if (HvNAME(stash)) {
+           CV* destructor = NULL;
+           if (!SvOBJECT(stash)) destructor = (CV *)SvSTASH(stash);
+           if (!destructor) {
+               GV * const gv =
+                   gv_fetchmeth_autoload(stash, "DESTROY", 7, 0);
+               if (gv) destructor = GvCV(gv);
+               if (!SvOBJECT(stash))
+                   SvSTASH(stash) =
+                       destructor ? (HV *)destructor : ((HV *)0)+1;
+           }
+           assert(!destructor || destructor == ((CV *)0)+1
+               || SvTYPE(destructor) == SVt_PVCV);
+           if (destructor && destructor != ((CV *)0)+1
                /* A constant subroutine can have no side effects, so
                   don't bother calling it.  */
                && !CvCONST(destructor)
@@ -6338,6 +6490,7 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
                }
                SvREFCNT_dec(tmpref);
            }
+         }
        } while (SvOBJECT(sv) && SvSTASH(sv) != stash);
 
 
@@ -6352,8 +6505,12 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
     }
 
     if (SvOBJECT(sv)) {
-       SvREFCNT_dec(SvSTASH(sv)); /* possibly of changed persuasion */
+       HV * const stash = SvSTASH(sv);
+       /* Curse before freeing the stash, as freeing the stash could cause
+          a recursive call into S_curse. */
        SvOBJECT_off(sv);       /* Curse the object. */
+       SvSTASH_set(sv,0);      /* SvREFCNT_dec may try to read this */
+       SvREFCNT_dec(stash); /* possibly of changed persuasion */
        if (SvTYPE(sv) != SVt_PVIO)
            --PL_sv_objcount;/* XXX Might want something more general */
     }
@@ -6473,7 +6630,7 @@ gives raw access to the xpv_cur slot.
 */
 
 STRLEN
-Perl_sv_len(pTHX_ register SV *const sv)
+Perl_sv_len(pTHX_ SV *const sv)
 {
     STRLEN len;
 
@@ -6503,7 +6660,7 @@ UTF-8 bytes as a single character.  Handles magic and type coercion.
  */
 
 STRLEN
-Perl_sv_len_utf8(pTHX_ register SV *const sv)
+Perl_sv_len_utf8(pTHX_ SV *const sv)
 {
     if (!sv)
        return 0;
@@ -6811,7 +6968,7 @@ than 2Gb.
 /* This function is subject to size and sign problems */
 
 void
-Perl_sv_pos_u2b(pTHX_ register SV *const sv, I32 *const offsetp, I32 *const lenp)
+Perl_sv_pos_u2b(pTHX_ SV *const sv, I32 *const offsetp, I32 *const lenp)
 {
     PERL_ARGS_ASSERT_SV_POS_U2B;
 
@@ -7037,7 +7194,7 @@ Handles magic and type coercion.
  *
  */
 void
-Perl_sv_pos_b2u(pTHX_ register SV *const sv, I32 *const offsetp)
+Perl_sv_pos_b2u(pTHX_ SV *const sv, I32 *const offsetp)
 {
     const U8* s;
     const STRLEN byte = *offsetp;
@@ -7164,7 +7321,7 @@ if necessary.  If the flags include SV_GMAGIC, it handles get-magic, too.
 */
 
 I32
-Perl_sv_eq_flags(pTHX_ register SV *sv1, register SV *sv2, const U32 flags)
+Perl_sv_eq_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
 {
     dVAR;
     const char *pv1;
@@ -7259,13 +7416,13 @@ also C<sv_cmp_locale_flags>.
 */
 
 I32
-Perl_sv_cmp(pTHX_ register SV *const sv1, register SV *const sv2)
+Perl_sv_cmp(pTHX_ SV *const sv1, SV *const sv2)
 {
     return sv_cmp_flags(sv1, sv2, SV_GMAGIC);
 }
 
 I32
-Perl_sv_cmp_flags(pTHX_ register SV *const sv1, register SV *const sv2,
+Perl_sv_cmp_flags(pTHX_ SV *const sv1, SV *const sv2,
                  const U32 flags)
 {
     dVAR;
@@ -7358,13 +7515,13 @@ flags contain SV_GMAGIC, it handles get magic.  See also C<sv_cmp_flags>.
 */
 
 I32
-Perl_sv_cmp_locale(pTHX_ register SV *const sv1, register SV *const sv2)
+Perl_sv_cmp_locale(pTHX_ SV *const sv1, SV *const sv2)
 {
     return sv_cmp_locale_flags(sv1, sv2, SV_GMAGIC);
 }
 
 I32
-Perl_sv_cmp_locale_flags(pTHX_ register SV *const sv1, register SV *const sv2,
+Perl_sv_cmp_locale_flags(pTHX_ SV *const sv1, SV *const sv2,
                         const U32 flags)
 {
     dVAR;
@@ -7546,7 +7703,7 @@ in the SV (typically, C<SvCUR(sv)> is a suitable choice).
 */
 
 char *
-Perl_sv_gets(pTHX_ register SV *const sv, register PerlIO *const fp, I32 append)
+Perl_sv_gets(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
 {
     dVAR;
     const char *rsptr;
@@ -7879,7 +8036,7 @@ if necessary.  Handles 'get' magic and operator overloading.
 */
 
 void
-Perl_sv_inc(pTHX_ register SV *const sv)
+Perl_sv_inc(pTHX_ SV *const sv)
 {
     if (!sv)
        return;
@@ -7897,7 +8054,7 @@ if necessary.  Handles operator overloading.  Skips handling 'get' magic.
 */
 
 void
-Perl_sv_inc_nomg(pTHX_ register SV *const sv)
+Perl_sv_inc_nomg(pTHX_ SV *const sv)
 {
     dVAR;
     char *d;
@@ -7910,7 +8067,7 @@ Perl_sv_inc_nomg(pTHX_ register SV *const sv)
            sv_force_normal_flags(sv, 0);
        if (SvREADONLY(sv)) {
            if (IN_PERL_RUNTIME)
-               Perl_croak_no_modify(aTHX);
+               Perl_croak_no_modify();
        }
        if (SvROK(sv)) {
            IV i;
@@ -8061,7 +8218,7 @@ if necessary.  Handles 'get' magic and operator overloading.
 */
 
 void
-Perl_sv_dec(pTHX_ register SV *const sv)
+Perl_sv_dec(pTHX_ SV *const sv)
 {
     dVAR;
     if (!sv)
@@ -8080,7 +8237,7 @@ if necessary.  Handles operator overloading.  Skips handling 'get' magic.
 */
 
 void
-Perl_sv_dec_nomg(pTHX_ register SV *const sv)
+Perl_sv_dec_nomg(pTHX_ SV *const sv)
 {
     dVAR;
     int flags;
@@ -8092,7 +8249,7 @@ Perl_sv_dec_nomg(pTHX_ register SV *const sv)
            sv_force_normal_flags(sv, 0);
        if (SvREADONLY(sv)) {
            if (IN_PERL_RUNTIME)
-               Perl_croak_no_modify(aTHX);
+               Perl_croak_no_modify();
        }
        if (SvROK(sv)) {
            IV i;
@@ -8319,7 +8476,7 @@ and C<sv_mortalcopy>.
 */
 
 SV *
-Perl_sv_2mortal(pTHX_ register SV *const sv)
+Perl_sv_2mortal(pTHX_ SV *const sv)
 {
     dVAR;
     if (!sv)
@@ -8412,13 +8569,8 @@ Perl_newSVhek(pTHX_ const HEK *const hek)
            sv_usepvn_flags(sv, as_utf8, utf8_len, SV_HAS_TRAILING_NUL);
            SvUTF8_on (sv);
            return sv;
-       } else if (flags & (HVhek_REHASH|HVhek_UNSHARED)) {
-           /* We don't have a pointer to the hv, so we have to replicate the
-              flag into every HEK. This hv is using custom a hasing
-              algorithm. Hence we can't return a shared string scalar, as
-              that would contain the (wrong) hash value, and might get passed
-              into an hv routine with a regular hash.
-              Similarly, a hash that isn't using shared hash keys has to have
+        } else if (flags & HVhek_UNSHARED) {
+            /* A hash that isn't using shared hash keys has to have
               the flag in every key so that we know not to try to call
               share_hek_hek on it.  */
 
@@ -8438,8 +8590,7 @@ Perl_newSVhek(pTHX_ const HEK *const hek)
            SvPV_set(sv, (char *)HEK_KEY(share_hek_hek(hek)));
            SvCUR_set(sv, HEK_LEN(hek));
            SvLEN_set(sv, 0);
-           SvREADONLY_on(sv);
-           SvFAKE_on(sv);
+           SvIsCOW_on(sv);
            SvPOK_on(sv);
            if (HEK_UTF8(hek))
                SvUTF8_on(sv);
@@ -8487,8 +8638,7 @@ Perl_newSVpvn_share(pTHX_ const char *src, I32 len, U32 hash)
     SvPV_set(sv, sharepvn(src, is_utf8?-len:len, hash));
     SvCUR_set(sv, len);
     SvLEN_set(sv, 0);
-    SvREADONLY_on(sv);
-    SvFAKE_on(sv);
+    SvIsCOW_on(sv);
     SvPOK_on(sv);
     if (is_utf8)
         SvUTF8_on(sv);
@@ -8699,7 +8849,7 @@ Creates a new SV which is an exact duplicate of the original SV.
 */
 
 SV *
-Perl_newSVsv(pTHX_ register SV *const old)
+Perl_newSVsv(pTHX_ SV *const old)
 {
     dVAR;
     SV *sv;
@@ -8729,7 +8879,7 @@ Note that the perl-level function is vaguely deprecated.
 */
 
 void
-Perl_sv_reset(pTHX_ register const char *s, HV *const stash)
+Perl_sv_reset(pTHX_ const char *s, HV *const stash)
 {
     PERL_ARGS_ASSERT_SV_RESET;
 
@@ -8981,7 +9131,7 @@ instead use an in-line version.
 */
 
 I32
-Perl_sv_true(pTHX_ register SV *const sv)
+Perl_sv_true(pTHX_ SV *const sv)
 {
     if (!sv)
        return 0;
@@ -9183,7 +9333,7 @@ Returns a SV describing what the SV passed in is a reference to.
 */
 
 SV *
-Perl_sv_ref(pTHX_ register SV *dst, const SV *const sv, const int ob)
+Perl_sv_ref(pTHX_ SV *dst, const SV *const sv, const int ob)
 {
     PERL_ARGS_ASSERT_SV_REF;
 
@@ -9451,7 +9601,7 @@ Perl_sv_bless(pTHX_ SV *const sv, HV *const stash)
     tmpRef = SvRV(sv);
     if (SvFLAGS(tmpRef) & (SVs_OBJECT|SVf_READONLY)) {
        if (SvREADONLY(tmpRef) && !SvIsCOW(tmpRef))
-           Perl_croak_no_modify(aTHX);
+           Perl_croak_no_modify();
        if (SvOBJECT(tmpRef)) {
            if (SvTYPE(tmpRef) != SVt_PVIO)
                --PL_sv_objcount;
@@ -11735,6 +11885,7 @@ Perl_rvpv_dup(pTHX_ SV *const dstr, const SV *const sstr, CLONE_PARAMS *const pa
 {
     PERL_ARGS_ASSERT_RVPV_DUP;
 
+    assert(!isREGEXP(sstr));
     if (SvROK(sstr)) {
        if (SvWEAKREF(sstr)) {
            SvRV_set(dstr, sv_dup(SvRV_const(sstr), param));
@@ -11752,19 +11903,16 @@ Perl_rvpv_dup(pTHX_ SV *const dstr, const SV *const sstr, CLONE_PARAMS *const pa
        if (SvLEN(sstr)) {
            /* Normal PV - clone whole allocated space */
            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, independent SV, so:  */
-               SvREADONLY_off(dstr);
-               SvFAKE_off(dstr);
-           }
+           /* sstr may not be that normal, but actually copy on write.
+              But we are a true, independent SV, so:  */
+           SvIsCOW_off(dstr);
        }
        else {
            /* Special case - not normally malloced for some reason */
            if (isGV_with_GP(sstr)) {
                /* Don't need to do anything here.  */
            }
-           else if ((SvREADONLY(sstr) && SvFAKE(sstr))) {
+           else if ((SvIsCOW(sstr))) {
                /* A "shared" PV - clone it as "shared" PV */
                SvPV_set(dstr,
                         HEK_KEY(hek_dup(SvSHARED_HEK_FROM_PV(SvPVX_const(sstr)),
@@ -11862,7 +12010,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
     dstr->sv_debug_inpad = sstr->sv_debug_inpad;
     dstr->sv_debug_parent = (SV*)sstr;
     FREE_SV_DEBUG_FILE(dstr);
-    dstr->sv_debug_file = savepv(sstr->sv_debug_file);
+    dstr->sv_debug_file = savesharedpv(sstr->sv_debug_file);
 #endif
 
     ptr_table_store(PL_ptr_table, sstr, dstr);
@@ -11950,6 +12098,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
 
            if (sv_type != SVt_PVAV && sv_type != SVt_PVHV
                && !isGV_with_GP(dstr)
+               && !isREGEXP(dstr)
                && !(sv_type == SVt_PVIO && !(IoFLAGS(dstr) & IOf_FAKE_DIRP)))
                Perl_rvpv_dup(aTHX_ dstr, sstr, param);
 
@@ -11963,8 +12112,9 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                    SvOURSTASH_set(dstr, hv_dup_inc(SvOURSTASH(dstr), param));
                } else if (SvMAGIC(dstr))
                    SvMAGIC_set(dstr, mg_dup(SvMAGIC(dstr), param));
-               if (SvSTASH(dstr))
+               if (SvOBJECT(dstr) && SvSTASH(dstr))
                    SvSTASH_set(dstr, hv_dup_inc(SvSTASH(dstr), param));
+               else SvSTASH_set(dstr, 0); /* don't copy DESTROY cache */
            }
 
            /* The cast silences a GCC warning about unhandled types.  */
@@ -11978,7 +12128,9 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
            case SVt_PVMG:
                break;
            case SVt_REGEXP:
+             duprex:
                /* FIXME for plugins */
+               dstr->sv_u.svu_rx = ((REGEXP *)dstr)->sv_any;
                re_dup_guts((REGEXP*) sstr, (REGEXP*) dstr, param);
                break;
            case SVt_PVLV:
@@ -11989,6 +12141,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                    LvTARG(dstr) = MUTABLE_SV(he_dup((HE*)LvTARG(dstr), 0, param));
                else
                    LvTARG(dstr) = sv_dup_inc(LvTARG(dstr), param);
+               if (isREGEXP(sstr)) goto duprex;
            case SVt_PVGV:
                /* non-GP case already handled above */
                if(isGV_with_GP(sstr)) {
@@ -12444,6 +12597,7 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
        TOPUV(nss,ix) = uv;
        switch (type) {
        case SAVEt_CLEARSV:
+       case SAVEt_CLEARPADRANGE:
            break;
        case SAVEt_HELEM:               /* hash element */
            sv = (const SV *)POPPTR(ss,ix);
@@ -12473,6 +12627,14 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = svp_dup_inc((SV**)ptr, proto_perl);/* XXXXX */
            break;
+        case SAVEt_GVSLOT:             /* any slot in GV */
+           sv = (const SV *)POPPTR(ss,ix);
+           TOPPTR(nss,ix) = sv_dup_inc(sv, param);
+           ptr = POPPTR(ss,ix);
+           TOPPTR(nss,ix) = svp_dup_inc((SV**)ptr, proto_perl);/* XXXXX */
+           sv = (const SV *)POPPTR(ss,ix);
+           TOPPTR(nss,ix) = sv_dup_inc(sv, param);
+           break;
         case SAVEt_HV:                         /* hash reference */
         case SAVEt_AV:                         /* array reference */
            sv = (const SV *) POPPTR(ss,ix);
@@ -12660,7 +12822,7 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
                    = pv_dup(old_state->re_state_bostr);
                new_state->re_state_regeol
                    = pv_dup(old_state->re_state_regeol);
-#ifdef PERL_OLD_COPY_ON_WRITE
+#ifdef PERL_ANY_COW
                new_state->re_state_nrs
                    = sv_dup(old_state->re_state_nrs, param);
 #endif
@@ -12866,6 +13028,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_Proc            = ipP;
 #endif         /* PERL_IMPLICIT_SYS */
 
+
     param->flags = flags;
     /* Nothing in the core code uses this, but we make it available to
        extensions (using mg_dup).  */
@@ -12875,6 +13038,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     param->new_perl = my_perl;
     param->unreferenced = NULL;
 
+
     INIT_TRACK_MEMPOOL(my_perl->Imemory_debug_header, my_perl);
 
     PL_body_arenas = NULL;
@@ -12887,9 +13051,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_debug           = proto_perl->Idebug;
 
-    PL_hash_seed       = proto_perl->Ihash_seed;
-    PL_rehash_seed     = proto_perl->Irehash_seed;
-
     /* dbargs array probably holds garbage */
     PL_dbargs          = NULL;
 
@@ -12899,9 +13060,14 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_origargc                = proto_perl->Iorigargc;
     PL_origargv                = proto_perl->Iorigargv;
 
+#if !NO_TAINT_SUPPORT
     /* Set tainting stuff before PerlIO_debug can possibly get called */
     PL_tainting                = proto_perl->Itainting;
     PL_taint_warn      = proto_perl->Itaint_warn;
+#else
+    PL_tainting         = FALSE;
+    PL_taint_warn      = FALSE;
+#endif
 
     PL_minus_c         = proto_perl->Iminus_c;
 
@@ -12915,7 +13081,9 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_minus_F         = proto_perl->Iminus_F;
     PL_doswitches      = proto_perl->Idoswitches;
     PL_dowarn          = proto_perl->Idowarn;
+#ifdef PERL_SAWAMPERSAND
     PL_sawampersand    = proto_perl->Isawampersand;
+#endif
     PL_unsafe          = proto_perl->Iunsafe;
     PL_perldb          = proto_perl->Iperldb;
     PL_perl_destruct_level = proto_perl->Iperl_destruct_level;
@@ -13074,7 +13242,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_timesbuf                = proto_perl->Itimesbuf;
 #endif
 
+#if !NO_TAINT_SUPPORT
     PL_tainted         = proto_perl->Itainted;
+#else
+    PL_tainted          = FALSE;
+#endif
     PL_curpm           = proto_perl->Icurpm;   /* XXX No PMOP ref count */
 
     PL_chopset         = proto_perl->Ichopset; /* XXX never deallocated */
@@ -13376,15 +13548,12 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     /* utf8 character class swashes */
     PL_utf8_alnum      = sv_dup_inc(proto_perl->Iutf8_alnum, param);
     PL_utf8_alpha      = sv_dup_inc(proto_perl->Iutf8_alpha, param);
-    PL_utf8_blank      = sv_dup_inc(proto_perl->Iutf8_blank, param);
-    PL_utf8_space      = sv_dup_inc(proto_perl->Iutf8_space, param);
     PL_utf8_graph      = sv_dup_inc(proto_perl->Iutf8_graph, param);
     PL_utf8_digit      = sv_dup_inc(proto_perl->Iutf8_digit, param);
     PL_utf8_upper      = sv_dup_inc(proto_perl->Iutf8_upper, param);
     PL_utf8_lower      = sv_dup_inc(proto_perl->Iutf8_lower, param);
     PL_utf8_print      = sv_dup_inc(proto_perl->Iutf8_print, param);
     PL_utf8_punct      = sv_dup_inc(proto_perl->Iutf8_punct, param);
-    PL_utf8_xdigit     = sv_dup_inc(proto_perl->Iutf8_xdigit, param);
     PL_utf8_mark       = sv_dup_inc(proto_perl->Iutf8_mark, param);
     PL_utf8_X_regular_begin    = sv_dup_inc(proto_perl->Iutf8_X_regular_begin, param);
     PL_utf8_X_extend   = sv_dup_inc(proto_perl->Iutf8_X_extend, param);
@@ -13399,6 +13568,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_utf8_idcont     = sv_dup_inc(proto_perl->Iutf8_idcont, param);
     PL_utf8_xidcont    = sv_dup_inc(proto_perl->Iutf8_xidcont, param);
     PL_utf8_foldable   = sv_dup_inc(proto_perl->Iutf8_foldable, param);
+    PL_utf8_charname_begin = sv_dup_inc(proto_perl->Iutf8_charname_begin, param);
+    PL_utf8_charname_continue = sv_dup_inc(proto_perl->Iutf8_charname_continue, param);
     PL_ASCII           = sv_dup_inc(proto_perl->IASCII, param);
     PL_AboveLatin1     = sv_dup_inc(proto_perl->IAboveLatin1, param);
     PL_Latin1          = sv_dup_inc(proto_perl->ILatin1, param);
@@ -13445,6 +13616,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        Newxz(PL_scopestack_name, PL_scopestack_max, const char *);
        Copy(proto_perl->Iscopestack_name, PL_scopestack_name, PL_scopestack_ix, const char *);
 #endif
+        /* reset stack AV to correct length before its duped via
+         * PL_curstackinfo */
+        AvFILLp(proto_perl->Icurstack) =
+                            proto_perl->Istack_sp - proto_perl->Istack_base;
+
        /* NOTE: si_dup() looks at PL_markstack */
        PL_curstackinfo         = si_dup(proto_perl->Icurstackinfo, param);
 
@@ -13983,8 +14159,16 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
     case OP_PADAV:
     case OP_PADHV:
       {
-       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);
+       const bool pad  = (    obase->op_type == OP_PADAV
+                            || obase->op_type == OP_PADHV
+                            || obase->op_type == OP_PADRANGE
+                          );
+
+       const bool hash = (    obase->op_type == OP_PADHV
+                            || obase->op_type == OP_RV2HV
+                            || (obase->op_type == OP_PADRANGE
+                                && SvTYPE(PAD_SVl(obase->op_targ)) == SVt_PVHV)
+                          );
        I32 index = 0;
        SV *keysv = NULL;
        int subscript_type = FUV_SUBSCRIPT_WITHIN;
@@ -14190,7 +14374,9 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
 
     case OP_OPEN:
        o = cUNOPx(obase)->op_first;
-       if (o->op_type == OP_PUSHMARK)
+       if (   o->op_type == OP_PUSHMARK
+          || (o->op_type == OP_NULL && o->op_targ == OP_PUSHMARK)
+        )
            o = o->op_sibling;
 
        if (!o->op_sibling) {
@@ -14234,7 +14420,10 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
        match = 1; /* print etc can return undef on defined args */
        /* skip filehandle as it can't produce 'undef' warning  */
        o = cUNOPx(obase)->op_first;
-       if ((obase->op_flags & OPf_STACKED) && o->op_type == OP_PUSHMARK)
+       if ((obase->op_flags & OPf_STACKED)
+            &&
+               (   o->op_type == OP_PUSHMARK
+               || (o->op_type == OP_NULL && o->op_targ == OP_PUSHMARK)))
            o = o->op_sibling->op_sibling;
        goto do_op2;
 
@@ -14362,6 +14551,8 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
         * left that is not skipped, then we *know* it is responsible for
         * the uninitialized value.  If there is more than one op left, we
         * have to look for an exact match in the while() loop below.
+         * Note that we skip padrange, because the individual pad ops that
+         * it replaced are still in the tree, so we work on them instead.
         */
        o2 = NULL;
        for (kid=o; kid; kid = kid->op_sibling) {
@@ -14370,6 +14561,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
                if ( (type == OP_CONST && SvOK(cSVOPx_sv(kid)))
                  || (type == OP_NULL  && ! (kid->op_flags & OPf_KIDS))
                  || (type == OP_PUSHMARK)
+                 || (type == OP_PADRANGE)
                )
                continue;
            }