This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix threaded build broken by 823ac2c80
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index a2d0cbc..2cb036e 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -477,7 +477,7 @@ do_clean_objs(pTHX_ SV *const ref)
            } else {
                SvROK_off(ref);
                SvRV_set(ref, NULL);
-               SvREFCNT_dec(target);
+               SvREFCNT_dec_NN(target);
            }
        }
     }
@@ -505,27 +505,27 @@ do_clean_named_objs(pTHX_ SV *const sv)
        DEBUG_D((PerlIO_printf(Perl_debug_log,
                "Cleaning named glob SV object:\n "), sv_dump(obj)));
        GvSV(sv) = NULL;
-       SvREFCNT_dec(obj);
+       SvREFCNT_dec_NN(obj);
     }
     if ( ((obj = MUTABLE_SV(GvAV(sv)) )) && SvOBJECT(obj)) {
        DEBUG_D((PerlIO_printf(Perl_debug_log,
                "Cleaning named glob AV object:\n "), sv_dump(obj)));
        GvAV(sv) = NULL;
-       SvREFCNT_dec(obj);
+       SvREFCNT_dec_NN(obj);
     }
     if ( ((obj = MUTABLE_SV(GvHV(sv)) )) && SvOBJECT(obj)) {
        DEBUG_D((PerlIO_printf(Perl_debug_log,
                "Cleaning named glob HV object:\n "), sv_dump(obj)));
        GvHV(sv) = NULL;
-       SvREFCNT_dec(obj);
+       SvREFCNT_dec_NN(obj);
     }
     if ( ((obj = MUTABLE_SV(GvCV(sv)) )) && SvOBJECT(obj)) {
        DEBUG_D((PerlIO_printf(Perl_debug_log,
                "Cleaning named glob CV object:\n "), sv_dump(obj)));
        GvCV_set(sv, NULL);
-       SvREFCNT_dec(obj);
+       SvREFCNT_dec_NN(obj);
     }
-    SvREFCNT_dec(sv); /* undo the inc above */
+    SvREFCNT_dec_NN(sv); /* undo the inc above */
 }
 
 /* clear any IO slots in a GV which hold objects (except stderr, defout);
@@ -546,9 +546,9 @@ do_clean_named_io_objs(pTHX_ SV *const sv)
        DEBUG_D((PerlIO_printf(Perl_debug_log,
                "Cleaning named glob IO object:\n "), sv_dump(obj)));
        GvIOp(sv) = NULL;
-       SvREFCNT_dec(obj);
+       SvREFCNT_dec_NN(obj);
     }
-    SvREFCNT_dec(sv); /* undo the inc above */
+    SvREFCNT_dec_NN(sv); /* undo the inc above */
 }
 
 /* Void wrapper to pass to visit() */
@@ -607,7 +607,7 @@ do_clean_all(pTHX_ SV *const sv)
     }
     DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning loops: SV at 0x%"UVxf"\n", PTR2UV(sv)) ));
     SvFLAGS(sv) |= SVf_BREAK;
-    SvREFCNT_dec(sv);
+    SvREFCNT_dec_NN(sv);
 }
 
 /*
@@ -881,11 +881,6 @@ static const struct body_details bodies_by_type[] = {
     /* HEs use this offset for their arena.  */
     { 0, 0, 0, SVt_NULL, FALSE, NONV, NOARENA, 0 },
 
-    /* The bind placeholder pretends to be an RV for now.
-       Also it's marked as "can't upgrade" to stop anyone using it before it's
-       implemented.  */
-    { 0, 0, 0, SVt_BIND, TRUE, NONV, NOARENA, 0 },
-
     /* IVs are in the head, so the allocation size is 0.  */
     { 0,
       sizeof(IV), /* This is used to copy out the IV body.  */
@@ -903,6 +898,12 @@ static const struct body_details bodies_by_type[] = {
       SVt_PV, FALSE, NONV, HASARENA,
       FIT_ARENA(0, sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur)) },
 
+    { sizeof(XINVLIST) - STRUCT_OFFSET(XPV, xpv_cur),
+      copy_length(XINVLIST, is_offset) - STRUCT_OFFSET(XPV, xpv_cur),
+      + STRUCT_OFFSET(XPV, xpv_cur),
+      SVt_INVLIST, TRUE, NONV, HASARENA,
+      FIT_ARENA(0, sizeof(XINVLIST) - STRUCT_OFFSET(XPV, xpv_cur)) },
+
     { sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur),
       copy_length(XPVIV, xiv_u) - STRUCT_OFFSET(XPV, xpv_cur),
       + STRUCT_OFFSET(XPV, xpv_cur),
@@ -921,7 +922,7 @@ static const struct body_details bodies_by_type[] = {
     { sizeof(regexp),
       sizeof(regexp),
       0,
-      SVt_REGEXP, FALSE, NONV, HASARENA,
+      SVt_REGEXP, TRUE, NONV, HASARENA,
       FIT_ARENA(0, sizeof(regexp))
     },
 
@@ -1246,12 +1247,12 @@ Perl_sv_upgrade(pTHX_ SV *const sv, svtype new_type)
        assert(!SvPAD_TYPED(sv));
        break;
     default:
-       if (old_type_details->cant_upgrade)
+       if (UNLIKELY(old_type_details->cant_upgrade))
            Perl_croak(aTHX_ "Can't upgrade %s (%" UVuf ") to %" UVuf,
                       sv_reftype(sv, 0), (UV) old_type, (UV) new_type);
     }
 
-    if (old_type > new_type)
+    if (UNLIKELY(old_type > new_type))
        Perl_croak(aTHX_ "sv_upgrade from type %d down to type %d",
                (int)old_type, (int)new_type);
 
@@ -1308,7 +1309,8 @@ Perl_sv_upgrade(pTHX_ SV *const sv, svtype new_type)
 #ifndef NODEFAULT_SHAREKEYS
            HvSHAREKEYS_on(sv);         /* key-sharing on by default */
 #endif
-           HvMAX(sv) = 7; /* (start with 8 buckets) */
+            /* start with PERL_HASH_DEFAULT_HvMAX+1 buckets: */
+           HvMAX(sv) = PERL_HASH_DEFAULT_HvMAX;
        }
 
        /* SVt_NULL isn't the only thing upgraded to AV or HV.
@@ -1339,6 +1341,7 @@ Perl_sv_upgrade(pTHX_ SV *const sv, svtype new_type)
     case SVt_PVGV:
     case SVt_PVCV:
     case SVt_PVLV:
+    case SVt_INVLIST:
     case SVt_REGEXP:
     case SVt_PVMG:
     case SVt_PVNV:
@@ -1386,7 +1389,7 @@ Perl_sv_upgrade(pTHX_ SV *const sv, svtype new_type)
            SvNV_set(sv, 0);
 #endif
 
-       if (new_type == SVt_PVIO) {
+       if (UNLIKELY(new_type == SVt_PVIO)) {
            IO * const io = MUTABLE_IO(sv);
            GV *iogv = gv_fetchpvs("IO::File::", GV_ADD, SVt_PVHV);
 
@@ -1399,7 +1402,7 @@ Perl_sv_upgrade(pTHX_ SV *const sv, svtype new_type)
            SvSTASH_set(io, MUTABLE_HV(SvREFCNT_inc(GvHV(iogv))));
            IoPAGE_LEN(sv) = 60;
        }
-       if (new_type == SVt_REGEXP)
+       if (UNLIKELY(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
@@ -1474,10 +1477,6 @@ Perl_sv_grow(pTHX_ SV *const sv, STRLEN newlen)
 
     PERL_ARGS_ASSERT_SV_GROW;
 
-    if (PL_madskills && newlen >= 0x100000) {
-       PerlIO_printf(Perl_debug_log,
-                     "Allocation too large: %"UVxf"\n", (UV)newlen);
-    }
 #ifdef HAS_64K_LIMIT
     if (newlen >= 0x10000) {
        PerlIO_printf(Perl_debug_log,
@@ -1507,6 +1506,18 @@ Perl_sv_grow(pTHX_ SV *const sv, STRLEN newlen)
        s = SvPVX_mutable(sv);
     }
 
+#ifdef PERL_NEW_COPY_ON_WRITE
+    /* the new COW scheme uses SvPVX(sv)[SvLEN(sv)-1] (if spare)
+     * to store the COW count. So in general, allocate one more byte than
+     * asked for, to make it likely this byte is always spare: and thus
+     * make more strings COW-able.
+     * If the new size is a big power of two, don't bother: we assume the
+     * caller wanted a nice 2^N sized block and will be annoyed at getting
+     * 2^N+1 */
+    if (newlen & 0xff)
+        newlen++;
+#endif
+
     if (newlen > SvLEN(sv)) {          /* need more room? */
        STRLEN minlen = SvCUR(sv);
        minlen += (minlen >> PERL_STRLEN_EXPAND_SHIFT) + 10;
@@ -2262,6 +2273,9 @@ Perl_sv_2iv_flags(pTHX_ SV *const sv, const I32 flags)
     if (!sv)
        return 0;
 
+    assert (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV
+        && SvTYPE(sv) != SVt_PVFM);
+
     if (SvGMAGICAL(sv) && (flags & SV_GMAGIC))
        mg_get(sv);
 
@@ -2436,6 +2450,8 @@ Perl_sv_2nv_flags(pTHX_ SV *const sv, const I32 flags)
     dVAR;
     if (!sv)
        return 0.0;
+    assert (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV
+        && SvTYPE(sv) != SVt_PVFM);
     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.
@@ -2741,6 +2757,8 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
            *lp = 0;
        return (char *)"";
     }
+    assert (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV
+        && SvTYPE(sv) != SVt_PVFM);
     if (SvGMAGICAL(sv) && (flags & SV_GMAGIC))
        mg_get(sv);
     if (SvROK(sv)) {
@@ -2894,6 +2912,7 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
        Move(ptr, s, len, char);
        s += len;
        *s = '\0';
+        SvPOK_on(sv);
     }
     else if (SvNOK(sv)) {
        if (SvTYPE(sv) < SVt_PVNV)
@@ -2907,7 +2926,43 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
            /* The +20 is pure guesswork.  Configure test needed. --jhi */
            s = SvGROW_mutable(sv, NV_DIG + 20);
            /* some Xenix systems wipe out errno here */
-           Gconvert(SvNVX(sv), NV_DIG, 0, s);
+
+#ifndef USE_LOCALE_NUMERIC
+            Gconvert(SvNVX(sv), NV_DIG, 0, s);
+            SvPOK_on(sv);
+#else
+            /* Gconvert always uses the current locale.  That's the right thing
+             * to do if we're supposed to be using locales.  But otherwise, we
+             * want the result to be based on the C locale, so we need to
+             * change to the C locale during the Gconvert and then change back.
+             * But if we're already in the C locale (PL_numeric_standard is
+             * TRUE in that case), no need to do any changing */
+            if (PL_numeric_standard || IN_SOME_LOCALE_FORM_RUNTIME) {
+                Gconvert(SvNVX(sv), NV_DIG, 0, s);
+
+                /* If the radix character is UTF-8, and actually is in the
+                 * output, turn on the UTF-8 flag for the scalar */
+                if (! PL_numeric_standard
+                    && PL_numeric_radix_sv && SvUTF8(PL_numeric_radix_sv)
+                    && instr(s, SvPVX_const(PL_numeric_radix_sv)))
+                {
+                    SvUTF8_on(sv);
+                }
+            }
+            else {
+                char *loc = savepv(setlocale(LC_NUMERIC, NULL));
+                setlocale(LC_NUMERIC, "C");
+                Gconvert(SvNVX(sv), NV_DIG, 0, s);
+                setlocale(LC_NUMERIC, loc);
+                Safefree(loc);
+
+            }
+
+            /* We don't call SvPOK_on(), because it may come to pass that the
+             * locale changes so that the stringification we just did is no
+             * longer correct.  We will have to re-stringify every time it is
+             * needed */
+#endif
            RESTORE_ERRNO;
            while (*s) s++;
        }
@@ -2952,7 +3007,6 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
            *lp = len;
        SvCUR_set(sv, len);
     }
-    SvPOK_on(sv);
     DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2pv(%s)\n",
                          PTR2UV(sv),SvPVX_const(sv)));
     if (flags & SV_CONST_RETURN)
@@ -3028,13 +3082,13 @@ Perl_sv_2pvbyte(pTHX_ SV *sv, STRLEN *const lp)
 {
     PERL_ARGS_ASSERT_SV_2PVBYTE;
 
+    SvGETMAGIC(sv);
     if (((SvREADONLY(sv) || SvFAKE(sv)) && !SvIsCOW(sv))
      || isGV_with_GP(sv) || SvROK(sv)) {
        SV *sv2 = sv_newmortal();
-       sv_copypv(sv2,sv);
+       sv_copypv_nomg(sv2,sv);
        sv = sv2;
     }
-    else SvGETMAGIC(sv);
     sv_utf8_downgrade(sv,0);
     return lp ? SvPV_nomg(sv,*lp) : SvPV_nomg_nolen(sv);
 }
@@ -3101,6 +3155,9 @@ Perl_sv_2bool_flags(pTHX_ SV *const sv, const I32 flags)
        }
        return SvRV(sv) != 0;
     }
+    if (isREGEXP(sv))
+       return
+         RX_WRAPLEN(sv) > 1 || (RX_WRAPLEN(sv) && *RX_WRAPPED(sv) != '0');
     return SvTRUE_common(sv, isGV_with_GP(sv) ? 1 : 0);
 }
 
@@ -3169,6 +3226,8 @@ especially if it could return the position of the first one.
 
 */
 
+static void S_sv_uncow(pTHX_ SV * const sv, const U32 flags);
+
 STRLEN
 Perl_sv_utf8_upgrade_flags_grow(pTHX_ SV *const sv, const I32 flags, STRLEN extra)
 {
@@ -3197,7 +3256,7 @@ Perl_sv_utf8_upgrade_flags_grow(pTHX_ SV *const sv, const I32 flags, STRLEN extr
     }
 
     if (SvIsCOW(sv)) {
-        sv_force_normal_flags(sv, 0);
+        S_sv_uncow(aTHX_ sv, 0);
     }
 
     if (PL_encoding && !(flags & SV_UTF8_NO_ENCODING)) {
@@ -3456,7 +3515,7 @@ Perl_sv_utf8_downgrade(pTHX_ SV *const sv, const bool fail_ok)
            int mg_flags = SV_GMAGIC;
 
             if (SvIsCOW(sv)) {
-                sv_force_normal_flags(sv, 0);
+                S_sv_uncow(aTHX_ sv, 0);
             }
            if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
                /* update pos */
@@ -3734,6 +3793,15 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
            );
     }
     else if(mro_changes) mro_method_changed_in(GvSTASH(dstr));
+    if (GvIO(dstr) && dtype == SVt_PVGV) {
+       DEBUG_o(Perl_deb(aTHX_
+                       "glob_assign_glob clearing PL_stashcache\n"));
+       /* It's a cache. It will rebuild itself quite happily.
+          It's a lot of effort to work out exactly which key (or keys)
+          might be invalidated by the creation of the this file handle.
+        */
+       hv_clear(PL_stashcache);
+    }
     return;
 }
 
@@ -3787,7 +3855,24 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
                    GvCVGEN(dstr) = 0; /* Switch off cacheness. */
                }
            }
-           SAVEGENERICSV(*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))) {
@@ -3823,7 +3908,7 @@ 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 = SvREFCNT_inc_simple_NN(sref);
        if (import_flag && !(GvFLAGS(dstr) & import_flag)
@@ -4056,7 +4141,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags)
        }
        break;
 
-       /* case SVt_BIND: */
+       case SVt_INVLIST:
     case SVt_PVLV:
     case SVt_PVGV:
     case SVt_PVMG:
@@ -4258,7 +4343,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags)
                ? (!((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 && len
 # else
                     && !(SvFLAGS(dstr) & SVf_BREAK)
                     && !(sflags & SVf_IsCOW)
@@ -4636,7 +4721,7 @@ Perl_sv_sethek(pTHX_ SV *const sv, const HEK *const hek)
         {
            SV_CHECK_THINKFIRST_COW_DROP(sv);
            SvUPGRADE(sv, SVt_PV);
-           Safefree(SvPVX(sv));
+           SvPV_free(sv);
            SvPV_set(sv,(char *)HEK_KEY(share_hek_hek(hek)));
            SvCUR_set(sv, HEK_LEN(hek));
            SvLEN_set(sv, 0);
@@ -4791,19 +4876,14 @@ with flags set to 0.
 =cut
 */
 
-void
-Perl_sv_force_normal_flags(pTHX_ SV *const sv, const U32 flags)
+static void
+S_sv_uncow(pTHX_ SV * const sv, const U32 flags)
 {
     dVAR;
 
-    PERL_ARGS_ASSERT_SV_FORCE_NORMAL_FLAGS;
-
+    assert(SvIsCOW(sv));
+    {
 #ifdef PERL_ANY_COW
-    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 = SvLEN(sv);
        const STRLEN cur = SvCUR(sv);
@@ -4856,14 +4936,7 @@ Perl_sv_force_normal_flags(pTHX_ SV *const sv, const U32 flags)
                 sv_dump(sv);
             }
        }
-    }
 #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);
            SvIsCOW_off(sv);
@@ -4878,8 +4951,19 @@ Perl_sv_force_normal_flags(pTHX_ SV *const sv, const U32 flags)
                *SvEND(sv) = '\0';
            }
            unshare_hek(SvSHARED_HEK_FROM_PV(pvx));
-       }
 #endif
+    }
+}
+
+void
+Perl_sv_force_normal_flags(pTHX_ SV *const sv, const U32 flags)
+{
+    PERL_ARGS_ASSERT_SV_FORCE_NORMAL_FLAGS;
+
+    if (SvREADONLY(sv))
+       Perl_croak_no_modify();
+    else if (SvIsCOW(sv))
+       S_sv_uncow(aTHX_ sv, flags);
     if (SvROK(sv))
        sv_unref_flags(sv, flags);
     else if (SvFAKE(sv) && isGV_with_GP(sv))
@@ -4931,7 +5015,7 @@ Perl_sv_force_normal_flags(pTHX_ SV *const sv, const U32 flags)
        SvANY(temp) = temp_p;
        temp->sv_u.svu_rx = (regexp *)temp_p;
 
-       SvREFCNT_dec(temp);
+       SvREFCNT_dec_NN(temp);
     }
     else if (SvVOK(sv)) sv_unmagic(sv, PERL_MAGIC_vstring);
 }
@@ -5014,8 +5098,14 @@ Perl_sv_chop(pTHX_ SV *const sv, const char *const ptr)
     evacp = p - evacn;
 #endif
 
+    /* This sets 'delta' to the accumulated value of all deltas so far */
     delta += old_delta;
     assert(delta);
+
+    /* If 'delta' fits in a byte, store it just prior to the new beginning of
+     * the string; otherwise store a 0 byte there and store 'delta' just prior
+     * to that, using as many bytes as a STRLEN occupies.  Thus it overwrites a
+     * portion of the chopped part of the string */
     if (delta < 0x100) {
        *--p = (U8) delta;
     } else {
@@ -5272,6 +5362,8 @@ Perl_sv_magicext(pTHX_ SV *const sv, SV *const obj, const int how,
 
     PERL_ARGS_ASSERT_SV_MAGICEXT;
 
+    if (SvTYPE(sv)==SVt_PVAV) { assert (!AvPAD_NAMELIST(sv)); }
+
     SvUPGRADE(sv, SVt_PVMG);
     Newxz(mg, 1, MAGIC);
     mg->mg_moremagic = SvMAGIC(sv);
@@ -5335,6 +5427,24 @@ Perl_sv_magicext(pTHX_ SV *const sv, SV *const obj, const int how,
     return mg;
 }
 
+MAGIC *
+Perl_sv_magicext_mglob(pTHX_ SV *sv)
+{
+    PERL_ARGS_ASSERT_SV_MAGICEXT_MGLOB;
+    if (SvTYPE(sv) == SVt_PVLV && LvTYPE(sv) == 'y') {
+       /* This sv is only a delegate.  //g magic must be attached to
+          its target. */
+       vivify_defelem(sv);
+       sv = LvTARG(sv);
+    }
+#ifdef PERL_OLD_COPY_ON_WRITE
+    if (SvIsCOW(sv))
+       sv_force_normal_flags(sv, 0);
+#endif
+    return sv_magicext(sv, NULL, PERL_MAGIC_regex_global,
+                      &PL_vtbl_mglob, 0, 0);
+}
+
 /*
 =for apidoc sv_magic
 
@@ -5377,17 +5487,13 @@ Perl_sv_magic(pTHX_ SV *const sv, SV *const obj, const int how,
     vtable = (vtable_index == magic_vtable_max)
        ? NULL : PL_magic_vtables + vtable_index;
 
-#ifdef PERL_ANY_COW
+#ifdef PERL_OLD_COPY_ON_WRITE
     if (SvIsCOW(sv))
         sv_force_normal_flags(sv, 0);
 #endif
     if (SvREADONLY(sv)) {
        if (
-           /* its okay to attach magic to shared strings */
-           !SvIsCOW(sv)
-
-           && IN_PERL_RUNTIME
-           && !PERL_MAGIC_TYPE_READONLY_ACCEPTABLE(how)
+           !PERL_MAGIC_TYPE_READONLY_ACCEPTABLE(how)
           )
        {
            Perl_croak_no_modify();
@@ -5522,7 +5628,7 @@ Perl_sv_rvweaken(pTHX_ SV *const sv)
     tsv = SvRV(sv);
     Perl_sv_add_backref(aTHX_ tsv, sv);
     SvWEAKREF_on(sv);
-    SvREFCNT_dec(tsv);
+    SvREFCNT_dec_NN(tsv);
     return sv;
 }
 
@@ -5818,7 +5924,7 @@ Perl_sv_kill_backrefs(pTHX_ SV *const sv, AV *const av)
     }
     if (is_array) {
        AvFILLp(av) = -1;
-       SvREFCNT_dec(av); /* remove extra count added by sv_add_backref() */
+       SvREFCNT_dec_NN(av); /* remove extra count added by sv_add_backref() */
     }
     return;
 }
@@ -6035,7 +6141,7 @@ S_anonymise_cv_maybe(pTHX_ GV *gv, CV* cv)
                     : newSVpvn_flags( "__ANON__", 8, 0 );
     sv_catpvs(gvname, "::__ANON__");
     anongv = gv_fetchsv(gvname, GV_ADDMULTI, SVt_PVCV);
-    SvREFCNT_dec(gvname);
+    SvREFCNT_dec_NN(gvname);
 
     CvANON_on(cv);
     CvCVGV_RC_on(cv);
@@ -6109,6 +6215,9 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
            }
            else if (type == SVt_PVMG && SvPAD_OUR(sv)) {
                SvREFCNT_dec(SvOURSTASH(sv));
+           }
+           else if (type == SVt_PVAV && AvPAD_NAMELIST(sv)) {
+               assert(!SvMAGICAL(sv));
            } else if (SvMAGIC(sv)) {
                /* Free back-references before other types of magic. */
                sv_unmagic(sv, PERL_MAGIC_backref);
@@ -6119,7 +6228,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                SvREFCNT_dec(SvSTASH(sv));
        }
        switch (type) {
-           /* case SVt_BIND: */
+           /* case SVt_INVLIST: */
        case SVt_PVIO:
            if (IoIFP(sv) &&
                IoIFP(sv) != PerlIO_stdin() &&
@@ -6240,9 +6349,12 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                PL_last_in_gv = NULL;
            else if ((const GV *)sv == PL_statgv)
                PL_statgv = NULL;
+            else if ((const GV *)sv == PL_stderrgv)
+                PL_stderrgv = NULL;
        case SVt_PVMG:
        case SVt_PVNV:
        case SVt_PVIV:
+       case SVt_INVLIST:
        case SVt_PV:
          freescalar:
            /* Don't bother with SvOOK_off(sv); as we're only going to
@@ -6392,9 +6504,9 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                continue;
            }
 #endif
-           if (SvREADONLY(sv) && SvIMMORTAL(sv)) {
+           if (SvIMMORTAL(sv)) {
                /* make sure SvREFCNT(sv)==0 happens very seldom */
-               SvREFCNT(sv) = (~(U32)0)/2;
+               SvREFCNT(sv) = SvREFCNT_IMMORTAL;
                continue;
            }
            break;
@@ -6471,7 +6583,7 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
                    SvRV_set(tmpref, NULL);
                    SvROK_off(tmpref);
                }
-               SvREFCNT_dec(tmpref);
+               SvREFCNT_dec_NN(tmpref);
            }
          }
        } while (SvOBJECT(sv) && SvSTASH(sv) != stash);
@@ -6494,8 +6606,6 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
        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 */
     }
     return TRUE;
 }
@@ -6532,76 +6642,85 @@ Normally called via a wrapper macro C<SvREFCNT_dec>.
 void
 Perl_sv_free(pTHX_ SV *const sv)
 {
-    dVAR;
-    if (!sv)
-       return;
-    if (SvREFCNT(sv) == 0) {
-       if (SvFLAGS(sv) & SVf_BREAK)
-           /* this SV's refcnt has been artificially decremented to
-            * trigger cleanup */
-           return;
-       if (PL_in_clean_all) /* All is fair */
-           return;
-       if (SvREADONLY(sv) && SvIMMORTAL(sv)) {
-           /* make sure SvREFCNT(sv)==0 happens very seldom */
-           SvREFCNT(sv) = (~(U32)0)/2;
-           return;
-       }
-       if (ckWARN_d(WARN_INTERNAL)) {
-#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
-           Perl_dump_sv_child(aTHX_ sv);
-#else
-  #ifdef DEBUG_LEAKING_SCALARS
-           sv_dump(sv);
-  #endif
-#ifdef DEBUG_LEAKING_SCALARS_ABORT
-           if (PL_warnhook == PERL_WARNHOOK_FATAL
-               || ckDEAD(packWARN(WARN_INTERNAL))) {
-               /* Don't let Perl_warner cause us to escape our fate:  */
-               abort();
-           }
-#endif
-           /* This may not return:  */
-           Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
-                        "Attempt to free unreferenced scalar: SV 0x%"UVxf
-                        pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE);
-#endif
-       }
-#ifdef DEBUG_LEAKING_SCALARS_ABORT
-       abort();
-#endif
-       return;
-    }
-    if (--(SvREFCNT(sv)) > 0)
-       return;
-    Perl_sv_free2(aTHX_ sv);
+    SvREFCNT_dec(sv);
 }
 
+
+/* Private helper function for SvREFCNT_dec().
+ * Called with rc set to original SvREFCNT(sv), where rc == 0 or 1 */
+
 void
-Perl_sv_free2(pTHX_ SV *const sv)
+Perl_sv_free2(pTHX_ SV *const sv, const U32 rc)
 {
     dVAR;
 
     PERL_ARGS_ASSERT_SV_FREE2;
 
+    if (LIKELY( rc == 1 )) {
+        /* normal case */
+        SvREFCNT(sv) = 0;
+
 #ifdef DEBUGGING
-    if (SvTEMP(sv)) {
-       Perl_ck_warner_d(aTHX_ packWARN(WARN_DEBUGGING),
-                        "Attempt to free temp prematurely: SV 0x%"UVxf
-                        pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE);
-       return;
+        if (SvTEMP(sv)) {
+            Perl_ck_warner_d(aTHX_ packWARN(WARN_DEBUGGING),
+                             "Attempt to free temp prematurely: SV 0x%"UVxf
+                             pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE);
+            return;
+        }
+#endif
+        if (SvIMMORTAL(sv)) {
+            /* make sure SvREFCNT(sv)==0 happens very seldom */
+            SvREFCNT(sv) = SvREFCNT_IMMORTAL;
+            return;
+        }
+        sv_clear(sv);
+        if (! SvREFCNT(sv)) /* may have have been resurrected */
+            del_SV(sv);
+        return;
+    }
+
+    /* handle exceptional cases */
+
+    assert(rc == 0);
+
+    if (SvFLAGS(sv) & SVf_BREAK)
+        /* this SV's refcnt has been artificially decremented to
+         * trigger cleanup */
+        return;
+    if (PL_in_clean_all) /* All is fair */
+        return;
+    if (SvIMMORTAL(sv)) {
+        /* make sure SvREFCNT(sv)==0 happens very seldom */
+        SvREFCNT(sv) = SvREFCNT_IMMORTAL;
+        return;
     }
+    if (ckWARN_d(WARN_INTERNAL)) {
+#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
+        Perl_dump_sv_child(aTHX_ sv);
+#else
+    #ifdef DEBUG_LEAKING_SCALARS
+        sv_dump(sv);
+    #endif
+#ifdef DEBUG_LEAKING_SCALARS_ABORT
+        if (PL_warnhook == PERL_WARNHOOK_FATAL
+            || ckDEAD(packWARN(WARN_INTERNAL))) {
+            /* Don't let Perl_warner cause us to escape our fate:  */
+            abort();
+        }
+#endif
+        /* This may not return:  */
+        Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
+                    "Attempt to free unreferenced scalar: SV 0x%"UVxf
+                    pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE);
 #endif
-    if (SvREADONLY(sv) && SvIMMORTAL(sv)) {
-       /* make sure SvREFCNT(sv)==0 happens very seldom */
-       SvREFCNT(sv) = (~(U32)0)/2;
-       return;
     }
-    sv_clear(sv);
-    if (! SvREFCNT(sv))
-       del_SV(sv);
+#ifdef DEBUG_LEAKING_SCALARS_ABORT
+    abort();
+#endif
+
 }
 
+
 /*
 =for apidoc sv_len
 
@@ -6872,7 +6991,7 @@ S_sv_pos_u2b_cached(pTHX_ SV *const sv, MAGIC **const mgp, const U8 *const start
 /*
 =for apidoc sv_pos_u2b_flags
 
-Converts the value pointed to by offsetp from a count of UTF-8 chars from
+Converts the offset from a count of UTF-8 chars from
 the start of the string, to a count of the equivalent number of bytes; if
 lenp is non-zero, it does the same to lenp, but this time starting from
 the offset, rather than from the start
@@ -6981,9 +7100,6 @@ S_utf8_mg_len_cache_update(pTHX_ SV *const sv, MAGIC **const mgp,
     assert(*mgp);
 
     (*mgp)->mg_len = ulen;
-    /* For now, treat "overflowed" as "still unknown". See RT #72924.  */
-    if (ulen != (STRLEN) (*mgp)->mg_len)
-       (*mgp)->mg_len = -1;
 }
 
 /* Create and update the UTF8 magic offset cache, with the proffered utf8/
@@ -7161,44 +7277,41 @@ S_sv_pos_b2u_midway(pTHX_ const U8 *const s, const U8 *const target,
 }
 
 /*
-=for apidoc sv_pos_b2u
+=for apidoc sv_pos_b2u_flags
 
-Converts the value pointed to by offsetp from a count of bytes from the
-start of the string, to a count of the equivalent number of UTF-8 chars.
-Handles magic and type coercion.
+Converts the offset from a count of bytes from the start of the string, to
+a count of the equivalent number of UTF-8 chars.  Handles type coercion.
+I<flags> is passed to C<SvPV_flags>, and usually should be
+C<SV_GMAGIC|SV_CONST_RETURN> to handle magic.
 
 =cut
 */
 
 /*
- * sv_pos_b2u() uses, like sv_pos_u2b(), the mg_ptr of the potential
- * PERL_MAGIC_utf8 of the sv to store the mapping between UTF-8 and
- * byte offsets.
+ * sv_pos_b2u_flags() uses, like sv_pos_u2b_flags(), the mg_ptr of the
+ * potential PERL_MAGIC_utf8 of the sv to store the mapping between UTF-8
+ * and byte offsets.
  *
  */
-void
-Perl_sv_pos_b2u(pTHX_ SV *const sv, I32 *const offsetp)
+STRLEN
+Perl_sv_pos_b2u_flags(pTHX_ SV *const sv, STRLEN const offset, U32 flags)
 {
     const U8* s;
-    const STRLEN byte = *offsetp;
     STRLEN len = 0; /* Actually always set, but let's keep gcc happy.  */
     STRLEN blen;
     MAGIC* mg = NULL;
     const U8* send;
     bool found = FALSE;
 
-    PERL_ARGS_ASSERT_SV_POS_B2U;
-
-    if (!sv)
-       return;
+    PERL_ARGS_ASSERT_SV_POS_B2U_FLAGS;
 
-    s = (const U8*)SvPV_const(sv, blen);
+    s = (const U8*)SvPV_flags(sv, blen, flags);
 
-    if (blen < byte)
+    if (blen < offset)
        Perl_croak(aTHX_ "panic: sv_pos_b2u: bad byte offset, blen=%"UVuf
-                  ", byte=%"UVuf, (UV)blen, (UV)byte);
+                  ", byte=%"UVuf, (UV)blen, (UV)offset);
 
-    send = s + byte;
+    send = s + offset;
 
     if (!SvREADONLY(sv)
        && PL_utf8cache
@@ -7207,18 +7320,16 @@ Perl_sv_pos_b2u(pTHX_ SV *const sv, I32 *const offsetp)
     {
        if (mg->mg_ptr) {
            STRLEN * const cache = (STRLEN *) mg->mg_ptr;
-           if (cache[1] == byte) {
+           if (cache[1] == offset) {
                /* An exact match. */
-               *offsetp = cache[0];
-               return;
+               return cache[0];
            }
-           if (cache[3] == byte) {
+           if (cache[3] == offset) {
                /* An exact match. */
-               *offsetp = cache[2];
-               return;
+               return cache[2];
            }
 
-           if (cache[1] < byte) {
+           if (cache[1] < offset) {
                /* We already know part of the way. */
                if (mg->mg_len != -1) {
                    /* Actually, we know the end too.  */
@@ -7229,7 +7340,7 @@ Perl_sv_pos_b2u(pTHX_ SV *const sv, I32 *const offsetp)
                    len = cache[0] + utf8_length(s + cache[1], send);
                }
            }
-           else if (cache[3] < byte) {
+           else if (cache[3] < offset) {
                /* We're between the two cached pairs, so we do the calculation
                   offset by the byte/utf-8 positions for the earlier pair,
                   then add the utf-8 characters from the string start to
@@ -7239,7 +7350,7 @@ Perl_sv_pos_b2u(pTHX_ SV *const sv, I32 *const offsetp)
                    + cache[2];
 
            }
-           else { /* cache[3] > byte */
+           else { /* cache[3] > offset */
                len = S_sv_pos_b2u_midway(aTHX_ s, send, s + cache[3],
                                          cache[2]);
 
@@ -7258,14 +7369,46 @@ Perl_sv_pos_b2u(pTHX_ SV *const sv, I32 *const offsetp)
            assert_uft8_cache_coherent("sv_pos_b2u", len, real_len, sv);
        len = real_len;
     }
-    *offsetp = len;
 
     if (PL_utf8cache) {
-       if (blen == byte)
+       if (blen == offset)
            utf8_mg_len_cache_update(sv, &mg, len);
        else
-           utf8_mg_pos_cache_update(sv, &mg, byte, len, blen);
+           utf8_mg_pos_cache_update(sv, &mg, offset, len, blen);
     }
+
+    return len;
+}
+
+/*
+=for apidoc sv_pos_b2u
+
+Converts the value pointed to by offsetp from a count of bytes from the
+start of the string, to a count of the equivalent number of UTF-8 chars.
+Handles magic and type coercion.
+
+Use C<sv_pos_b2u_flags> in preference, which correctly handles strings
+longer than 2Gb.
+
+=cut
+*/
+
+/*
+ * sv_pos_b2u() uses, like sv_pos_u2b(), the mg_ptr of the potential
+ * PERL_MAGIC_utf8 of the sv to store the mapping between UTF-8 and
+ * byte offsets.
+ *
+ */
+void
+Perl_sv_pos_b2u(pTHX_ SV *const sv, I32 *const offsetp)
+{
+    PERL_ARGS_ASSERT_SV_POS_B2U;
+
+    if (!sv)
+       return;
+
+    *offsetp = (I32)sv_pos_b2u_flags(sv, (STRLEN)*offsetp,
+                                    SV_GMAGIC|SV_CONST_RETURN);
 }
 
 static void
@@ -7353,7 +7496,7 @@ Perl_sv_eq_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
              }
              /* Now both are in UTF-8. */
              if (cur1 != cur2) {
-                  SvREFCNT_dec(svrecode);
+                  SvREFCNT_dec_NN(svrecode);
                   return FALSE;
              }
         }
@@ -7411,7 +7554,6 @@ Perl_sv_cmp_flags(pTHX_ SV *const sv1, SV *const sv2,
     dVAR;
     STRLEN cur1, cur2;
     const char *pv1, *pv2;
-    char *tpv = NULL;
     I32  cmp;
     SV *svrecode = NULL;
 
@@ -7475,8 +7617,6 @@ Perl_sv_cmp_flags(pTHX_ SV *const sv1, SV *const sv2,
     }
 
     SvREFCNT_dec(svrecode);
-    if (tpv)
-       Safefree(tpv);
 
     return cmp;
 }
@@ -7641,29 +7781,111 @@ S_sv_gets_append_to_utf8(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
 static char *
 S_sv_gets_read_record(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
 {
-    I32 bytesread;
-    const U32 recsize = SvUV(SvRV(PL_rs)); /* RsRECORD() guarantees > 0. */
+    SSize_t bytesread;
+    const STRLEN recsize = SvUV(SvRV(PL_rs)); /* RsRECORD() guarantees > 0. */
       /* Grab the size of the record we're getting */
-    char *const buffer = SvGROW(sv, (STRLEN)(recsize + append + 1)) + append;
+    char *buffer = SvGROW(sv, (STRLEN)(recsize + append + 1)) + append;
+    
+    /* Go yank in */
 #ifdef VMS
+#include <rms.h>
     int fd;
-#endif
+    Stat_t st;
 
-    /* Go yank in */
-#ifdef VMS
-    /* VMS wants read instead of fread, because fread doesn't respect */
-    /* RMS record boundaries. This is not necessarily a good thing to be */
-    /* doing, but we've got no other real choice - except avoid stdio
-       as implementation - perhaps write a :vms layer ?
-    */
+    /* With a true, record-oriented file on VMS, we need to use read directly
+     * to ensure that we respect RMS record boundaries.  The user is responsible
+     * for providing a PL_rs value that corresponds to the FAB$W_MRS (maximum
+     * record size) field.  N.B. This is likely to produce invalid results on
+     * varying-width character data when a record ends mid-character.
+     */
     fd = PerlIO_fileno(fp);
-    if (fd != -1) {
+    if (fd != -1
+       && PerlLIO_fstat(fd, &st) == 0
+       && (st.st_fab_rfm == FAB$C_VAR
+           || st.st_fab_rfm == FAB$C_VFC
+           || st.st_fab_rfm == FAB$C_FIX)) {
+
        bytesread = PerlLIO_read(fd, buffer, recsize);
     }
-    else /* in-memory file from PerlIO::Scalar */
+    else /* in-memory file from PerlIO::Scalar
+          * or not a record-oriented file
+          */
 #endif
     {
        bytesread = PerlIO_read(fp, buffer, recsize);
+
+       /* At this point, the logic in sv_get() means that sv will
+          be treated as utf-8 if the handle is utf8.
+       */
+       if (PerlIO_isutf8(fp) && bytesread > 0) {
+           char *bend = buffer + bytesread;
+           char *bufp = buffer;
+           size_t charcount = 0;
+           bool charstart = TRUE;
+           STRLEN skip = 0;
+
+           while (charcount < recsize) {
+               /* count accumulated characters */
+               while (bufp < bend) {
+                   if (charstart) {
+                       skip = UTF8SKIP(bufp);
+                   }
+                   if (bufp + skip > bend) {
+                       /* partial at the end */
+                       charstart = FALSE;
+                       break;
+                   }
+                   else {
+                       ++charcount;
+                       bufp += skip;
+                       charstart = TRUE;
+                   }
+               }
+
+               if (charcount < recsize) {
+                   STRLEN readsize;
+                   STRLEN bufp_offset = bufp - buffer;
+                   SSize_t morebytesread;
+
+                   /* originally I read enough to fill any incomplete
+                      character and the first byte of the next
+                      character if needed, but if there's many
+                      multi-byte encoded characters we're going to be
+                      making a read call for every character beyond
+                      the original read size.
+
+                      So instead, read the rest of the character if
+                      any, and enough bytes to match at least the
+                      start bytes for each character we're going to
+                      read.
+                   */
+                   if (charstart)
+                       readsize = recsize - charcount;
+                   else 
+                       readsize = skip - (bend - bufp) + recsize - charcount - 1;
+                   buffer = SvGROW(sv, append + bytesread + readsize + 1) + append;
+                   bend = buffer + bytesread;
+                   morebytesread = PerlIO_read(fp, bend, readsize);
+                   if (morebytesread <= 0) {
+                       /* we're done, if we still have incomplete
+                          characters the check code in sv_gets() will
+                          warn about them.
+
+                          I'd originally considered doing
+                          PerlIO_ungetc() on all but the lead
+                          character of the incomplete character, but
+                          read() doesn't do that, so I don't.
+                       */
+                       break;
+                   }
+
+                   /* prepare to scan some more */
+                   bytesread += morebytesread;
+                   bend = buffer + bytesread;
+                   bufp = buffer + bufp_offset;
+               }
+           }
+       }
     }
 
     if (bytesread < 0)
@@ -8046,10 +8268,7 @@ Perl_sv_inc_nomg(pTHX_ SV *const sv)
     if (!sv)
        return;
     if (SvTHINKFIRST(sv)) {
-       if (SvIsCOW(sv) || isGV_with_GP(sv))
-           sv_force_normal_flags(sv, 0);
        if (SvREADONLY(sv)) {
-           if (IN_PERL_RUNTIME)
                Perl_croak_no_modify();
        }
        if (SvROK(sv)) {
@@ -8060,6 +8279,7 @@ Perl_sv_inc_nomg(pTHX_ SV *const sv)
            sv_unref(sv);
            sv_setiv(sv, i);
        }
+       else sv_force_normal_flags(sv, 0);
     }
     flags = SvFLAGS(sv);
     if ((flags & (SVp_NOK|SVp_IOK)) == SVp_NOK) {
@@ -8228,10 +8448,7 @@ Perl_sv_dec_nomg(pTHX_ SV *const sv)
     if (!sv)
        return;
     if (SvTHINKFIRST(sv)) {
-       if (SvIsCOW(sv) || isGV_with_GP(sv))
-           sv_force_normal_flags(sv, 0);
        if (SvREADONLY(sv)) {
-           if (IN_PERL_RUNTIME)
                Perl_croak_no_modify();
        }
        if (SvROK(sv)) {
@@ -8242,6 +8459,7 @@ Perl_sv_dec_nomg(pTHX_ SV *const sv)
            sv_unref(sv);
            sv_setiv(sv, i);
        }
+       else sv_force_normal_flags(sv, 0);
     }
     /* Unlike sv_inc we don't have to worry about string-never-numbers
        and keeping them magic. But we mustn't warn on punting */
@@ -8429,13 +8647,13 @@ Perl_newSVpvn_flags(pTHX_ const char *const s, const STRLEN len, const U32 flags
     new_SV(sv);
     sv_setpvn(sv,s,len);
 
-    /* This code used to a sv_2mortal(), however we now unroll the call to sv_2mortal()
-     * and do what it does ourselves here.
-     * Since we have asserted that flags can only have the SVf_UTF8 and/or SVs_TEMP flags
-     * set above we can use it to enable the sv flags directly (bypassing SvTEMP_on), which
-     * in turn means we dont need to mask out the SVf_UTF8 flag below, which means that we
-     * eliminate quite a few steps than it looks - Yves (explaining patch by gfx)
-     */
+    /* This code used to do a sv_2mortal(), however we now unroll the call to
+     * sv_2mortal() and do what it does ourselves here.  Since we have asserted
+     * that flags can only have the SVf_UTF8 and/or SVs_TEMP flags set above we
+     * can use it to enable the sv flags directly (bypassing SvTEMP_on), which
+     * in turn means we dont need to mask out the SVf_UTF8 flag below, which
+     * means that we eliminate quite a few steps than it looks - Yves
+     * (explaining patch by gfx) */
 
     SvFLAGS(sv) |= flags;
 
@@ -8464,7 +8682,7 @@ Perl_sv_2mortal(pTHX_ SV *const sv)
     dVAR;
     if (!sv)
        return NULL;
-    if (SvREADONLY(sv) && SvIMMORTAL(sv))
+    if (SvIMMORTAL(sv))
        return sv;
     PUSH_EXTEND_MORTAL__SV_C(sv);
     SvTEMP_on(sv);
@@ -8587,7 +8805,8 @@ Perl_newSVhek(pTHX_ const HEK *const hek)
 
 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.  If the C<hash> parameter
+created first.  Turns on the SvIsCOW flag (or READONLY
+and FAKE in 5.16 and earlier).  If the C<hash> parameter
 is non-zero, that value is used; otherwise the hash is computed.
 The string's hash can later be retrieved from the SV
 with the C<SvSHARED_HASH()> macro.  The idea here is
@@ -8876,7 +9095,7 @@ Perl_sv_resetpvn(pTHX_ const char *s, STRLEN len, HV * const stash)
     char todo[PERL_UCHAR_MAX+1];
     const char *send;
 
-    if (!stash)
+    if (!stash || SvTYPE(stash) != SVt_PVHV)
        return;
 
     if (!s) {          /* reset ?? searches */
@@ -9166,7 +9385,7 @@ Perl_sv_pvn_force_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
     PERL_ARGS_ASSERT_SV_PVN_FORCE_FLAGS;
 
     if (flags & SV_GMAGIC) SvGETMAGIC(sv);
-    if (SvTHINKFIRST(sv) && !SvROK(sv))
+    if (SvTHINKFIRST(sv) && (!SvROK(sv) || SvREADONLY(sv)))
         sv_force_normal_flags(sv, 0);
 
     if (SvPOK(sv)) {
@@ -9177,14 +9396,6 @@ Perl_sv_pvn_force_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
        char *s;
        STRLEN len;
  
-       if (SvREADONLY(sv) && !(flags & SV_MUTABLE_RETURN)) {
-           const char * const ref = sv_reftype(sv,0);
-           if (PL_op)
-               Perl_croak(aTHX_ "Can't coerce readonly %s to string in %s",
-                          ref, OP_DESC(PL_op));
-           else
-               Perl_croak(aTHX_ "Can't coerce readonly %s to string", ref);
-       }
        if (SvTYPE(sv) > SVt_PVLV
            || isGV_with_GP(sv))
            /* diag_listed_as: Can't coerce %s to %s in %s */
@@ -9300,7 +9511,7 @@ Perl_sv_reftype(pTHX_ const SV *const sv, const int ob)
                                    ? "GLOB" : "SCALAR");
        case SVt_PVFM:          return "FORMAT";
        case SVt_PVIO:          return "IO";
-       case SVt_BIND:          return "BIND";
+       case SVt_INVLIST:       return "INVLIST";
        case SVt_REGEXP:        return "REGEXP";
        default:                return "UNKNOWN";
        }
@@ -9394,10 +9605,10 @@ Perl_sv_isa(pTHX_ SV *sv, const char *const name)
 /*
 =for apidoc newSVrv
 
-Creates a new SV for the RV, C<rv>, to point to.  If C<rv> is not an RV then
-it will be upgraded to one.  If C<classname> is non-null then the new SV will
-be blessed in the specified package.  The new SV is returned and its
-reference count is 1.
+Creates a new SV for the existing RV, C<rv>, to point to.  If C<rv> is not an
+RV then it will be upgraded to one.  If C<classname> is non-null then the new
+SV will be blessed in the specified package.  The new SV is returned and its
+reference count is 1. The reference count 1 is owned by C<rv>.
 
 =cut
 */
@@ -9579,21 +9790,18 @@ Perl_sv_bless(pTHX_ SV *const sv, HV *const stash)
 
     PERL_ARGS_ASSERT_SV_BLESS;
 
+    SvGETMAGIC(sv);
     if (!SvROK(sv))
         Perl_croak(aTHX_ "Can't bless non-reference value");
     tmpRef = SvRV(sv);
     if (SvFLAGS(tmpRef) & (SVs_OBJECT|SVf_READONLY)) {
-       if (SvREADONLY(tmpRef) && !SvIsCOW(tmpRef))
+       if (SvREADONLY(tmpRef))
            Perl_croak_no_modify();
        if (SvOBJECT(tmpRef)) {
-           if (SvTYPE(tmpRef) != SVt_PVIO)
-               --PL_sv_objcount;
            SvREFCNT_dec(SvSTASH(tmpRef));
        }
     }
     SvOBJECT_on(tmpRef);
-    if (SvTYPE(tmpRef) != SVt_PVIO)
-       ++PL_sv_objcount;
     SvUPGRADE(tmpRef, SVt_PVMG);
     SvSTASH_set(tmpRef, MUTABLE_HV(SvREFCNT_inc_simple(stash)));
 
@@ -9695,7 +9903,7 @@ Perl_sv_unref_flags(pTHX_ SV *const ref, const U32 flags)
     /* You can't have a || SvREADONLY(target) here, as $a = $$a, where $a was
        assigned to as BEGIN {$a = \"Foo"} will fail.  */
     if (SvREFCNT(target) != 1 || (flags & SV_IMMEDIATE_UNREF))
-       SvREFCNT_dec(target);
+       SvREFCNT_dec_NN(target);
     else /* XXX Hack, but hard to make $a=$a->[1] work otherwise */
        sv_2mortal(target);     /* Schedule for freeing later */
 }
@@ -10331,7 +10539,8 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                %-<num>p        include an SV with precision <num>      
                %2p             include a HEK
                %3p             include a HEK with precision of 256
-               %<num>p         (where num != 2 or 3) reserved for future
+               %4p             char* preceded by utf8 flag and length
+               %<num>p         (where num is 1 or > 4) reserved for future
                                extensions
 
        Robin Barker 2005-07-14 (but modified since)
@@ -10343,6 +10552,15 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
            STRLEN n = 0;
            if (*q == '-')
                sv = *q++;
+           else if (strnEQ(q, UTF8f, sizeof(UTF8f)-1)) { /* UTF8f */
+               /* The argument has already gone through cBOOL, so the cast
+                  is safe. */
+               is_utf8 = (bool)va_arg(*args, int);
+               elen = va_arg(*args, UV);
+               eptr = va_arg(*args, char *);
+               q += sizeof(UTF8f)-1;
+               goto string;
+           }
            n = expect_number(&q);
            if (*q++ == 'p') {
                if (sv) {                       /* SVf */
@@ -11123,6 +11341,12 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
            }
        float_converted:
            eptr = PL_efloatbuf;
+            if (PL_numeric_radix_sv && SvUTF8(PL_numeric_radix_sv)
+                && instr(eptr, SvPVX_const(PL_numeric_radix_sv)))
+            {
+                is_utf8 = TRUE;
+            }
+
            break;
 
            /* SPECIAL */
@@ -12031,7 +12255,6 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
        SvANY(dstr)     = new_XNV();
        SvNV_set(dstr, SvNVX(sstr));
        break;
-       /* case SVt_BIND: */
     default:
        {
            /* These are all the types that need complex bodies allocating.  */
@@ -12056,6 +12279,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
            case SVt_PVMG:
            case SVt_PVNV:
            case SVt_PVIV:
+            case SVt_INVLIST:
            case SVt_PV:
                assert(sv_type_details->body_size);
                if (sv_type_details->arena) {
@@ -12093,6 +12317,8 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
            if (sv_type >= SVt_PVMG) {
                if ((sv_type == SVt_PVMG) && SvPAD_OUR(dstr)) {
                    SvOURSTASH_set(dstr, hv_dup_inc(SvOURSTASH(dstr), param));
+               } else if (sv_type == SVt_PVAV && AvPAD_NAMELIST(dstr)) {
+                   NOOP;
                } else if (SvMAGIC(dstr))
                    SvMAGIC_set(dstr, mg_dup(SvMAGIC(dstr), param));
                if (SvOBJECT(dstr) && SvSTASH(dstr))
@@ -12247,6 +12473,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                        }
                        daux->xhv_name_count = saux->xhv_name_count;
 
+                       daux->xhv_fill_lazy = saux->xhv_fill_lazy;
                        daux->xhv_riter = saux->xhv_riter;
                        daux->xhv_eiter = saux->xhv_eiter
                            ? he_dup(saux->xhv_eiter,
@@ -12329,9 +12556,6 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
        }
     }
 
-    if (SvOBJECT(dstr) && SvTYPE(dstr) != SVt_PVIO)
-       ++PL_sv_objcount;
-
     return dstr;
  }
 
@@ -12594,6 +12818,7 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
            /* fall through */
        case SAVEt_FREESV:
        case SAVEt_MORTALIZESV:
+       case SAVEt_READONLY_OFF:
            sv = (const SV *)POPPTR(ss,ix);
            TOPPTR(nss,ix) = sv_dup_inc(sv, param);
            break;
@@ -12610,6 +12835,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);
@@ -12708,6 +12941,12 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = cophh_copy((COPHH *)ptr);
            break;
+       case SAVEt_ADELETE:
+           av = (const AV *)POPPTR(ss,ix);
+           TOPPTR(nss,ix) = av_dup_inc(av, param);
+           i = POPINT(ss,ix);
+           TOPINT(nss,ix) = i;
+           break;
        case SAVEt_DELETE:
            hv = (const HV *)POPPTR(ss,ix);
            TOPPTR(nss,ix) = hv_dup_inc(hv, param);
@@ -12781,43 +13020,6 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
            sv = (const SV *)POPPTR(ss,ix);
            TOPPTR(nss,ix) = sv_dup(sv, param);
            break;
-       case SAVEt_RE_STATE:
-           {
-               const struct re_save_state *const old_state
-                   = (struct re_save_state *)
-                   (ss + ix - SAVESTACK_ALLOC_FOR_RE_SAVE_STATE);
-               struct re_save_state *const new_state
-                   = (struct re_save_state *)
-                   (nss + ix - SAVESTACK_ALLOC_FOR_RE_SAVE_STATE);
-
-               Copy(old_state, new_state, 1, struct re_save_state);
-               ix -= SAVESTACK_ALLOC_FOR_RE_SAVE_STATE;
-
-               new_state->re_state_bostr
-                   = pv_dup(old_state->re_state_bostr);
-               new_state->re_state_regeol
-                   = pv_dup(old_state->re_state_regeol);
-#ifdef PERL_ANY_COW
-               new_state->re_state_nrs
-                   = sv_dup(old_state->re_state_nrs, param);
-#endif
-               new_state->re_state_reg_magic
-                   = (MAGIC*) any_dup(old_state->re_state_reg_magic, 
-                              proto_perl);
-               new_state->re_state_reg_oldcurpm
-                   = (PMOP*) any_dup(old_state->re_state_reg_oldcurpm, 
-                             proto_perl);
-               new_state->re_state_reg_curpm
-                   = (PMOP*)  any_dup(old_state->re_state_reg_curpm, 
-                              proto_perl);
-               new_state->re_state_reg_oldsaved
-                   = pv_dup(old_state->re_state_reg_oldsaved);
-               new_state->re_state_reg_poscache
-                   = pv_dup(old_state->re_state_reg_poscache);
-               new_state->re_state_reg_starttry
-                   = pv_dup(old_state->re_state_reg_starttry);
-               break;
-           }
        case SAVEt_COMPILE_WARNINGS:
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = DUP_WARNINGS((STRLEN*)ptr);
@@ -13020,7 +13222,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     Zero(&PL_body_roots, 1, PL_body_roots);
     
     PL_sv_count                = 0;
-    PL_sv_objcount     = 0;
     PL_sv_root         = NULL;
     PL_sv_arenaroot    = NULL;
 
@@ -13076,8 +13277,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 #endif
 
     /* RE engine related */
-    Zero(&PL_reg_state, 1, struct re_save_state);
     PL_regmatch_slab   = NULL;
+    PL_reg_curpm       = NULL;
 
     PL_sub_generation  = proto_perl->Isub_generation;
 
@@ -13129,8 +13330,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_cryptseen       = proto_perl->Icryptseen;
 #endif
 
-    PL_hints           = proto_perl->Ihints;
-
 #ifdef USE_LOCALE_COLLATE
     PL_collation_ix    = proto_perl->Icollation_ix;
     PL_collation_standard      = proto_perl->Icollation_standard;
@@ -13181,7 +13380,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_last_swash_tmps = (U8*)NULL;
     PL_last_swash_slen = 0;
 
-    PL_glob_index      = proto_perl->Iglob_index;
     PL_srand_called    = proto_perl->Isrand_called;
 
     if (flags & CLONEf_COPY_STACKS) {
@@ -13243,7 +13441,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* regex stuff */
 
-    PL_regdummy                = proto_perl->Iregdummy;
     PL_colorset                = 0;            /* reinits PL_colors[] */
     /*PL_colors[6]     = {0,0,0,0,0,0};*/
 
@@ -13276,6 +13473,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     hv_ksplit(PL_strtab, HvTOTALKEYS(proto_perl->Istrtab));
     ptr_table_store(PL_ptr_table, proto_perl->Istrtab, PL_strtab);
 
+    Zero(PL_sv_consts, SV_CONSTS_COUNT, SV*);
+
     /* This PV will be free'd special way so must set it same way op.c does */
     PL_compiling.cop_file    = savesharedpv(PL_compiling.cop_file);
     ptr_table_store(PL_ptr_table, proto_perl->Icompiling.cop_file, PL_compiling.cop_file);
@@ -13471,68 +13670,23 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     /* Unicode inversion lists */
     PL_ASCII           = sv_dup_inc(proto_perl->IASCII, param);
     PL_Latin1          = sv_dup_inc(proto_perl->ILatin1, param);
-
-    PL_PerlSpace       = sv_dup_inc(proto_perl->IPerlSpace, param);
-    PL_XPerlSpace      = sv_dup_inc(proto_perl->IXPerlSpace, param);
-
-    PL_L1PosixAlnum    = sv_dup_inc(proto_perl->IL1PosixAlnum, param);
-    PL_PosixAlnum      = sv_dup_inc(proto_perl->IPosixAlnum, param);
-
-    PL_L1PosixAlpha    = sv_dup_inc(proto_perl->IL1PosixAlpha, param);
-    PL_PosixAlpha      = sv_dup_inc(proto_perl->IPosixAlpha, param);
-
-    PL_PosixBlank      = sv_dup_inc(proto_perl->IPosixBlank, param);
-    PL_XPosixBlank     = sv_dup_inc(proto_perl->IXPosixBlank, param);
-
-    PL_L1Cased         = sv_dup_inc(proto_perl->IL1Cased, param);
-
-    PL_PosixCntrl      = sv_dup_inc(proto_perl->IPosixCntrl, param);
-    PL_XPosixCntrl     = sv_dup_inc(proto_perl->IXPosixCntrl, param);
-
-    PL_PosixDigit      = sv_dup_inc(proto_perl->IPosixDigit, param);
-
-    PL_L1PosixGraph    = sv_dup_inc(proto_perl->IL1PosixGraph, param);
-    PL_PosixGraph      = sv_dup_inc(proto_perl->IPosixGraph, param);
-
-    PL_L1PosixLower    = sv_dup_inc(proto_perl->IL1PosixLower, param);
-    PL_PosixLower      = sv_dup_inc(proto_perl->IPosixLower, param);
-
-    PL_L1PosixPrint    = sv_dup_inc(proto_perl->IL1PosixPrint, param);
-    PL_PosixPrint      = sv_dup_inc(proto_perl->IPosixPrint, param);
-
-    PL_L1PosixPunct    = sv_dup_inc(proto_perl->IL1PosixPunct, param);
-    PL_PosixPunct      = sv_dup_inc(proto_perl->IPosixPunct, param);
-
-    PL_PosixSpace      = sv_dup_inc(proto_perl->IPosixSpace, param);
-    PL_XPosixSpace     = sv_dup_inc(proto_perl->IXPosixSpace, param);
-
-    PL_L1PosixUpper    = sv_dup_inc(proto_perl->IL1PosixUpper, param);
-    PL_PosixUpper      = sv_dup_inc(proto_perl->IPosixUpper, param);
-
-    PL_L1PosixWord     = sv_dup_inc(proto_perl->IL1PosixWord, param);
-    PL_PosixWord       = sv_dup_inc(proto_perl->IPosixWord, param);
-
-    PL_PosixXDigit     = sv_dup_inc(proto_perl->IPosixXDigit, param);
-    PL_XPosixXDigit    = sv_dup_inc(proto_perl->IXPosixXDigit, param);
-
-    PL_VertSpace       = sv_dup_inc(proto_perl->IVertSpace, param);
+    PL_AboveLatin1     = sv_dup_inc(proto_perl->IAboveLatin1, param);
 
     PL_NonL1NonFinalFold = sv_dup_inc(proto_perl->INonL1NonFinalFold, param);
     PL_HasMultiCharFold= sv_dup_inc(proto_perl->IHasMultiCharFold, param);
 
     /* 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_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);
+    for (i = 0; i < POSIX_SWASH_COUNT; i++) {
+        PL_utf8_swash_ptrs[i] = sv_dup_inc(proto_perl->Iutf8_swash_ptrs[i], param);
+    }
+    for (i = 0; i < POSIX_CC_COUNT; i++) {
+        PL_Posix_ptrs[i] = sv_dup_inc(proto_perl->IPosix_ptrs[i], param);
+        PL_L1Posix_ptrs[i] = sv_dup_inc(proto_perl->IL1Posix_ptrs[i], param);
+        PL_XPosix_ptrs[i] = sv_dup_inc(proto_perl->IXPosix_ptrs[i], 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);
-    PL_utf8_X_LVT      = sv_dup_inc(proto_perl->Iutf8_X_LVT, param);
     PL_utf8_toupper    = sv_dup_inc(proto_perl->Iutf8_toupper, param);
     PL_utf8_totitle    = sv_dup_inc(proto_perl->Iutf8_totitle, param);
     PL_utf8_tolower    = sv_dup_inc(proto_perl->Iutf8_tolower, param);
@@ -13540,14 +13694,12 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_utf8_idstart    = sv_dup_inc(proto_perl->Iutf8_idstart, param);
     PL_utf8_xidstart   = sv_dup_inc(proto_perl->Iutf8_xidstart, param);
     PL_utf8_perl_idstart = sv_dup_inc(proto_perl->Iutf8_perl_idstart, param);
+    PL_utf8_perl_idcont = sv_dup_inc(proto_perl->Iutf8_perl_idcont, param);
     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);
 
     if (proto_perl->Ipsig_pend) {
        Newxz(PL_psig_pend, SIG_SIZE, int);
@@ -13630,7 +13782,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_errors          = sv_dup_inc(proto_perl->Ierrors, param);
 
     PL_sortcop         = (OP*)any_dup(proto_perl->Isortcop, proto_perl);
-    PL_sortstash       = hv_dup(proto_perl->Isortstash, param);
     PL_firstgv         = gv_dup(proto_perl->Ifirstgv, param);
     PL_secondgv                = gv_dup(proto_perl->Isecondgv, param);
 
@@ -13730,7 +13881,7 @@ S_unreferenced_to_tmp_stack(pTHX_ AV *const unreferenced)
        } while (++svp <= last);
        AvREAL_off(unreferenced);
     }
-    SvREFCNT_dec(unreferenced);
+    SvREFCNT_dec_NN(unreferenced);
 }
 
 void
@@ -13797,18 +13948,18 @@ Perl_clone_params_new(PerlInterpreter *const from, PerlInterpreter *const to)
 void
 Perl_init_constants(pTHX)
 {
-    SvREFCNT(&PL_sv_undef)     = (~(U32)0)/2;
+    SvREFCNT(&PL_sv_undef)     = SvREFCNT_IMMORTAL;
     SvFLAGS(&PL_sv_undef)      = SVf_READONLY|SVt_NULL;
     SvANY(&PL_sv_undef)                = NULL;
 
     SvANY(&PL_sv_no)           = new_XPVNV();
-    SvREFCNT(&PL_sv_no)                = (~(U32)0)/2;
+    SvREFCNT(&PL_sv_no)                = SvREFCNT_IMMORTAL;
     SvFLAGS(&PL_sv_no)         = SVt_PVNV|SVf_READONLY
                                  |SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
                                  |SVp_POK|SVf_POK;
 
     SvANY(&PL_sv_yes)          = new_XPVNV();
-    SvREFCNT(&PL_sv_yes)       = (~(U32)0)/2;
+    SvREFCNT(&PL_sv_yes)       = SvREFCNT_IMMORTAL;
     SvFLAGS(&PL_sv_yes)                = SVt_PVNV|SVf_READONLY
                                  |SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
                                  |SVp_POK|SVf_POK;
@@ -14079,7 +14230,7 @@ Perl_varname(pTHX_ const GV *const gv, const char gvtype, PADOFFSET targ,
        Perl_sv_catpvf(aTHX_ name, "{%s}",
            pv_pretty(sv, SvPVX_const(keyname), SvCUR(keyname), 32, NULL, NULL,
                    PERL_PV_PRETTY_DUMP | PERL_PV_ESCAPE_UNI_DETECT ));
-       SvREFCNT_dec(sv);
+       SvREFCNT_dec_NN(sv);
     }
     else if (subscript_type == FUV_SUBSCRIPT_ARRAY) {
        *SvPVX(name) = '$';
@@ -14302,8 +14453,10 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
                        break;
                }
                else {
+                   SV * const  opsv = cSVOPx_sv(kid);
+                   const IV  opsviv = SvIV(opsv);
                    SV * const * const svp = av_fetch(MUTABLE_AV(sv),
-                       negate ? - SvIV(cSVOPx_sv(kid)) : SvIV(cSVOPx_sv(kid)),
+                       negate ? - opsviv : opsviv,
                        FALSE);
                    if (!svp || *svp != uninit_sv)
                        break;