This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perldelta for c9df4fdaad9 (dump LABEL leak)
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index 4b63ac8..b5950d6 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -413,7 +413,7 @@ S_visit(pTHX_ SVFUNC_t f, const U32 flags, const U32 mask)
        register const SV * const svend = &sva[SvREFCNT(sva)];
        register SV* sv;
        for (sv = sva + 1; sv < svend; ++sv) {
-           if (SvTYPE(sv) != SVTYPEMASK
+           if (SvTYPE(sv) != (svtype)SVTYPEMASK
                    && (sv->sv_flags & mask) == flags
                    && SvREFCNT(sv))
            {
@@ -432,7 +432,7 @@ S_visit(pTHX_ SVFUNC_t f, const U32 flags, const U32 mask)
 static void
 do_report_used(pTHX_ SV *const sv)
 {
-    if (SvTYPE(sv) != SVTYPEMASK) {
+    if (SvTYPE(sv) != (svtype)SVTYPEMASK) {
        PerlIO_printf(Perl_debug_log, "****\n");
        sv_dump(sv);
     }
@@ -442,7 +442,7 @@ do_report_used(pTHX_ SV *const sv)
 /*
 =for apidoc sv_report_used
 
-Dump the contents of all SVs not yet freed. (Debugging aid).
+Dump the contents of all SVs not yet freed (debugging aid).
 
 =cut
 */
@@ -563,7 +563,7 @@ do_curse(pTHX_ SV * const sv) {
 /*
 =for apidoc sv_clean_objs
 
-Attempt to destroy all objects not yet freed
+Attempt to destroy all objects not yet freed.
 
 =cut
 */
@@ -614,7 +614,7 @@ do_clean_all(pTHX_ SV *const sv)
 =for apidoc sv_clean_all
 
 Decrement the refcnt of each remaining SV, possibly triggering a
-cleanup. This function may have to be called multiple times to free
+cleanup.  This function may have to be called multiple times to free
 SVs which are in complex self-referential hierarchies.
 
 =cut
@@ -670,7 +670,7 @@ struct arena_set {
 /*
 =for apidoc sv_free_arenas
 
-Deallocate the memory used by all arenas. Note that all the individual SV
+Deallocate the memory used by all arenas.  Note that all the individual SV
 heads and bodies within the arenas must already have been freed.
 
 =cut
@@ -893,37 +893,31 @@ static const struct body_details bodies_by_type[] = {
       NOARENA /* IVS don't need an arena  */, 0
     },
 
-    /* 8 bytes on most ILP32 with IEEE doubles */
     { sizeof(NV), sizeof(NV),
       STRUCT_OFFSET(XPVNV, xnv_u),
       SVt_NV, FALSE, HADNV, HASARENA, FIT_ARENA(0, sizeof(NV)) },
 
-    /* 8 bytes on most ILP32 with IEEE doubles */
     { sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur),
       copy_length(XPV, xpv_len) - STRUCT_OFFSET(XPV, xpv_cur),
       + STRUCT_OFFSET(XPV, xpv_cur),
       SVt_PV, FALSE, NONV, HASARENA,
       FIT_ARENA(0, sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur)) },
 
-    /* 12 */
     { sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur),
       copy_length(XPVIV, xiv_u) - STRUCT_OFFSET(XPV, xpv_cur),
       + STRUCT_OFFSET(XPV, xpv_cur),
       SVt_PVIV, FALSE, NONV, HASARENA,
       FIT_ARENA(0, sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur)) },
 
-    /* 20 */
     { sizeof(XPVNV) - STRUCT_OFFSET(XPV, xpv_cur),
       copy_length(XPVNV, xnv_u) - STRUCT_OFFSET(XPV, xpv_cur),
       + STRUCT_OFFSET(XPV, xpv_cur),
       SVt_PVNV, FALSE, HADNV, HASARENA,
       FIT_ARENA(0, sizeof(XPVNV) - STRUCT_OFFSET(XPV, xpv_cur)) },
 
-    /* 28 */
     { sizeof(XPVMG), copy_length(XPVMG, xnv_u), 0, SVt_PVMG, FALSE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVMG)) },
 
-    /* something big */
     { sizeof(regexp),
       sizeof(regexp),
       0,
@@ -931,11 +925,9 @@ static const struct body_details bodies_by_type[] = {
       FIT_ARENA(0, sizeof(regexp))
     },
 
-    /* 48 */
     { sizeof(XPVGV), sizeof(XPVGV), 0, SVt_PVGV, TRUE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVGV)) },
     
-    /* 64 */
     { sizeof(XPVLV), sizeof(XPVLV), 0, SVt_PVLV, TRUE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVLV)) },
 
@@ -951,7 +943,6 @@ static const struct body_details bodies_by_type[] = {
       SVt_PVHV, TRUE, NONV, HASARENA,
       FIT_ARENA(0, sizeof(XPVHV)) },
 
-    /* 56 */
     { sizeof(XPVCV),
       sizeof(XPVCV),
       0,
@@ -964,7 +955,6 @@ static const struct body_details bodies_by_type[] = {
       SVt_PVFM, TRUE, NONV, NOARENA,
       FIT_ARENA(20, sizeof(XPVFM)) },
 
-    /* XPVIO is 84 bytes, fits 48x */
     { sizeof(XPVIO),
       sizeof(XPVIO),
       0,
@@ -1137,7 +1127,10 @@ static const struct body_details fake_rv =
 
 Upgrade an SV to a more complex form.  Generally adds a new body type to the
 SV, then copies across as much information as possible from the old body.
-You generally want to use the C<SvUPGRADE> macro wrapper. See also C<svtype>.
+It croaks if the SV is already in a more complex form than requested.  You
+generally want to use the C<SvUPGRADE> macro wrapper, which checks the type
+before calling C<sv_upgrade>, and hence does not croak.  See also
+C<svtype>.
 
 =cut
 */
@@ -1437,7 +1430,7 @@ Perl_sv_upgrade(pTHX_ register SV *const sv, svtype new_type)
 /*
 =for apidoc sv_backoff
 
-Remove any string offset. You should normally use the C<SvOOK_off> macro
+Remove any string offset.  You should normally use the C<SvOOK_off> macro
 wrapper instead.
 
 =cut
@@ -1617,13 +1610,16 @@ Perl_sv_setuv(pTHX_ register SV *const sv, const UV u)
 {
     PERL_ARGS_ASSERT_SV_SETUV;
 
-    /* With these two if statements:
+    /* With the if statement to ensure that integers are stored as IVs whenever
+       possible:
        u=1.49  s=0.52  cu=72.49  cs=10.64  scripts=270  tests=20865
 
        without
        u=1.35  s=0.47  cu=73.45  cs=11.43  scripts=270  tests=20865
 
-       If you wish to remove them, please benchmark to see what the effect is
+       If you wish to remove the following if statement, so that this routine
+       (and its callers) always return UVs, please benchmark to see what the
+       effect is. Modern CPUs may be different. Or may not :-)
     */
     if (u <= (UV)IV_MAX) {
        sv_setiv(sv, (IV)u);
@@ -1729,7 +1725,7 @@ S_not_a_number(pTHX_ SV *const sv)
 
      if (DO_UTF8(sv)) {
           dsv = newSVpvs_flags("", SVs_TEMP);
-          pv = sv_uni_display(dsv, sv, 10, 0);
+          pv = sv_uni_display(dsv, sv, 10, UNI_DISPLAY_ISPRINT);
      } else {
          char *d = tmpbuf;
          const char * const limit = tmpbuf + sizeof(tmpbuf) - 8;
@@ -1783,10 +1779,12 @@ S_not_a_number(pTHX_ SV *const sv)
 
     if (PL_op)
        Perl_warner(aTHX_ packWARN(WARN_NUMERIC),
+                   /* diag_listed_as: Argument "%s" isn't numeric%s */
                    "Argument \"%s\" isn't numeric in %s", pv,
                    OP_DESC(PL_op));
     else
        Perl_warner(aTHX_ packWARN(WARN_NUMERIC),
+                   /* diag_listed_as: Argument "%s" isn't numeric%s */
                    "Argument \"%s\" isn't numeric", pv);
 }
 
@@ -1795,7 +1793,8 @@ S_not_a_number(pTHX_ SV *const sv)
 
 Test if the content of an SV looks like a number (or is a number).
 C<Inf> and C<Infinity> are treated as numbers (so will not issue a
-non-numeric warning), even if your atof() doesn't grok them.
+non-numeric warning), even if your atof() doesn't grok them.  Get-magic is
+ignored.
 
 =cut
 */
@@ -1808,12 +1807,9 @@ Perl_looks_like_number(pTHX_ SV *const sv)
 
     PERL_ARGS_ASSERT_LOOKS_LIKE_NUMBER;
 
-    if (SvPOK(sv)) {
-       sbegin = SvPVX_const(sv);
-       len = SvCUR(sv);
+    if (SvPOK(sv) || SvPOKp(sv)) {
+       sbegin = SvPV_nomg_const(sv, len);
     }
-    else if (SvPOKp(sv))
-       sbegin = SvPV_const(sv, len);
     else
        return SvFLAGS(sv) & (SVf_NOK|SVp_NOK|SVf_IOK|SVp_IOK);
     return grok_number(sbegin, len, NULL);
@@ -1822,21 +1818,16 @@ Perl_looks_like_number(pTHX_ SV *const sv)
 STATIC bool
 S_glob_2number(pTHX_ GV * const gv)
 {
-    const U32 wasfake = SvFLAGS(gv) & SVf_FAKE;
-    SV *const buffer = sv_newmortal();
-
     PERL_ARGS_ASSERT_GLOB_2NUMBER;
 
-    /* FAKE globs can get coerced, so need to turn this off temporarily if it
-       is on.  */
-    SvFAKE_off(gv);
-    gv_efullname3(buffer, gv, "*");
-    SvFLAGS(gv) |= wasfake;
-
     /* We know that all GVs stringify to something that is not-a-number,
        so no need to test that.  */
     if (ckWARN(WARN_NUMERIC))
+    {
+       SV *const buffer = sv_newmortal();
+       gv_efullname3(buffer, gv, "*");
        not_a_number(buffer);
+    }
     /* We just want something true to return, so that S_sv_2iuv_common
        can tail call us and return true.  */
     return TRUE;
@@ -2238,7 +2229,7 @@ S_sv_2iuv_common(pTHX_ SV *const sv)
        if (isGV_with_GP(sv))
            return glob_2number(MUTABLE_GV(sv));
 
-       if (!(SvFLAGS(sv) & SVs_PADTMP)) {
+       if (!SvPADTMP(sv)) {
            if (!PL_localizing && ckWARN(WARN_UNINITIALIZED))
                report_uninit(sv);
        }
@@ -2265,22 +2256,37 @@ IV
 Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags)
 {
     dVAR;
+
     if (!sv)
        return 0;
-    if (SvGMAGICAL(sv) || SvVALID(sv)) {
+
+    if (SvGMAGICAL(sv) && (flags & SV_GMAGIC))
+       mg_get(sv);
+
+    if (SvROK(sv)) {
+       if (SvAMAGIC(sv)) {
+           SV * tmpstr;
+           if (flags & SV_SKIP_OVERLOAD)
+               return 0;
+           tmpstr = AMG_CALLunary(sv, numer_amg);
+           if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
+               return SvIV(tmpstr);
+           }
+       }
+       return PTR2IV(SvRV(sv));
+    }
+
+    if (SvVALID(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
           accessible by user Perl code - the only way that I'm aware of is when
           a constant subroutine which is used as the second argument to index.
        */
-       if (flags & SV_GMAGIC)
-           mg_get(sv);
        if (SvIOKp(sv))
            return SvIVX(sv);
-       if (SvNOKp(sv)) {
+       if (SvNOKp(sv))
            return I_V(SvNVX(sv));
-       }
        if (SvPOKp(sv) && SvLEN(sv)) {
            UV value;
            const int numtype
@@ -2303,25 +2309,12 @@ Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags)
            }
            return I_V(Atof(SvPVX_const(sv)));
        }
-        if (SvROK(sv)) {
-           goto return_rok;
-       }
-       assert(SvTYPE(sv) >= SVt_PVMG);
-       /* This falls through to the report_uninit inside S_sv_2iuv_common.  */
-    } else if (SvTHINKFIRST(sv)) {
-       if (SvROK(sv)) {
-       return_rok:
-           if (SvAMAGIC(sv)) {
-               SV * tmpstr;
-               if (flags & SV_SKIP_OVERLOAD)
-                   return 0;
-               tmpstr = AMG_CALLunary(sv, numer_amg);
-               if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
-                   return SvIV(tmpstr);
-               }
-           }
-           return PTR2IV(SvRV(sv));
-       }
+       if (ckWARN(WARN_UNINITIALIZED))
+           report_uninit(sv);
+       return 0;
+    }
+
+    if (SvTHINKFIRST(sv)) {
        if (SvIsCOW(sv)) {
            sv_force_normal_flags(sv, 0);
        }
@@ -2331,16 +2324,40 @@ Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags)
            return 0;
        }
     }
+
     if (!SvIOKp(sv)) {
        if (S_sv_2iuv_common(aTHX_ sv))
            return 0;
     }
+
     DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2iv(%"IVdf")\n",
        PTR2UV(sv),SvIVX(sv)));
     return SvIsUV(sv) ? (IV)SvUVX(sv) : SvIVX(sv);
 }
 
 /*
+=for apidoc sv_gmagical_2iv_please
+
+Used internally by C<SvIV_please_nomg>, this function sets the C<SvIVX>
+slot if C<sv_2iv> would have made the scalar C<SvIOK> had it not been
+magical.  In that case it returns true.
+
+=cut
+*/
+
+bool
+Perl_sv_gmagical_2iv_please(pTHX_ register SV *sv)
+{
+    bool has_int;
+    PERL_ARGS_ASSERT_SV_GMAGICAL_2IV_PLEASE;
+    assert(SvGMAGICAL(sv) && !SvIOKp(sv) && (SvNOKp(sv) || SvPOKp(sv)));
+    if (S_sv_2iuv_common(aTHX_ sv)) { SvNIOK_off(sv); return 0; }
+    has_int = !!SvIOK(sv);
+    SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK);
+    return has_int;
+}
+
+/*
 =for apidoc sv_2uv_flags
 
 Return the unsigned integer value of an SV, doing any necessary string
@@ -2354,13 +2371,29 @@ UV
 Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags)
 {
     dVAR;
+
     if (!sv)
        return 0;
-    if (SvGMAGICAL(sv) || SvVALID(sv)) {
+
+    if (SvGMAGICAL(sv) && (flags & SV_GMAGIC))
+       mg_get(sv);
+
+    if (SvROK(sv)) {
+       if (SvAMAGIC(sv)) {
+           SV *tmpstr;
+           if (flags & SV_SKIP_OVERLOAD)
+               return 0;
+           tmpstr = AMG_CALLunary(sv, numer_amg);
+           if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
+               return SvUV(tmpstr);
+           }
+       }
+       return PTR2UV(SvRV(sv));
+    }
+
+    if (SvVALID(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.  */
-       if (flags & SV_GMAGIC)
-           mg_get(sv);
        if (SvIOKp(sv))
            return SvUVX(sv);
        if (SvNOKp(sv))
@@ -2382,25 +2415,12 @@ Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags)
            }
            return U_V(Atof(SvPVX_const(sv)));
        }
-        if (SvROK(sv)) {
-           goto return_rok;
-       }
-       assert(SvTYPE(sv) >= SVt_PVMG);
-       /* This falls through to the report_uninit inside S_sv_2iuv_common.  */
-    } else if (SvTHINKFIRST(sv)) {
-       if (SvROK(sv)) {
-       return_rok:
-           if (SvAMAGIC(sv)) {
-               SV *tmpstr;
-               if (flags & SV_SKIP_OVERLOAD)
-                   return 0;
-               tmpstr = AMG_CALLunary(sv, numer_amg);
-               if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
-                   return SvUV(tmpstr);
-               }
-           }
-           return PTR2UV(SvRV(sv));
-       }
+       if (ckWARN(WARN_UNINITIALIZED))
+           report_uninit(sv);
+       return 0;
+    }
+
+    if (SvTHINKFIRST(sv)) {
        if (SvIsCOW(sv)) {
            sv_force_normal_flags(sv, 0);
        }
@@ -2410,6 +2430,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags)
            return 0;
        }
     }
+
     if (!SvIOKp(sv)) {
        if (S_sv_2iuv_common(aTHX_ sv))
            return 0;
@@ -2424,7 +2445,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags)
 =for apidoc sv_2nv_flags
 
 Return the num value of an SV, doing any necessary string or integer
-conversion. If flags includes SV_GMAGIC, does an mg_get() first.
+conversion.  If flags includes SV_GMAGIC, does an mg_get() first.
 Normally used via the C<SvNV(sv)> and C<SvNVx(sv)> macros.
 
 =cut
@@ -2623,7 +2644,7 @@ Perl_sv_2nv_flags(pTHX_ register SV *const sv, const I32 flags)
            return 0.0;
        }
 
-       if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
+       if (!PL_localizing && !SvPADTMP(sv) && ckWARN(WARN_UNINITIALIZED))
            report_uninit(sv);
        assert (SvTYPE(sv) >= SVt_NV);
        /* Typically the caller expects that sv_any is not NULL now.  */
@@ -2713,10 +2734,9 @@ S_uiv_2buf(char *const buf, const IV iv, UV uv, const int is_uv, char **const pe
 =for apidoc sv_2pv_flags
 
 Returns a pointer to the string value of an SV, and sets *lp to its length.
-If flags includes SV_GMAGIC, does an mg_get() first. Coerces sv to a string
-if necessary.
-Normally invoked via the C<SvPV_flags> macro. C<sv_2pv()> and C<sv_2pv_nomg>
-usually end up here too.
+If flags includes SV_GMAGIC, does an mg_get() first.  Coerces sv to a
+string if necessary.  Normally invoked via the C<SvPV_flags> macro.
+C<sv_2pv()> and C<sv_2pv_nomg> usually end up here too.
 
 =cut
 */
@@ -2732,191 +2752,143 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
            *lp = 0;
        return (char *)"";
     }
-    if (SvGMAGICAL(sv)) {
-       if (flags & SV_GMAGIC)
-           mg_get(sv);
-       if (SvPOKp(sv)) {
-           if (lp)
-               *lp = SvCUR(sv);
-           if (flags & SV_MUTABLE_RETURN)
-               return SvPVX_mutable(sv);
-           if (flags & SV_CONST_RETURN)
-               return (char *)SvPVX_const(sv);
-           return SvPVX(sv);
-       }
-       if (SvIOKp(sv) || SvNOKp(sv)) {
-           char tbuf[64];  /* Must fit sprintf/Gconvert of longest IV/NV */
-           STRLEN len;
-
-           if (SvIOKp(sv)) {
-               len = SvIsUV(sv)
-                   ? my_snprintf(tbuf, sizeof(tbuf), "%"UVuf, (UV)SvUVX(sv))
-                   : my_snprintf(tbuf, sizeof(tbuf), "%"IVdf, (IV)SvIVX(sv));
-           } else if(SvNVX(sv) == 0.0) {
-                   tbuf[0] = '0';
-                   tbuf[1] = 0;
-                   len = 1;
-           } else {
-               Gconvert(SvNVX(sv), NV_DIG, 0, tbuf);
-               len = strlen(tbuf);
-           }
-           assert(!SvROK(sv));
-           {
-               dVAR;
+    if (SvGMAGICAL(sv) && (flags & SV_GMAGIC))
+       mg_get(sv);
+    if (SvROK(sv)) {
+       if (SvAMAGIC(sv)) {
+           SV *tmpstr;
+           if (flags & SV_SKIP_OVERLOAD)
+               return NULL;
+           tmpstr = AMG_CALLunary(sv, string_amg);
+           TAINT_IF(tmpstr && SvTAINTED(tmpstr));
+           if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
+               /* Unwrap this:  */
+               /* char *pv = lp ? SvPV(tmpstr, *lp) : SvPV_nolen(tmpstr);
+                */
 
-               SvUPGRADE(sv, SVt_PV);
-               if (lp)
-                   *lp = len;
-               s = SvGROW_mutable(sv, len + 1);
-               SvCUR_set(sv, len);
-               SvPOKp_on(sv);
-               return (char*)memcpy(s, tbuf, len + 1);
-           }
-       }
-        if (SvROK(sv)) {
-           goto return_rok;
-       }
-       assert(SvTYPE(sv) >= SVt_PVMG);
-       /* This falls through to the report_uninit near the end of the
-          function. */
-    } else if (SvTHINKFIRST(sv)) {
-       if (SvROK(sv)) {
-       return_rok:
-            if (SvAMAGIC(sv)) {
-               SV *tmpstr;
-               if (flags & SV_SKIP_OVERLOAD)
-                   return NULL;
-               tmpstr = AMG_CALLunary(sv, string_amg);
-               TAINT_IF(tmpstr && SvTAINTED(tmpstr));
-               if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
-                   /* Unwrap this:  */
-                   /* char *pv = lp ? SvPV(tmpstr, *lp) : SvPV_nolen(tmpstr);
-                    */
-
-                   char *pv;
-                   if ((SvFLAGS(tmpstr) & (SVf_POK)) == SVf_POK) {
-                       if (flags & SV_CONST_RETURN) {
-                           pv = (char *) SvPVX_const(tmpstr);
-                       } else {
-                           pv = (flags & SV_MUTABLE_RETURN)
-                               ? SvPVX_mutable(tmpstr) : SvPVX(tmpstr);
-                       }
-                       if (lp)
-                           *lp = SvCUR(tmpstr);
+               char *pv;
+               if ((SvFLAGS(tmpstr) & (SVf_POK)) == SVf_POK) {
+                   if (flags & SV_CONST_RETURN) {
+                       pv = (char *) SvPVX_const(tmpstr);
                    } else {
-                       pv = sv_2pv_flags(tmpstr, lp, flags);
+                       pv = (flags & SV_MUTABLE_RETURN)
+                           ? SvPVX_mutable(tmpstr) : SvPVX(tmpstr);
                    }
-                   if (SvUTF8(tmpstr))
-                       SvUTF8_on(sv);
-                   else
-                       SvUTF8_off(sv);
-                   return pv;
+                   if (lp)
+                       *lp = SvCUR(tmpstr);
+               } else {
+                   pv = sv_2pv_flags(tmpstr, lp, flags);
                }
+               if (SvUTF8(tmpstr))
+                   SvUTF8_on(sv);
+               else
+                   SvUTF8_off(sv);
+               return pv;
            }
-           {
-               STRLEN len;
-               char *retval;
-               char *buffer;
-               SV *const referent = SvRV(sv);
-
-               if (!referent) {
-                   len = 7;
-                   retval = buffer = savepvn("NULLREF", len);
-               } else if (SvTYPE(referent) == SVt_REGEXP) {
-                   REGEXP * const re = (REGEXP *)MUTABLE_PTR(referent);
-                   I32 seen_evals = 0;
-
-                   assert(re);
+       }
+       {
+           STRLEN len;
+           char *retval;
+           char *buffer;
+           SV *const referent = SvRV(sv);
+
+           if (!referent) {
+               len = 7;
+               retval = buffer = savepvn("NULLREF", len);
+           } else if (SvTYPE(referent) == SVt_REGEXP &&
+                      (!(PL_curcop->cop_hints & HINT_NO_AMAGIC) ||
+                       amagic_is_enabled(string_amg))) {
+               REGEXP * const re = (REGEXP *)MUTABLE_PTR(referent);
+
+               assert(re);
                        
-                   /* If the regex is UTF-8 we want the containing scalar to
-                      have an UTF-8 flag too */
-                   if (RX_UTF8(re))
-                       SvUTF8_on(sv);
-                   else
-                       SvUTF8_off(sv); 
-
-                   if ((seen_evals = RX_SEEN_EVALS(re)))
-                       PL_reginterp_cnt += seen_evals;
+               /* If the regex is UTF-8 we want the containing scalar to
+                  have an UTF-8 flag too */
+               if (RX_UTF8(re))
+                   SvUTF8_on(sv);
+               else
+                   SvUTF8_off(sv);     
 
-                   if (lp)
-                       *lp = RX_WRAPLEN(re);
+               if (lp)
+                   *lp = RX_WRAPLEN(re);
  
-                   return RX_WRAPPED(re);
-               } else {
-                   const char *const typestr = sv_reftype(referent, 0);
-                   const STRLEN typelen = strlen(typestr);
-                   UV addr = PTR2UV(referent);
-                   const char *stashname = NULL;
-                   STRLEN stashnamelen = 0; /* hush, gcc */
-                   const char *buffer_end;
-
-                   if (SvOBJECT(referent)) {
-                       const HEK *const name = HvNAME_HEK(SvSTASH(referent));
-
-                       if (name) {
-                           stashname = HEK_KEY(name);
-                           stashnamelen = HEK_LEN(name);
-
-                           if (HEK_UTF8(name)) {
-                               SvUTF8_on(sv);
-                           } else {
-                               SvUTF8_off(sv);
-                           }
+               return RX_WRAPPED(re);
+           } else {
+               const char *const typestr = sv_reftype(referent, 0);
+               const STRLEN typelen = strlen(typestr);
+               UV addr = PTR2UV(referent);
+               const char *stashname = NULL;
+               STRLEN stashnamelen = 0; /* hush, gcc */
+               const char *buffer_end;
+
+               if (SvOBJECT(referent)) {
+                   const HEK *const name = HvNAME_HEK(SvSTASH(referent));
+
+                   if (name) {
+                       stashname = HEK_KEY(name);
+                       stashnamelen = HEK_LEN(name);
+
+                       if (HEK_UTF8(name)) {
+                           SvUTF8_on(sv);
                        } else {
-                           stashname = "__ANON__";
-                           stashnamelen = 8;
+                           SvUTF8_off(sv);
                        }
-                       len = stashnamelen + 1 /* = */ + typelen + 3 /* (0x */
-                           + 2 * sizeof(UV) + 2 /* )\0 */;
                    } else {
-                       len = typelen + 3 /* (0x */
-                           + 2 * sizeof(UV) + 2 /* )\0 */;
-                   }
-
-                   Newx(buffer, len, char);
-                   buffer_end = retval = buffer + len;
-
-                   /* Working backwards  */
-                   *--retval = '\0';
-                   *--retval = ')';
-                   do {
-                       *--retval = PL_hexdigit[addr & 15];
-                   } while (addr >>= 4);
-                   *--retval = 'x';
-                   *--retval = '0';
-                   *--retval = '(';
-
-                   retval -= typelen;
-                   memcpy(retval, typestr, typelen);
-
-                   if (stashname) {
-                       *--retval = '=';
-                       retval -= stashnamelen;
-                       memcpy(retval, stashname, stashnamelen);
+                       stashname = "__ANON__";
+                       stashnamelen = 8;
                    }
-                   /* retval may not necessarily have reached the start of the
-                      buffer here.  */
-                   assert (retval >= buffer);
+                   len = stashnamelen + 1 /* = */ + typelen + 3 /* (0x */
+                       + 2 * sizeof(UV) + 2 /* )\0 */;
+               } else {
+                   len = typelen + 3 /* (0x */
+                       + 2 * sizeof(UV) + 2 /* )\0 */;
+               }
 
-                   len = buffer_end - retval - 1; /* -1 for that \0  */
+               Newx(buffer, len, char);
+               buffer_end = retval = buffer + len;
+
+               /* Working backwards  */
+               *--retval = '\0';
+               *--retval = ')';
+               do {
+                   *--retval = PL_hexdigit[addr & 15];
+               } while (addr >>= 4);
+               *--retval = 'x';
+               *--retval = '0';
+               *--retval = '(';
+
+               retval -= typelen;
+               memcpy(retval, typestr, typelen);
+
+               if (stashname) {
+                   *--retval = '=';
+                   retval -= stashnamelen;
+                   memcpy(retval, stashname, stashnamelen);
                }
-               if (lp)
-                   *lp = len;
-               SAVEFREEPV(buffer);
-               return retval;
+               /* retval may not necessarily have reached the start of the
+                  buffer here.  */
+               assert (retval >= buffer);
+
+               len = buffer_end - retval - 1; /* -1 for that \0  */
            }
-       }
-       if (SvREADONLY(sv) && !SvOK(sv)) {
            if (lp)
-               *lp = 0;
-           if (flags & SV_UNDEF_RETURNS_NULL)
-               return NULL;
-           if (ckWARN(WARN_UNINITIALIZED))
-               report_uninit(sv);
-           return (char *)"";
+               *lp = len;
+           SAVEFREEPV(buffer);
+           return retval;
        }
     }
-    if (SvIOK(sv) || ((SvIOKp(sv) && !SvNOKp(sv)))) {
+
+    if (SvPOKp(sv)) {
+       if (lp)
+           *lp = SvCUR(sv);
+       if (flags & SV_MUTABLE_RETURN)
+           return SvPVX_mutable(sv);
+       if (flags & SV_CONST_RETURN)
+           return (char *)SvPVX_const(sv);
+       return SvPVX(sv);
+    }
+
+    if (SvIOK(sv)) {
        /* I'm assuming that if both IV and NV are equally valid then
           converting the IV is going to be more efficient */
        const U32 isUIOK = SvIsUV(sv);
@@ -2934,7 +2906,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
        s += len;
        *s = '\0';
     }
-    else if (SvNOKp(sv)) {
+    else if (SvNOK(sv)) {
        if (SvTYPE(sv) < SVt_PVNV)
            sv_upgrade(sv, SVt_PVNV);
        if (SvNVX(sv) == 0.0) {
@@ -2955,42 +2927,32 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
            *--s = '\0';
 #endif
     }
-    else {
-       if (isGV_with_GP(sv)) {
-           GV *const gv = MUTABLE_GV(sv);
-           const U32 wasfake = SvFLAGS(gv) & SVf_FAKE;
-           SV *const buffer = sv_newmortal();
-
-           /* FAKE globs can get coerced, so need to turn this off temporarily
-              if it is on.  */
-           SvFAKE_off(gv);
-           gv_efullname3(buffer, gv, "*");
-           SvFLAGS(gv) |= wasfake;
-
-           if (SvPOK(buffer)) {
-               if (lp) {
-                   *lp = SvCUR(buffer);
-               }
-               return SvPVX(buffer);
-           }
-           else {
-               if (lp)
-                   *lp = 0;
-               return (char *)"";
-           }
-       }
+    else if (isGV_with_GP(sv)) {
+       GV *const gv = MUTABLE_GV(sv);
+       SV *const buffer = sv_newmortal();
+
+       gv_efullname3(buffer, gv, "*");
 
+       assert(SvPOK(buffer));
+       if (SvUTF8(buffer))
+           SvUTF8_on(sv);
+       if (lp)
+           *lp = SvCUR(buffer);
+       return SvPVX(buffer);
+    }
+    else {
        if (lp)
            *lp = 0;
        if (flags & SV_UNDEF_RETURNS_NULL)
            return NULL;
-       if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
+       if (!PL_localizing && !SvPADTMP(sv) && ckWARN(WARN_UNINITIALIZED))
            report_uninit(sv);
-       if (SvTYPE(sv) < SVt_PV)
-           /* Typically the caller expects that sv_any is not NULL now.  */
+       /* Typically the caller expects that sv_any is not NULL now.  */
+       if (!SvREADONLY(sv) && SvTYPE(sv) < SVt_PV)
            sv_upgrade(sv, SVt_PV);
        return (char *)"";
     }
+
     {
        const STRLEN len = s - SvPVX_const(sv);
        if (lp) 
@@ -3018,17 +2980,37 @@ sv_2pv[_flags] but operates directly on an SV instead of just the
 string.  Mostly uses sv_2pv_flags to do its work, except when that
 would lose the UTF-8'ness of the PV.
 
+=for apidoc sv_copypv_nomg
+
+Like sv_copypv, but doesn't invoke get magic first.
+
+=for apidoc sv_copypv_flags
+
+Implementation of sv_copypv and sv_copypv_nomg.  Calls get magic iff flags
+include SV_GMAGIC.
+
 =cut
 */
 
 void
 Perl_sv_copypv(pTHX_ SV *const dsv, register SV *const ssv)
 {
+    PERL_ARGS_ASSERT_SV_COPYPV;
+
+    sv_copypv_flags(dsv, ssv, 0);
+}
+
+void
+Perl_sv_copypv_flags(pTHX_ SV *const dsv, register SV *const ssv, const I32 flags)
+{
     STRLEN len;
-    const char * const s = SvPV_const(ssv,len);
+    const char *s;
 
-    PERL_ARGS_ASSERT_SV_COPYPV;
+    PERL_ARGS_ASSERT_SV_COPYPV_FLAGS;
 
+    if ((flags & SV_GMAGIC) && SvGMAGICAL(ssv))
+       mg_get(ssv);
+    s = SvPV_nomg_const(ssv,len);
     sv_setpvn(dsv,s,len);
     if (SvUTF8(ssv))
        SvUTF8_on(dsv);
@@ -3049,11 +3031,17 @@ Usually accessed via the C<SvPVbyte> macro.
 */
 
 char *
-Perl_sv_2pvbyte(pTHX_ register SV *const sv, STRLEN *const lp)
+Perl_sv_2pvbyte(pTHX_ register 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 = sv2;
+    }
+    else SvGETMAGIC(sv);
     sv_utf8_downgrade(sv,0);
     return lp ? SvPV_nomg(sv,*lp) : SvPV_nomg_nolen(sv);
 }
@@ -3070,12 +3058,17 @@ Usually accessed via the C<SvPVutf8> macro.
 */
 
 char *
-Perl_sv_2pvutf8(pTHX_ register SV *const sv, STRLEN *const lp)
+Perl_sv_2pvutf8(pTHX_ register SV *sv, STRLEN *const lp)
 {
     PERL_ARGS_ASSERT_SV_2PVUTF8;
 
-    sv_utf8_upgrade(sv);
-    return lp ? SvPV(sv,*lp) : SvPV_nolen(sv);
+    if (((SvREADONLY(sv) || SvFAKE(sv)) && !SvIsCOW(sv))
+     || isGV_with_GP(sv) || SvROK(sv))
+       sv = sv_mortalcopy(sv);
+    else
+        SvGETMAGIC(sv);
+    sv_utf8_upgrade_nomg(sv);
+    return lp ? SvPV_nomg(sv,*lp) : SvPV_nomg_nolen(sv);
 }
 
 
@@ -3089,7 +3082,7 @@ It calls sv_2bool_flags with the SV_GMAGIC flag.
 =for apidoc sv_2bool_flags
 
 This function is only used by sv_true() and friends,  and only if
-the latter's argument is neither SvPOK, SvIOK nor SvNOK. If the flags
+the latter's argument is neither SvPOK, SvIOK nor SvNOK.  If the flags
 contain SV_GMAGIC, then it does an mg_get() first.
 
 
@@ -3115,30 +3108,7 @@ Perl_sv_2bool_flags(pTHX_ register SV *const sv, const I32 flags)
        }
        return SvRV(sv) != 0;
     }
-    if (SvPOKp(sv)) {
-       register XPV* const Xpvtmp = (XPV*)SvANY(sv);
-       if (Xpvtmp &&
-               (*sv->sv_u.svu_pv > '0' ||
-               Xpvtmp->xpv_cur > 1 ||
-               (Xpvtmp->xpv_cur && *sv->sv_u.svu_pv != '0')))
-           return 1;
-       else
-           return 0;
-    }
-    else {
-       if (SvIOKp(sv))
-           return SvIVX(sv) != 0;
-       else {
-           if (SvNOKp(sv))
-               return SvNVX(sv) != 0.0;
-           else {
-               if (isGV_with_GP(sv))
-                   return TRUE;
-               else
-                   return FALSE;
-           }
-       }
-    }
+    return SvTRUE_common(sv, isGV_with_GP(sv) ? 1 : 0);
 }
 
 /*
@@ -3156,14 +3126,15 @@ use the Encode extension for that.
 
 =for apidoc sv_utf8_upgrade_nomg
 
-Like sv_utf8_upgrade, but doesn't do magic on C<sv>
+Like sv_utf8_upgrade, but doesn't do magic on C<sv>.
 
 =for apidoc sv_utf8_upgrade_flags
 
 Converts the PV of an SV to its UTF-8-encoded form.
 Forces the SV to string form if it is not already.
 Always sets the SvUTF8 flag to avoid future validity checks even
-if all the bytes are invariant in UTF-8. If C<flags> has C<SV_GMAGIC> bit set,
+if all the bytes are invariant in UTF-8.
+If C<flags> has C<SV_GMAGIC> bit set,
 will C<mg_get> on C<sv> if appropriate, else not.
 Returns the number of bytes in the converted string
 C<sv_utf8_upgrade> and
@@ -3273,6 +3244,7 @@ Perl_sv_utf8_upgrade_flags_grow(pTHX_ register SV *const sv, const I32 flags, ST
        /* utf8 conversion not needed because all are invariants.  Mark as
         * UTF-8 even if no variant - saves scanning loop */
        SvUTF8_on(sv);
+       if (extra) SvGROW(sv, SvCUR(sv) + extra);
        return SvCUR(sv);
 
 must_be_utf8:
@@ -3542,11 +3514,8 @@ Perl_sv_utf8_encode(pTHX_ register SV *const sv)
 {
     PERL_ARGS_ASSERT_SV_UTF8_ENCODE;
 
-    if (SvIsCOW(sv)) {
-        sv_force_normal_flags(sv, 0);
-    }
     if (SvREADONLY(sv)) {
-       Perl_croak_no_modify(aTHX);
+       sv_force_normal_flags(sv, 0);
     }
     (void) sv_utf8_upgrade(sv);
     SvUTF8_off(sv);
@@ -3557,7 +3526,7 @@ Perl_sv_utf8_encode(pTHX_ register SV *const sv)
 
 If the PV of the SV is an octet sequence in UTF-8
 and contains a multiple-byte character, the C<SvUTF8> flag is turned on
-so that it looks like a character. If the PV contains only single-byte
+so that it looks like a character.  If the PV contains only single-byte
 characters, the C<SvUTF8> flag stays off.
 Scans PV for validity and returns false if the PV is invalid UTF-8.
 
@@ -3583,7 +3552,7 @@ Perl_sv_utf8_decode(pTHX_ register SV *const sv)
          * we want to make sure everything inside is valid utf8 first.
          */
         c = start = (const U8 *) SvPVX_const(sv);
-       if (!is_utf8_string(c, SvCUR(sv)+1))
+       if (!is_utf8_string(c, SvCUR(sv)))
            return FALSE;
         e = (const U8 *) SvEND(sv);
         while (c < e) {
@@ -3618,7 +3587,7 @@ Perl_sv_utf8_decode(pTHX_ register SV *const sv)
 
 Copies the contents of the source SV C<ssv> into the destination SV
 C<dsv>.  The source SV may be destroyed if it is mortal, so don't use this
-function if the source SV needs to be reused. Does not handle 'set' magic.
+function if the source SV needs to be reused.  Does not handle 'set' magic.
 Loosely speaking, it performs a copy-by-value, obliterating any previous
 content of the destination.
 
@@ -3630,12 +3599,13 @@ C<SvSetMagicSV_nosteal>.
 
 Copies the contents of the source SV C<ssv> into the destination SV
 C<dsv>.  The source SV may be destroyed if it is mortal, so don't use this
-function if the source SV needs to be reused. Does not handle 'set' magic.
+function if the source SV needs to be reused.  Does not handle 'set' magic.
 Loosely speaking, it performs a copy-by-value, obliterating any previous
 content of the destination.
 If the C<flags> parameter has the C<SV_GMAGIC> bit set, will C<mg_get> on
-C<ssv> if appropriate, else not. If the C<flags> parameter has the
-C<NOSTEAL> bit set then the buffers of temps will not be stolen. <sv_setsv>
+C<ssv> if appropriate, else not.  If the C<flags>
+parameter has the C<NOSTEAL> bit set then the
+buffers of temps will not be stolen.  <sv_setsv>
 and C<sv_setsv_nomg> are implemented in terms of this function.
 
 You probably want to use one of the assortment of wrappers, such as
@@ -3668,14 +3638,15 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
            }
            SvUPGRADE(dstr, SVt_PVGV);
            (void)SvOK_off(dstr);
-           /* FIXME - why are we doing this, then turning it off and on again
-              below */
+           /* We have to turn this on here, even though we turn it off
+              below, as GvSTASH will fail an assertion otherwise. */
            isGV_with_GP_on(dstr);
        }
        GvSTASH(dstr) = GvSTASH(sstr);
        if (GvSTASH(dstr))
            Perl_sv_add_backref(aTHX_ MUTABLE_SV(GvSTASH(dstr)), dstr);
-       gv_name_set(MUTABLE_GV(dstr), name, len, GV_ADD);
+        gv_name_set(MUTABLE_GV(dstr), name, len,
+                        GV_ADD | (GvNAMEUTF8(sstr) ? SVf_UTF8 : 0 ));
        SvFAKE_on(dstr);        /* can coerce to non-glob */
     }
 
@@ -3703,7 +3674,7 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
         mro_changes = 1;
     }
 
-    /* We don’t need to check the name of the destination if it was not a
+    /* We don't need to check the name of the destination if it was not a
        glob to begin with. */
     if(dtype == SVt_PVGV) {
         const char * const name = GvNAME((const GV *)dstr);
@@ -3712,7 +3683,6 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
          /* The stash may have been detached from the symbol table, so
             check its name. */
          && GvSTASH(dstr) && HvENAME(GvSTASH(dstr))
-         && GvAV((const GV *)sstr)
         )
             mro_changes = 2;
         else {
@@ -3733,7 +3703,7 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
     }
 
     gp_free(MUTABLE_GV(dstr));
-    isGV_with_GP_off(dstr);
+    isGV_with_GP_off(dstr); /* SvOK_off does not like globs. */
     (void)SvOK_off(dstr);
     isGV_with_GP_on(dstr);
     GvINTRO_off(dstr);         /* one-shot flag */
@@ -3747,6 +3717,7 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
        }
     GvMULTI_on(dstr);
     if(mro_changes == 2) {
+      if (GvAV((const GV *)sstr)) {
        MAGIC *mg;
        SV * const sref = (SV *)GvAV((const GV *)dstr);
        if (SvSMAGICAL(sref) && (mg = mg_find(sref, PERL_MAGIC_isa))) {
@@ -3758,7 +3729,8 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
            av_push((AV *)mg->mg_obj, SvREFCNT_inc_simple_NN(dstr));
        }
        else sv_magic(sref, dstr, PERL_MAGIC_isa, NULL, 0);
-       mro_isa_changed_in(GvSTASH(dstr));
+      }
+      mro_isa_changed_in(GvSTASH(dstr));
     }
     else if(mro_changes == 3) {
        HV * const stash = GvHV(dstr);
@@ -3830,40 +3802,32 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
            CV* const cv = MUTABLE_CV(*location);
            if (cv) {
                if (!GvCVGEN((const GV *)dstr) &&
-                   (CvROOT(cv) || CvXSUB(cv)))
+                   (CvROOT(cv) || CvXSUB(cv)) &&
+                   /* redundant check that avoids creating the extra SV
+                      most of the time: */
+                   (CvCONST(cv) || ckWARN(WARN_REDEFINE)))
                    {
-                       /* Redefining a sub - warning is mandatory if
-                          it was a const and its value changed. */
-                       if (CvCONST(cv) && CvCONST((const CV *)sref)
-                           && cv_const_sv(cv)
-                           == cv_const_sv((const CV *)sref)) {
-                           NOOP;
-                           /* They are 2 constant subroutines generated from
-                              the same constant. This probably means that
-                              they are really the "same" proxy subroutine
-                              instantiated in 2 places. Most likely this is
-                              when a constant is exported twice.  Don't warn.
-                           */
-                       }
-                       else if (ckWARN(WARN_REDEFINE)
-                                || (CvCONST(cv)
-                                    && (!CvCONST((const CV *)sref)
-                                        || sv_cmp(cv_const_sv(cv),
-                                                  cv_const_sv((const CV *)
-                                                              sref))))) {
-                           Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
-                                       (const char *)
-                                       (CvCONST(cv)
-                                        ? "Constant subroutine %s::%s redefined"
-                                        : "Subroutine %s::%s redefined"),
-                                       HvNAME_get(GvSTASH((const GV *)dstr)),
-                                       GvENAME(MUTABLE_GV(dstr)));
-                       }
+                       SV * const new_const_sv =
+                           CvCONST((const CV *)sref)
+                                ? cv_const_sv((const CV *)sref)
+                                : NULL;
+                       report_redefined_cv(
+                          sv_2mortal(Perl_newSVpvf(aTHX_
+                               "%"HEKf"::%"HEKf,
+                               HEKfARG(
+                                HvNAME_HEK(GvSTASH((const GV *)dstr))
+                               ),
+                               HEKfARG(GvENAME_HEK(MUTABLE_GV(dstr)))
+                          )),
+                          cv,
+                          CvCONST((const CV *)sref) ? &new_const_sv : NULL
+                       );
                    }
                if (!intro)
-                   cv_ckproto_len(cv, (const GV *)dstr,
-                                  SvPOK(sref) ? SvPVX_const(sref) : NULL,
-                                  SvPOK(sref) ? SvCUR(sref) : 0);
+                   cv_ckproto_len_flags(cv, (const GV *)dstr,
+                                  SvPOK(sref) ? CvPROTO(sref) : NULL,
+                                  SvPOK(sref) ? CvPROTOLEN(sref) : 0,
+                                   SvPOK(sref) ? SvUTF8(sref) : 0);
            }
            GvCVGEN(dstr) = 0; /* Switch off cacheness. */
            GvASSUMECV_on(dstr);
@@ -3934,7 +3898,7 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
                mg = mg_find(sref, PERL_MAGIC_isa);
            }
            /* Since the *ISA assignment could have affected more than
-              one stash, don’t call mro_isa_changed_in directly, but let
+              one stash, don't call mro_isa_changed_in directly, but let
               magic_clearisa do it for us, as it already has the logic for
               dealing with globs vs arrays of globs. */
            assert(mg);
@@ -3975,13 +3939,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
     stype = SvTYPE(sstr);
     dtype = SvTYPE(dstr);
 
-    (void)SvAMAGIC_off(dstr);
-    if ( SvVOK(dstr) )
-    {
-       /* need to nuke the magic */
-       mg_free(dstr);
-    }
-
     /* There's a lot of redundancy below but we're going for speed here */
 
     switch (stype) {
@@ -4074,6 +4031,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
        {
        const char * const type = sv_reftype(sstr,0);
        if (PL_op)
+           /* diag_listed_as: Bizarre copy of %s */
            Perl_croak(aTHX_ "Bizarre copy of %s in %s", type, OP_DESC(PL_op));
        else
            Perl_croak(aTHX_ "Bizarre copy of %s", type);
@@ -4120,12 +4078,14 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
             SvCUR_set(dstr, len);
            SvPOK_only(dstr);
            SvFLAGS(dstr) |= sflags & SVf_UTF8;
+           CvAUTOLOAD_off(dstr);
        } else {
            SvOK_off(dstr);
        }
     } else if (dtype == SVt_PVAV || dtype == SVt_PVHV) {
        const char * const type = sv_reftype(dstr,0);
        if (PL_op)
+           /* diag_listed_as: Cannot copy to %s */
            Perl_croak(aTHX_ "Cannot copy to %s in %s", type, OP_DESC(PL_op));
        else
            Perl_croak(aTHX_ "Cannot copy to %s", type);
@@ -4171,7 +4131,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
                           "Undefined value assigned to typeglob");
        }
        else {
-           GV *gv = gv_fetchsv(sstr, GV_ADD, SVt_PVGV);
+           GV *gv = gv_fetchsv_nomg(sstr, GV_ADD, SVt_PVGV);
            if (dstr != (const SV *)gv) {
                const char * const name = GvNAME((const GV *)dstr);
                const STRLEN len = GvNAMELEN(dstr);
@@ -4378,15 +4338,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
     }
     else {
        if (isGV_with_GP(sstr)) {
-           /* This stringification rule for globs is spread in 3 places.
-              This feels bad. FIXME.  */
-           const U32 wasfake = sflags & SVf_FAKE;
-
-           /* FAKE globs can get coerced, so need to turn this off
-              temporarily if it is on.  */
-           SvFAKE_off(sstr);
            gv_efullname3(dstr, MUTABLE_GV(sstr), "*");
-           SvFLAGS(sstr) |= wasfake;
        }
        else
            (void)SvOK_off(dstr);
@@ -4510,7 +4462,8 @@ Perl_sv_setpvn(pTHX_ register SV *const sv, register const char *const ptr, regi
         /* len is STRLEN which is unsigned, need to copy to signed */
        const IV iv = len;
        if (iv < 0)
-           Perl_croak(aTHX_ "panic: sv_setpvn called with negative strlen");
+           Perl_croak(aTHX_ "panic: sv_setpvn called with negative strlen %"
+                      IVdf, iv);
     }
     SvUPGRADE(sv, SVt_PV);
 
@@ -4520,6 +4473,7 @@ Perl_sv_setpvn(pTHX_ register SV *const sv, register const char *const ptr, regi
     SvCUR_set(sv, len);
     (void)SvPOK_only_UTF8(sv);         /* validate pointer */
     SvTAINT(sv);
+    if (SvTYPE(sv) == SVt_PVCV) CvAUTOLOAD_off(sv);
 }
 
 /*
@@ -4569,6 +4523,7 @@ Perl_sv_setpv(pTHX_ register SV *const sv, register const char *const ptr)
     SvCUR_set(sv, len);
     (void)SvPOK_only_UTF8(sv);         /* validate pointer */
     SvTAINT(sv);
+    if (SvTYPE(sv) == SVt_PVCV) CvAUTOLOAD_off(sv);
 }
 
 /*
@@ -4588,22 +4543,71 @@ Perl_sv_setpv_mg(pTHX_ register SV *const sv, register const char *const ptr)
     SvSETMAGIC(sv);
 }
 
+void
+Perl_sv_sethek(pTHX_ register SV *const sv, const HEK *const hek)
+{
+    dVAR;
+
+    PERL_ARGS_ASSERT_SV_SETHEK;
+
+    if (!hek) {
+       return;
+    }
+
+    if (HEK_LEN(hek) == HEf_SVKEY) {
+       sv_setsv(sv, *(SV**)HEK_KEY(hek));
+        return;
+    } else {
+       const int flags = HEK_FLAGS(hek);
+       if (flags & HVhek_WASUTF8) {
+           STRLEN utf8_len = HEK_LEN(hek);
+           char *as_utf8 = (char *)bytes_to_utf8((U8*)HEK_KEY(hek), &utf8_len);
+           sv_usepvn_flags(sv, as_utf8, utf8_len, SV_HAS_TRAILING_NUL);
+           SvUTF8_on(sv);
+            return;
+       } else if (flags & (HVhek_REHASH|HVhek_UNSHARED)) {
+           sv_setpvn(sv, HEK_KEY(hek), HEK_LEN(hek));
+           if (HEK_UTF8(hek))
+               SvUTF8_on(sv);
+           else SvUTF8_off(sv);
+            return;
+       }
+        {
+           SV_CHECK_THINKFIRST_COW_DROP(sv);
+           SvUPGRADE(sv, SVt_PV);
+           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);
+           SvPOK_on(sv);
+           if (HEK_UTF8(hek))
+               SvUTF8_on(sv);
+           else SvUTF8_off(sv);
+            return;
+       }
+    }
+}
+
+
 /*
 =for apidoc sv_usepvn_flags
 
 Tells an SV to use C<ptr> to find its string value.  Normally the
 string is stored inside the SV but sv_usepvn allows the SV to use an
 outside string.  The C<ptr> should point to memory that was allocated
-by C<malloc>.  The string length, C<len>, must be supplied.  By default
+by C<malloc>.  It must be the start of a mallocked block
+of memory, and not a pointer to the middle of it.  The
+string length, C<len>, must be supplied.  By default
 this function will realloc (i.e. move) the memory pointed to by C<ptr>,
 so that pointer should not be freed or used by the programmer after
 giving it to sv_usepvn, and neither should any pointers from "behind"
 that pointer (e.g. ptr + 1) be used.
 
-If C<flags> & SV_SMAGIC is true, will call SvSETMAGIC. If C<flags> &
+If C<flags> & SV_SMAGIC is true, will call SvSETMAGIC.  If C<flags> &
 SV_HAS_TRAILING_NUL is true, then C<ptr[len]> must be NUL, and the realloc
-will be skipped. (i.e. the buffer is actually at least 1 byte longer than
-C<len>, and already meets the requirements for storing in C<SvPVX>)
+will be skipped (i.e. the buffer is actually at least 1 byte longer than
+C<len>, and already meets the requirements for storing in C<SvPVX>).
 
 =cut
 */
@@ -4711,14 +4715,17 @@ S_sv_release_COW(pTHX_ register SV *sv, const char *pvx, SV *after)
 /*
 =for apidoc sv_force_normal_flags
 
-Undo various types of fakery on an SV: if the PV is a shared string, make
+Undo various types of fakery on an SV, where fakery means
+"more than" a string: if the PV is a shared string, make
 a private copy; if we're a ref, stop refing; if we're a glob, downgrade to
 an xpvmg; if we're a copy-on-write scalar, this is the on-write time when
-we do the copy, and is also used locally. If C<SV_COW_DROP_PV> is set
+we do the copy, and is also used locally; if this is a
+vstring, drop the vstring magic.  If C<SV_COW_DROP_PV> is set
 then a copy-on-write scalar drops its PV buffer (if any) and becomes
-SvPOK_off rather than making a copy. (Used where this scalar is about to be
-set to some other value.) In addition, the C<flags> parameter gets passed to
-C<sv_unref_flags()> when unreffing. C<sv_force_normal> calls this function
+SvPOK_off rather than making a copy.  (Used where this
+scalar is about to be set to some other value.)  In addition,
+the C<flags> parameter gets passed to C<sv_unref_flags()>
+when unreffing.  C<sv_force_normal> calls this function
 with flags set to 0.
 
 =cut
@@ -4776,16 +4783,21 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
     }
 #else
     if (SvREADONLY(sv)) {
-       if (SvFAKE(sv)) {
+       if (SvIsCOW(sv)) {
            const char * const pvx = SvPVX_const(sv);
            const STRLEN len = SvCUR(sv);
            SvFAKE_off(sv);
            SvREADONLY_off(sv);
            SvPV_set(sv, NULL);
            SvLEN_set(sv, 0);
-           SvGROW(sv, len + 1);
-           Move(pvx,SvPVX(sv),len,char);
-           *SvEND(sv) = '\0';
+           if (flags & SV_COW_DROP_PV) {
+               /* OK, so we don't need to copy our buffer.  */
+               SvPOK_off(sv);
+           } else {
+               SvGROW(sv, len + 1);
+               Move(pvx,SvPVX(sv),len,char);
+               *SvEND(sv) = '\0';
+           }
            unshare_hek(SvSHARED_HEK_FROM_PV(pvx));
        }
        else if (IN_PERL_RUNTIME)
@@ -4795,7 +4807,7 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
     if (SvROK(sv))
        sv_unref_flags(sv, flags);
     else if (SvFAKE(sv) && isGV_with_GP(sv))
-       sv_unglob(sv);
+       sv_unglob(sv, flags);
     else if (SvFAKE(sv) && SvTYPE(sv) == SVt_REGEXP) {
        /* Need to downgrade the REGEXP to a simple(r) scalar. This is analogous
           to sv_unglob. We only need it here, so inline it.  */
@@ -4835,18 +4847,25 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
 
        SvREFCNT_dec(temp);
     }
+    else if (SvVOK(sv)) sv_unmagic(sv, PERL_MAGIC_vstring);
 }
 
 /*
 =for apidoc sv_chop
 
 Efficient removal of characters from the beginning of the string buffer.
-SvPOK(sv) must be true and the C<ptr> must be a pointer to somewhere inside
-the string buffer.  The C<ptr> becomes the first character of the adjusted
-string. Uses the "OOK hack".
+SvPOK(sv), or at least SvPOKp(sv), must be true and the C<ptr> must be a
+pointer to somewhere inside the string buffer.  The C<ptr> becomes the first
+character of the adjusted string.  Uses the "OOK hack".  On return, only
+SvPOK(sv) and SvPOKp(sv) among the OK flags will be true.
+
 Beware: after this function returns, C<ptr> and SvPVX_const(sv) may no longer
 refer to the same chunk of data.
 
+The unfortunate similarity of this function's name to that of Perl's C<chop>
+operator is strictly coincidental.  This function works from the left;
+C<chop> works from the right.
+
 =cut
 */
 
@@ -4857,7 +4876,8 @@ Perl_sv_chop(pTHX_ register SV *const sv, register const char *const ptr)
     STRLEN old_delta;
     U8 *p;
 #ifdef DEBUGGING
-    const U8 *real_start;
+    const U8 *evacp;
+    STRLEN evacn;
 #endif
     STRLEN max_delta;
 
@@ -4870,17 +4890,13 @@ Perl_sv_chop(pTHX_ register SV *const sv, register const char *const ptr)
        /* Nothing to do.  */
        return;
     }
-    /* SvPVX(sv) may move in SV_CHECK_THINKFIRST(sv), but after this line,
-       nothing uses the value of ptr any more.  */
     max_delta = SvLEN(sv) ? SvLEN(sv) : SvCUR(sv);
-    if (ptr <= SvPVX_const(sv))
+    if (delta > max_delta)
        Perl_croak(aTHX_ "panic: sv_chop ptr=%p, start=%p, end=%p",
                   ptr, SvPVX_const(sv), SvPVX_const(sv) + max_delta);
+    /* SvPVX(sv) may move in SV_CHECK_THINKFIRST(sv), so don't use ptr any more */
     SV_CHECK_THINKFIRST(sv);
-    if (delta > max_delta)
-       Perl_croak(aTHX_ "panic: sv_chop ptr=%p (was %p), start=%p, end=%p",
-                  SvPVX_const(sv) + delta, ptr, SvPVX_const(sv),
-                  SvPVX_const(sv) + max_delta);
+    SvPOK_only_UTF8(sv);
 
     if (!SvOOK(sv)) {
        if (!SvLEN(sv)) { /* make copy of shared string */
@@ -4890,7 +4906,7 @@ Perl_sv_chop(pTHX_ register SV *const sv, register const char *const ptr)
            Move(pvx,SvPVX(sv),len,char);
            *SvEND(sv) = '\0';
        }
-       SvFLAGS(sv) |= SVf_OOK;
+       SvOOK_on(sv);
        old_delta = 0;
     } else {
        SvOOK_offset(sv, old_delta);
@@ -4901,12 +4917,18 @@ Perl_sv_chop(pTHX_ register SV *const sv, register const char *const ptr)
 
     p = (U8 *)SvPVX_const(sv);
 
-    delta += old_delta;
-
 #ifdef DEBUGGING
-    real_start = p - delta;
+    /* how many bytes were evacuated?  we will fill them with sentinel
+       bytes, except for the part holding the new offset of course. */
+    evacn = delta;
+    if (old_delta)
+       evacn += (old_delta < 0x100 ? 1 : 1 + sizeof(STRLEN));
+    assert(evacn);
+    assert(evacn <= delta + old_delta);
+    evacp = p - evacn;
 #endif
 
+    delta += old_delta;
     assert(delta);
     if (delta < 0x100) {
        *--p = (U8) delta;
@@ -4919,7 +4941,7 @@ Perl_sv_chop(pTHX_ register SV *const sv, register const char *const ptr)
 #ifdef DEBUGGING
     /* Fill the preceding buffer with sentinals to verify that no-one is
        using it.  */
-    while (p > real_start) {
+    while (p > evacp) {
        --p;
        *p = (U8)PTR2UV(p);
     }
@@ -4939,8 +4961,9 @@ Handles 'get' magic, but not 'set' magic.  See C<sv_catpvn_mg>.
 Concatenates the string onto the end of the string which is in the SV.  The
 C<len> indicates number of bytes to copy.  If the SV has the UTF-8
 status set, then the bytes appended should be valid UTF-8.
-If C<flags> has C<SV_GMAGIC> bit set, will C<mg_get> on C<dsv> if
-appropriate, else not. C<sv_catpvn> and C<sv_catpvn_nomg> are implemented
+If C<flags> has the C<SV_SMAGIC> bit set, will
+C<mg_set> on C<dsv> afterwards if appropriate.
+C<sv_catpvn> and C<sv_catpvn_nomg> are implemented
 in terms of this function.
 
 =cut
@@ -4954,12 +4977,43 @@ Perl_sv_catpvn_flags(pTHX_ register SV *const dsv, register const char *sstr, re
     const char * const dstr = SvPV_force_flags(dsv, dlen, flags);
 
     PERL_ARGS_ASSERT_SV_CATPVN_FLAGS;
+    assert((flags & (SV_CATBYTES|SV_CATUTF8)) != (SV_CATBYTES|SV_CATUTF8));
 
-    SvGROW(dsv, dlen + slen + 1);
-    if (sstr == dstr)
+    if (!(flags & SV_CATBYTES) || !SvUTF8(dsv)) {
+      if (flags & SV_CATUTF8 && !SvUTF8(dsv)) {
+        sv_utf8_upgrade_flags_grow(dsv, 0, slen + 1);
+        dlen = SvCUR(dsv);
+      }
+      else SvGROW(dsv, dlen + slen + 1);
+      if (sstr == dstr)
        sstr = SvPVX_const(dsv);
-    Move(sstr, SvPVX(dsv) + dlen, slen, char);
-    SvCUR_set(dsv, SvCUR(dsv) + slen);
+      Move(sstr, SvPVX(dsv) + dlen, slen, char);
+      SvCUR_set(dsv, SvCUR(dsv) + slen);
+    }
+    else {
+       /* We inline bytes_to_utf8, to avoid an extra malloc. */
+       const char * const send = sstr + slen;
+       U8 *d;
+
+       /* Something this code does not account for, which I think is
+          impossible; it would require the same pv to be treated as
+          bytes *and* utf8, which would indicate a bug elsewhere. */
+       assert(sstr != dstr);
+
+       SvGROW(dsv, dlen + slen * 2 + 1);
+       d = (U8 *)SvPVX(dsv) + dlen;
+
+       while (sstr < send) {
+           const UV uv = NATIVE_TO_ASCII((U8)*sstr++);
+           if (UNI_IS_INVARIANT(uv))
+               *d++ = (U8)UTF_TO_NATIVE(uv);
+           else {
+               *d++ = (U8)UTF8_EIGHT_BIT_HI(uv);
+               *d++ = (U8)UTF8_EIGHT_BIT_LO(uv);
+           }
+       }
+       SvCUR_set(dsv, d-(const U8 *)SvPVX(dsv));
+    }
     *SvEND(dsv) = '\0';
     (void)SvPOK_only_UTF8(dsv);                /* validate pointer */
     SvTAINT(dsv);
@@ -4970,16 +5024,19 @@ Perl_sv_catpvn_flags(pTHX_ register SV *const dsv, register const char *sstr, re
 /*
 =for apidoc sv_catsv
 
-Concatenates the string from SV C<ssv> onto the end of the string in
-SV C<dsv>.  Modifies C<dsv> but not C<ssv>.  Handles 'get' magic, but
-not 'set' magic.  See C<sv_catsv_mg>.
+Concatenates the string from SV C<ssv> onto the end of the string in SV
+C<dsv>.  If C<ssv> is null, does nothing; otherwise modifies only C<dsv>.
+Handles 'get' magic on both SVs, but no 'set' magic.  See C<sv_catsv_mg> and
+C<sv_catsv_nomg>.
 
 =for apidoc sv_catsv_flags
 
-Concatenates the string from SV C<ssv> onto the end of the string in
-SV C<dsv>.  Modifies C<dsv> but not C<ssv>.  If C<flags> has C<SV_GMAGIC>
-bit set, will C<mg_get> on the SVs if appropriate, else not. C<sv_catsv>
-and C<sv_catsv_nomg> are implemented in terms of this function.
+Concatenates the string from SV C<ssv> onto the end of the string in SV
+C<dsv>.  If C<ssv> is null, does nothing; otherwise modifies only C<dsv>.
+If C<flags> include C<SV_GMAGIC> bit set, will call C<mg_get> on both SVs if
+appropriate.  If C<flags> include C<SV_SMAGIC>, C<mg_set> will be called on
+the modified SV afterward, if appropriate.  C<sv_catsv>, C<sv_catsv_nomg>,
+and C<sv_catsv_mg> are implemented in terms of this function.
 
 =cut */
 
@@ -4990,41 +5047,18 @@ Perl_sv_catsv_flags(pTHX_ SV *const dsv, register SV *const ssv, const I32 flags
  
     PERL_ARGS_ASSERT_SV_CATSV_FLAGS;
 
-   if (ssv) {
+    if (ssv) {
        STRLEN slen;
        const char *spv = SvPV_flags_const(ssv, slen, flags);
        if (spv) {
-           /*  sutf8 and dutf8 were type bool, but under USE_ITHREADS,
-               gcc version 2.95.2 20000220 (Debian GNU/Linux) for
-               Linux xxx 2.2.17 on sparc64 with gcc -O2, we erroneously
-               get dutf8 = 0x20000000, (i.e.  SVf_UTF8) even though
-               dsv->sv_flags doesn't have that bit set.
-               Andy Dougherty  12 Oct 2001
-           */
-           const I32 sutf8 = DO_UTF8(ssv);
-           I32 dutf8;
-
-           if (SvGMAGICAL(dsv) && (flags & SV_GMAGIC))
-               mg_get(dsv);
-           dutf8 = DO_UTF8(dsv);
-
-           if (dutf8 != sutf8) {
-               if (dutf8) {
-                   /* Not modifying source SV, so taking a temporary copy. */
-                   SV* const csv = newSVpvn_flags(spv, slen, SVs_TEMP);
-
-                   sv_utf8_upgrade(csv);
-                   spv = SvPV_const(csv, slen);
-               }
-               else
-                   /* Leave enough space for the cat that's about to happen */
-                   sv_utf8_upgrade_flags_grow(dsv, 0, slen);
-           }
-           sv_catpvn_nomg(dsv, spv, slen);
-       }
+            if (flags & SV_GMAGIC)
+                SvGETMAGIC(dsv);
+           sv_catpvn_flags(dsv, spv, slen,
+                           DO_UTF8(ssv) ? SV_CATUTF8 : SV_CATBYTES);
+            if (flags & SV_SMAGIC)
+                SvSETMAGIC(dsv);
+        }
     }
-    if (flags & SV_SMAGIC)
-       SvSETMAGIC(dsv);
 }
 
 /*
@@ -5064,8 +5098,8 @@ Perl_sv_catpv(pTHX_ register SV *const sv, register const char *ptr)
 
 Concatenates the string onto the end of the string which is in the SV.
 If the SV has the UTF-8 status set, then the bytes appended should
-be valid UTF-8.  If C<flags> has C<SV_GMAGIC> bit set, will C<mg_get>
-on the SVs if appropriate, else not.
+be valid UTF-8.  If C<flags> has the C<SV_SMAGIC> bit set, will C<mg_set>
+on the modified SV if appropriate.
 
 =cut
 */
@@ -5105,7 +5139,7 @@ space is allocated.)  The reference count for the new SV is set to 1.
 In 5.9.3, newSV() replaces the older NEWSV() API, and drops the first
 parameter, I<x>, a debug aid which allowed callers to identify themselves.
 This aid has been superseded by a new build option, PERL_MEM_LOG (see
-L<perlhack/PERL_MEM_LOG>).  The older API is still there for use in XS
+L<perlhacktips/PERL_MEM_LOG>).  The older API is still there for use in XS
 modules supporting older perls.
 
 =cut
@@ -5127,7 +5161,7 @@ Perl_newSV(pTHX_ const STRLEN len)
 /*
 =for apidoc sv_magicext
 
-Adds magic to an SV, upgrading it if necessary. Applies the
+Adds magic to an SV, upgrading it if necessary.  Applies the
 supplied vtable and returns a pointer to the magic added.
 
 Note that C<sv_magicext> will allow things that C<sv_magic> will not.
@@ -5212,16 +5246,15 @@ Perl_sv_magicext(pTHX_ SV *const sv, SV *const obj, const int how,
     mg->mg_virtual = (MGVTBL *) vtable;
 
     mg_magical(sv);
-    if (SvGMAGICAL(sv))
-       SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK);
     return mg;
 }
 
 /*
 =for apidoc sv_magic
 
-Adds magic to an SV. First upgrades C<sv> to type C<SVt_PVMG> if necessary,
-then adds a new magic item of type C<how> to the head of the magic list.
+Adds magic to an SV.  First upgrades C<sv> to type C<SVt_PVMG> if
+necessary, then adds a new magic item of type C<how> to the head of the
+magic list.
 
 See C<sv_magicext> (which C<sv_magic> now calls) for a description of the
 handling of the C<name> and C<namlen> arguments.
@@ -5239,25 +5272,36 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how,
     dVAR;
     const MGVTBL *vtable;
     MAGIC* mg;
+    unsigned int flags;
+    unsigned int vtable_index;
 
     PERL_ARGS_ASSERT_SV_MAGIC;
 
+    if (how < 0 || (unsigned)how > C_ARRAY_LENGTH(PL_magic_data)
+       || ((flags = PL_magic_data[how]),
+           (vtable_index = flags & PERL_MAGIC_VTABLE_MASK)
+           > magic_vtable_max))
+       Perl_croak(aTHX_ "Don't know how to handle magic of type \\%o", how);
+
+    /* PERL_MAGIC_ext is reserved for use by extensions not perl internals.
+       Useful for attaching extension internal data to perl vars.
+       Note that multiple extensions may clash if magical scalars
+       etc holding private data from one are passed to another. */
+
+    vtable = (vtable_index == magic_vtable_max)
+       ? NULL : PL_magic_vtables + vtable_index;
+
 #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; the subsequent
-            * upgrade to PVMG will unshare the string */
-           !(SvFAKE(sv) && SvTYPE(sv) < SVt_PVMG)
+           /* its okay to attach magic to shared strings */
+           !SvIsCOW(sv)
 
            && IN_PERL_RUNTIME
-           && how != PERL_MAGIC_regex_global
-           && how != PERL_MAGIC_bm
-           && how != PERL_MAGIC_fm
-           && how != PERL_MAGIC_sv
-           && how != PERL_MAGIC_backref
+           && !PERL_MAGIC_TYPE_READONLY_ACCEPTABLE(how)
           )
        {
            Perl_croak_no_modify(aTHX);
@@ -5268,138 +5312,12 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how,
            /* sv_magic() refuses to add a magic of the same 'how' as an
               existing one
             */
-           if (how == PERL_MAGIC_taint) {
+           if (how == PERL_MAGIC_taint)
                mg->mg_len |= 1;
-               /* Any scalar which already had taint magic on which someone
-                  (erroneously?) did SvIOK_on() or similar will now be
-                  incorrectly sporting public "OK" flags.  */
-               SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK);
-           }
            return;
        }
     }
 
-    switch (how) {
-    case PERL_MAGIC_sv:
-       vtable = &PL_vtbl_sv;
-       break;
-    case PERL_MAGIC_overload:
-        vtable = &PL_vtbl_amagic;
-        break;
-    case PERL_MAGIC_overload_elem:
-        vtable = &PL_vtbl_amagicelem;
-        break;
-    case PERL_MAGIC_overload_table:
-        vtable = &PL_vtbl_ovrld;
-        break;
-    case PERL_MAGIC_bm:
-       vtable = &PL_vtbl_bm;
-       break;
-    case PERL_MAGIC_regdata:
-       vtable = &PL_vtbl_regdata;
-       break;
-    case PERL_MAGIC_regdatum:
-       vtable = &PL_vtbl_regdatum;
-       break;
-    case PERL_MAGIC_env:
-       vtable = &PL_vtbl_env;
-       break;
-    case PERL_MAGIC_fm:
-       vtable = &PL_vtbl_fm;
-       break;
-    case PERL_MAGIC_envelem:
-       vtable = &PL_vtbl_envelem;
-       break;
-    case PERL_MAGIC_regex_global:
-       vtable = &PL_vtbl_mglob;
-       break;
-    case PERL_MAGIC_isa:
-       vtable = &PL_vtbl_isa;
-       break;
-    case PERL_MAGIC_isaelem:
-       vtable = &PL_vtbl_isaelem;
-       break;
-    case PERL_MAGIC_nkeys:
-       vtable = &PL_vtbl_nkeys;
-       break;
-    case PERL_MAGIC_dbfile:
-       vtable = NULL;
-       break;
-    case PERL_MAGIC_dbline:
-       vtable = &PL_vtbl_dbline;
-       break;
-#ifdef USE_LOCALE_COLLATE
-    case PERL_MAGIC_collxfrm:
-        vtable = &PL_vtbl_collxfrm;
-        break;
-#endif /* USE_LOCALE_COLLATE */
-    case PERL_MAGIC_tied:
-       vtable = &PL_vtbl_pack;
-       break;
-    case PERL_MAGIC_tiedelem:
-    case PERL_MAGIC_tiedscalar:
-       vtable = &PL_vtbl_packelem;
-       break;
-    case PERL_MAGIC_qr:
-       vtable = &PL_vtbl_regexp;
-       break;
-#ifndef PERL_MICRO
-    case PERL_MAGIC_sigelem:
-       vtable = &PL_vtbl_sigelem;
-       break;
-#endif
-    case PERL_MAGIC_taint:
-       vtable = &PL_vtbl_taint;
-       break;
-    case PERL_MAGIC_uvar:
-       vtable = &PL_vtbl_uvar;
-       break;
-    case PERL_MAGIC_vec:
-       vtable = &PL_vtbl_vec;
-       break;
-    case PERL_MAGIC_sig:
-    case PERL_MAGIC_arylen_p:
-    case PERL_MAGIC_rhash:
-    case PERL_MAGIC_symtab:
-    case PERL_MAGIC_vstring:
-    case PERL_MAGIC_checkcall:
-       vtable = NULL;
-       break;
-    case PERL_MAGIC_utf8:
-       vtable = &PL_vtbl_utf8;
-       break;
-    case PERL_MAGIC_substr:
-       vtable = &PL_vtbl_substr;
-       break;
-    case PERL_MAGIC_defelem:
-       vtable = &PL_vtbl_defelem;
-       break;
-    case PERL_MAGIC_arylen:
-       vtable = &PL_vtbl_arylen;
-       break;
-    case PERL_MAGIC_pos:
-       vtable = &PL_vtbl_pos;
-       break;
-    case PERL_MAGIC_backref:
-       vtable = &PL_vtbl_backref;
-       break;
-    case PERL_MAGIC_hintselem:
-       vtable = &PL_vtbl_hintselem;
-       break;
-    case PERL_MAGIC_hints:
-       vtable = &PL_vtbl_hints;
-       break;
-    case PERL_MAGIC_ext:
-       /* Reserved for use by extensions not perl internals.           */
-       /* Useful for attaching extension internal data to perl vars.   */
-       /* Note that multiple extensions may clash if magical scalars   */
-       /* etc holding private data from one are passed to another.     */
-       vtable = NULL;
-       break;
-    default:
-       Perl_croak(aTHX_ "Don't know how to handle magic of type \\%o", how);
-    }
-
     /* Rest of work is done else where */
     mg = sv_magicext(sv,obj,how,vtable,name,namlen);
 
@@ -5493,7 +5411,7 @@ Perl_sv_unmagicext(pTHX_ SV *const sv, const int type, MGVTBL *vtbl)
 Weaken a reference: set the C<SvWEAKREF> flag on this RV; give the
 referred-to SV C<PERL_MAGIC_backref> magic if it hasn't already; and
 push a back-reference to this RV onto the array of backreferences
-associated with that magic. If the RV is magical, set magic will be
+associated with that magic.  If the RV is magical, set magic will be
 called after the RV is cleared.
 
 =cut
@@ -5514,6 +5432,7 @@ Perl_sv_rvweaken(pTHX_ SV *const sv)
        Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Reference is already weak");
        return sv;
     }
+    else if (SvREADONLY(sv)) croak_no_modify();
     tsv = SvRV(sv);
     Perl_sv_add_backref(aTHX_ tsv, sv);
     SvWEAKREF_on(sv);
@@ -5623,14 +5542,48 @@ Perl_sv_del_backref(pTHX_ SV *const tsv, SV *const sv)
        if (SvOOK(tsv))
            svp = (SV**)Perl_hv_backreferences_p(aTHX_ MUTABLE_HV(tsv));
     }
+    else if (SvIS_FREED(tsv) && PL_phase == PERL_PHASE_DESTRUCT) {
+       /* It's possible for the the last (strong) reference to tsv to have
+          become freed *before* the last thing holding a weak reference.
+          If both survive longer than the backreferences array, then when
+          the referent's reference count drops to 0 and it is freed, it's
+          not able to chase the backreferences, so they aren't NULLed.
+
+          For example, a CV holds a weak reference to its stash. If both the
+          CV and the stash survive longer than the backreferences array,
+          and the CV gets picked for the SvBREAK() treatment first,
+          *and* it turns out that the stash is only being kept alive because
+          of an our variable in the pad of the CV, then midway during CV
+          destruction the stash gets freed, but CvSTASH() isn't set to NULL.
+          It ends up pointing to the freed HV. Hence it's chased in here, and
+          if this block wasn't here, it would hit the !svp panic just below.
+
+          I don't believe that "better" destruction ordering is going to help
+          here - during global destruction there's always going to be the
+          chance that something goes out of order. We've tried to make it
+          foolproof before, and it only resulted in evolutionary pressure on
+          fools. Which made us look foolish for our hubris. :-(
+       */
+       return;
+    }
     else {
        MAGIC *const mg
            = SvMAGICAL(tsv) ? mg_find(tsv, PERL_MAGIC_backref) : NULL;
        svp =  mg ? &(mg->mg_obj) : NULL;
     }
 
-    if (!svp || !*svp)
-       Perl_croak(aTHX_ "panic: del_backref");
+    if (!svp)
+       Perl_croak(aTHX_ "panic: del_backref, svp=0");
+    if (!*svp) {
+       /* It's possible that sv is being freed recursively part way through the
+          freeing of tsv. If this happens, the backreferences array of tsv has
+          already been freed, and so svp will be NULL. If this is the case,
+          we should not panic. Instead, nothing needs doing, so return.  */
+       if (PL_phase == PERL_PHASE_DESTRUCT && SvREFCNT(tsv) == 0)
+           return;
+       Perl_croak(aTHX_ "panic: del_backref, *svp=%p phase=%s refcnt=%" UVuf,
+                  *svp, PL_phase_names[PL_phase], (UV)SvREFCNT(tsv));
+    }
 
     if (SvTYPE(*svp) == SVt_PVAV) {
 #ifdef DEBUGGING
@@ -5682,10 +5635,13 @@ Perl_sv_del_backref(pTHX_ SV *const tsv, SV *const sv)
        assert(count ==1);
        AvFILLp(av) = fill-1;
     }
+    else if (SvIS_FREED(*svp) && PL_phase == PERL_PHASE_DESTRUCT) {
+       /* freed AV; skip */
+    }
     else {
        /* optimisation: only a single backref, stored directly */
        if (*svp != sv)
-           Perl_croak(aTHX_ "panic: del_backref");
+           Perl_croak(aTHX_ "panic: del_backref, *svp=%p, sv=%p", *svp, sv);
        *svp = NULL;
     }
 
@@ -5703,7 +5659,7 @@ Perl_sv_kill_backrefs(pTHX_ SV *const sv, AV *const av)
     if (!av)
        return;
 
-    /* after multiple passes through Perl_sv_clean_all() for a thinngy
+    /* after multiple passes through Perl_sv_clean_all() for a thingy
      * that has badly leaked, the backref array may have gotten freed,
      * since we only protect it against 1 round of cleanup */
     if (SvIS_FREED(av)) {
@@ -5784,12 +5740,13 @@ Perl_sv_kill_backrefs(pTHX_ SV *const sv, AV *const av)
 /*
 =for apidoc sv_insert
 
-Inserts a string at the specified offset/length within the SV. Similar to
-the Perl substr() function. Handles get magic.
+Inserts a string at the specified offset/length within the SV.  Similar to
+the Perl substr() function.  Handles get magic.
 
 =for apidoc sv_insert_flags
 
-Same as C<sv_insert>, but the extra C<flags> are passed the C<SvPV_force_flags> that applies to C<bigstr>.
+Same as C<sv_insert>, but the extra C<flags> are passed to the
+C<SvPV_force_flags> that applies to C<bigstr>.
 
 =cut
 */
@@ -5802,13 +5759,13 @@ Perl_sv_insert_flags(pTHX_ SV *const bigstr, const STRLEN offset, const STRLEN l
     register char *mid;
     register char *midend;
     register char *bigend;
-    register I32 i;
+    register SSize_t i;                /* better be sizeof(STRLEN) or bad things happen */
     STRLEN curlen;
 
     PERL_ARGS_ASSERT_SV_INSERT_FLAGS;
 
     if (!bigstr)
-       Perl_croak(aTHX_ "Can't modify non-existent substring");
+       Perl_croak(aTHX_ "Can't modify nonexistent substring");
     SvPV_force_flags(bigstr, curlen, flags);
     (void)SvPOK_only_UTF8(bigstr);
     if (offset + len > curlen) {
@@ -5844,7 +5801,8 @@ Perl_sv_insert_flags(pTHX_ SV *const bigstr, const STRLEN offset, const STRLEN l
     bigend = big + SvCUR(bigstr);
 
     if (midend > bigend)
-       Perl_croak(aTHX_ "panic: sv_insert");
+       Perl_croak(aTHX_ "panic: sv_insert, midend=%p, bigend=%p",
+                  midend, bigend);
 
     if (mid - big > bigend - midend) { /* faster to shorten from end */
        if (littlelen) {
@@ -5966,7 +5924,6 @@ Perl_sv_replace(pTHX_ register SV *const sv, register SV *const nsv)
 STATIC void
 S_anonymise_cv_maybe(pTHX_ GV *gv, CV* cv)
 {
-    char *stash;
     SV *gvname;
     GV *anongv;
 
@@ -5986,10 +5943,10 @@ S_anonymise_cv_maybe(pTHX_ GV *gv, CV* cv)
     }
 
     /* if not, anonymise: */
-    stash  = GvSTASH(gv) && HvNAME(GvSTASH(gv))
-              ? HvENAME(GvSTASH(gv)) : NULL;
-    gvname = Perl_newSVpvf(aTHX_ "%s::__ANON__",
-                                       stash ? stash : "__ANON__");
+    gvname = (GvSTASH(gv) && HvNAME(GvSTASH(gv)) && HvENAME(GvSTASH(gv)))
+                    ? newSVhek(HvENAME_HEK(GvSTASH(gv)))
+                    : newSVpvn_flags( "__ANON__", 8, 0 );
+    sv_catpvs(gvname, "::__ANON__");
     anongv = gv_fetchsv(gvname, GV_ADDMULTI, SVt_PVCV);
     SvREFCNT_dec(gvname);
 
@@ -6003,10 +5960,10 @@ S_anonymise_cv_maybe(pTHX_ GV *gv, CV* cv)
 =for apidoc sv_clear
 
 Clear an SV: call any destructors, free up any memory used by the body,
-and free the body itself. The SV's head is I<not> freed, although
+and free the body itself.  The SV's head is I<not> freed, although
 its type is set to all 1's so that it won't inadvertently be assumed
 to be live during global destruction etc.
-This function should only be called when REFCNT is zero. Most of the time
+This function should only be called when REFCNT is zero.  Most of the time
 you'll want to call C<sv_free()> (or its macro wrapper C<SvREFCNT_dec>)
 instead.
 
@@ -6036,7 +5993,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
        type = SvTYPE(sv);
 
        assert(SvREFCNT(sv) == 0);
-       assert(SvTYPE(sv) != SVTYPEMASK);
+       assert(SvTYPE(sv) != (svtype)SVTYPEMASK);
 
        if (type <= SVt_IV) {
            /* See the comment in sv.h about the collusion between this
@@ -6070,6 +6027,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                sv_unmagic(sv, PERL_MAGIC_backref);
                mg_free(sv);
            }
+           SvMAGICAL_off(sv);
            if (type == SVt_PVMG && SvPAD_TYPED(sv))
                SvREFCNT_dec(SvSTASH(sv));
        }
@@ -6090,6 +6048,8 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
            Safefree(IoTOP_NAME(sv));
            Safefree(IoFMT_NAME(sv));
            Safefree(IoBOTTOM_NAME(sv));
+           if ((const GV *)sv == PL_statgv)
+               PL_statgv = NULL;
            goto freescalar;
        case SVt_REGEXP:
            /* FIXME for plugins */
@@ -6117,7 +6077,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                {
                    if (PL_stashcache)
                        (void)hv_delete(PL_stashcache, name,
-                           HvNAMELEN_get((HV*)sv), G_DISCARD);
+                           HvNAMEUTF8((HV*)sv) ? -HvNAMELEN_get((HV*)sv) : HvNAMELEN_get((HV*)sv), G_DISCARD);
                    hv_name_set((HV*)sv, NULL, 0, 0);
                }
 
@@ -6126,14 +6086,12 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                SvSTASH(sv) = (HV*)iter_sv;
                iter_sv = sv;
 
-               /* XXX ideally we should save the old value of hash_index
-                * too, but I can't think of any place to hide it. The
-                * effect of not saving it is that for freeing hashes of
-                * hashes, we become quadratic in scanning the HvARRAY of
-                * the top hash looking for new entries to free; but
-                * hopefully this will be dwarfed by the freeing of all
-                * the nested hashes. */
+               /* save old hash_index in unused SvMAGIC field */
+               assert(!SvMAGICAL(sv));
+               assert(!SvMAGIC(sv));
+               ((XPVMG*) SvANY(sv))->xmg_u.xmg_hash_index = hash_index;
                hash_index = 0;
+
                next_sv = Perl_hfree_next_entry(aTHX_ (HV*)sv, &hash_index);
                goto get_next_sv; /* process this new sv */
            }
@@ -6185,8 +6143,11 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
            /* FIXME. There are probably more unreferenced pointers to SVs
             * in the interpreter struct that we should check and tidy in
             * a similar fashion to this:  */
+           /* See also S_sv_unglob, which does the same thing. */
            if ((const GV *)sv == PL_last_in_gv)
                PL_last_in_gv = NULL;
+           else if ((const GV *)sv == PL_statgv)
+               PL_statgv = NULL;
        case SVt_PVMG:
        case SVt_PVNV:
        case SVt_PVIV:
@@ -6236,7 +6197,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                     && !(SvTYPE(sv) == SVt_PVIO
                     && !(IoFLAGS(sv) & IOf_FAKE_DIRP)))
                Safefree(SvPVX_mutable(sv));
-           else if (SvPVX_const(sv) && SvREADONLY(sv) && SvFAKE(sv)) {
+           else if (SvPVX_const(sv) && SvIsCOW(sv)) {
                unshare_hek(SvSHARED_HEK_FROM_PV(SvPVX_const(sv)));
                SvFAKE_off(sv);
            }
@@ -6290,16 +6251,16 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                }
            } else if (SvTYPE(iter_sv) == SVt_PVHV) {
                sv = Perl_hfree_next_entry(aTHX_ (HV*)iter_sv, &hash_index);
-               if (!sv) { /* no more elements of current HV to free */
+               if (!sv && !HvTOTALKEYS((HV *)iter_sv)) {
+                   /* no more elements of current HV to free */
                    sv = iter_sv;
                    type = SvTYPE(sv);
-                   /* Restore previous value of iter_sv, squirrelled away */
+                   /* Restore previous values of iter_sv and hash_index,
+                    * squirrelled away */
                    assert(!SvOBJECT(sv));
                    iter_sv = (SV*)SvSTASH(sv);
-
-                   /* ideally we should restore the old hash_index here,
-                    * but we don't currently save the old value */
-                   hash_index = 0;
+                   assert(!SvMAGICAL(sv));
+                   hash_index = ((XPVMG*) SvANY(sv))->xmg_u.xmg_hash_index;
 
                    /* free any remaining detritus from the hash struct */
                    Perl_hv_undef_flags(aTHX_ MUTABLE_HV(sv), HV_NAME_SETALL);
@@ -6360,11 +6321,19 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
                /* A constant subroutine can have no side effects, so
                   don't bother calling it.  */
                && !CvCONST(destructor)
-               /* Don't bother calling an empty destructor */
+               /* Don't bother calling an empty destructor or one that
+                  returns immediately. */
                && (CvISXSUB(destructor)
                || (CvSTART(destructor)
                    && (CvSTART(destructor)->op_next->op_type
-                                       != OP_LEAVESUB))))
+                                       != OP_LEAVESUB)
+                   && (CvSTART(destructor)->op_next->op_type
+                                       != OP_PUSHMARK
+                       || CvSTART(destructor)->op_next->op_next->op_type
+                                       != OP_RETURN
+                      )
+                  ))
+              )
            {
                SV* const tmpref = newRV(sv);
                SvREADONLY_on(tmpref); /* DESTROY() could be naughty */
@@ -6393,8 +6362,8 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
        if (check_refcnt && SvREFCNT(sv)) {
            if (PL_in_clean_objs)
                Perl_croak(aTHX_
-                   "DESTROY created new reference to dead object '%s'",
-                   HvNAME_get(stash));
+                 "DESTROY created new reference to dead object '%"HEKf"'",
+                  HEKfARG(HvNAME_HEK(stash)));
            /* DESTROY gave object new lease on life */
            return FALSE;
        }
@@ -6412,7 +6381,7 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
 /*
 =for apidoc sv_newref
 
-Increment an SV's reference count. Use the C<SvREFCNT_inc()> wrapper
+Increment an SV's reference count.  Use the C<SvREFCNT_inc()> wrapper
 instead.
 
 =cut
@@ -6514,7 +6483,7 @@ Perl_sv_free2(pTHX_ SV *const sv)
 /*
 =for apidoc sv_len
 
-Returns the length of the string in the SV. Handles magic and type
+Returns the length of the string in the SV.  Handles magic and type
 coercion.  See also C<SvCUR>, which gives raw access to the xpv_cur slot.
 
 =cut
@@ -6539,7 +6508,7 @@ Perl_sv_len(pTHX_ register SV *const sv)
 =for apidoc sv_len_utf8
 
 Returns the number of characters in the string in an SV, counting wide
-UTF-8 bytes as a single character. Handles magic and type coercion.
+UTF-8 bytes as a single character.  Handles magic and type coercion.
 
 =cut
 */
@@ -6781,7 +6750,8 @@ S_sv_pos_u2b_cached(pTHX_ SV *const sv, MAGIC **const mgp, const U8 *const start
 Converts the value pointed to by offsetp 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 of the string. Handles type coercion.
+the offset, rather than from the start
+of the string.  Handles type coercion.
 I<flags> is passed to C<SvPV_flags>, and usually should be
 C<SV_GMAGIC|SV_CONST_RETURN> to handle magic.
 
@@ -6837,7 +6807,7 @@ Perl_sv_pos_u2b_flags(pTHX_ SV *const sv, STRLEN uoffset, STRLEN *const lenp,
 Converts the value pointed to by offsetp 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 of the string. Handles magic and
+the offset, rather than from the start of the string.  Handles magic and
 type coercion.
 
 Use C<sv_pos_u2b_flags> in preference, which correctly handles strings longer
@@ -7113,7 +7083,8 @@ Perl_sv_pos_b2u(pTHX_ register SV *const sv, I32 *const offsetp)
     s = (const U8*)SvPV_const(sv, blen);
 
     if (blen < byte)
-       Perl_croak(aTHX_ "panic: sv_pos_b2u: bad byte offset");
+       Perl_croak(aTHX_ "panic: sv_pos_b2u: bad byte offset, blen=%"UVuf
+                  ", byte=%"UVuf, (UV)blen, (UV)byte);
 
     send = s + byte;
 
@@ -7208,14 +7179,14 @@ S_assert_uft8_cache_coherent(pTHX_ const char *const func, STRLEN from_cache,
 =for apidoc sv_eq
 
 Returns a boolean indicating whether the strings in the two SVs are
-identical. Is UTF-8 and 'use bytes' aware, handles get magic, and will
+identical.  Is UTF-8 and 'use bytes' aware, handles get magic, and will
 coerce its args to strings if necessary.
 
 =for apidoc sv_eq_flags
 
 Returns a boolean indicating whether the strings in the two SVs are
-identical. Is UTF-8 and 'use bytes' aware and coerces its args to strings
-if necessary. If the flags include SV_GMAGIC, it handles get-magic, too.
+identical.  Is UTF-8 and 'use bytes' aware and coerces its args to strings
+if necessary.  If the flags include SV_GMAGIC, it handles get-magic, too.
 
 =cut
 */
@@ -7229,7 +7200,6 @@ Perl_sv_eq_flags(pTHX_ register SV *sv1, register SV *sv2, const U32 flags)
     const char *pv2;
     STRLEN cur2;
     I32  eq     = 0;
-    char *tpv   = NULL;
     SV* svrecode = NULL;
 
     if (!sv1) {
@@ -7293,8 +7263,6 @@ Perl_sv_eq_flags(pTHX_ register SV *sv1, register SV *sv2, const U32 flags)
        eq = (pv1 == pv2) || memEQ(pv1, pv2, cur1);
        
     SvREFCNT_dec(svrecode);
-    if (tpv)
-       Safefree(tpv);
 
     return eq;
 }
@@ -7304,15 +7272,15 @@ Perl_sv_eq_flags(pTHX_ register SV *sv1, register SV *sv2, const U32 flags)
 
 Compares the strings in two SVs.  Returns -1, 0, or 1 indicating whether the
 string in C<sv1> is less than, equal to, or greater than the string in
-C<sv2>. Is UTF-8 and 'use bytes' aware, handles get magic, and will
+C<sv2>.  Is UTF-8 and 'use bytes' aware, handles get magic, and will
 coerce its args to strings if necessary.  See also C<sv_cmp_locale>.
 
 =for apidoc sv_cmp_flags
 
 Compares the strings in two SVs.  Returns -1, 0, or 1 indicating whether the
 string in C<sv1> is less than, equal to, or greater than the string in
-C<sv2>. Is UTF-8 and 'use bytes' aware and will coerce its args to strings
-if necessary. If the flags include SV_GMAGIC, it handles get magic. See
+C<sv2>.  Is UTF-8 and 'use bytes' aware and will coerce its args to strings
+if necessary.  If the flags include SV_GMAGIC, it handles get magic.  See
 also C<sv_cmp_locale_flags>.
 
 =cut
@@ -7404,15 +7372,15 @@ Perl_sv_cmp_flags(pTHX_ register SV *const sv1, register SV *const sv2,
 /*
 =for apidoc sv_cmp_locale
 
-Compares the strings in two SVs in a locale-aware manner. Is UTF-8 and
+Compares the strings in two SVs in a locale-aware manner.  Is UTF-8 and
 'use bytes' aware, handles get magic, and will coerce its args to strings
 if necessary.  See also C<sv_cmp>.
 
 =for apidoc sv_cmp_locale_flags
 
-Compares the strings in two SVs in a locale-aware manner. Is UTF-8 and
-'use bytes' aware and will coerce its args to strings if necessary. If the
-flags contain SV_GMAGIC, it handles get magic. See also C<sv_cmp_flags>.
+Compares the strings in two SVs in a locale-aware manner.  Is UTF-8 and
+'use bytes' aware and will coerce its args to strings if necessary.  If the
+flags contain SV_GMAGIC, it handles get magic.  See also C<sv_cmp_flags>.
 
 =cut
 */
@@ -7479,12 +7447,12 @@ Perl_sv_cmp_locale_flags(pTHX_ register SV *const sv1, register SV *const sv2,
 /*
 =for apidoc sv_collxfrm
 
-This calls C<sv_collxfrm_flags> with the SV_GMAGIC flag. See
+This calls C<sv_collxfrm_flags> with the SV_GMAGIC flag.  See
 C<sv_collxfrm_flags>.
 
 =for apidoc sv_collxfrm_flags
 
-Add Collate Transform magic to an SV if it doesn't already have it. If the
+Add Collate Transform magic to an SV if it doesn't already have it.  If the
 flags contain SV_GMAGIC, it handles get-magic.
 
 Any scalar variable may carry PERL_MAGIC_collxfrm magic that contains the
@@ -7597,7 +7565,10 @@ S_sv_gets_read_record(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
 =for apidoc sv_gets
 
 Get a line from the filehandle and store it into the SV, optionally
-appending to the currently-stored string.
+appending to the currently-stored string. If C<append> is not 0, the
+line is appended to the SV instead of overwriting it. C<append> should
+be set to the byte offset that the appended string should start at
+in the SV (typically, C<SvCUR(sv)> is a suitable choice).
 
 =cut
 */
@@ -7625,8 +7596,6 @@ Perl_sv_gets(pTHX_ register SV *const sv, register PerlIO *const fp, I32 append)
        Swings and roundabouts.  */
     SvUPGRADE(sv, SVt_PV);
 
-    SvSCREAM_off(sv);
-
     if (append) {
        if (PerlIO_isutf8(fp)) {
            if (!SvUTF8(sv)) {
@@ -7885,9 +7854,9 @@ screamer2:
        if (cnt < 0)
            cnt = 0;  /* we do need to re-set the sv even when cnt <= 0 */
        if (append)
-            sv_catpvn(sv, (char *) buf, cnt);
+            sv_catpvn_nomg(sv, (char *) buf, cnt);
        else
-            sv_setpvn(sv, (char *) buf, cnt);
+            sv_setpvn(sv, (char *) buf, cnt);   /* "nomg" is implied */
 
        if (i != EOF &&                 /* joy */
            (!rslen ||
@@ -7932,7 +7901,7 @@ screamer2:
 =for apidoc sv_inc
 
 Auto-increment of the value in the SV, doing string to numeric conversion
-if necessary. Handles 'get' magic and operator overloading.
+if necessary.  Handles 'get' magic and operator overloading.
 
 =cut
 */
@@ -7950,7 +7919,7 @@ Perl_sv_inc(pTHX_ register SV *const sv)
 =for apidoc sv_inc_nomg
 
 Auto-increment of the value in the SV, doing string to numeric conversion
-if necessary. Handles operator overloading. Skips handling 'get' magic.
+if necessary.  Handles operator overloading.  Skips handling 'get' magic.
 
 =cut
 */
@@ -7965,7 +7934,7 @@ Perl_sv_inc_nomg(pTHX_ register SV *const sv)
     if (!sv)
        return;
     if (SvTHINKFIRST(sv)) {
-       if (SvIsCOW(sv))
+       if (SvIsCOW(sv) || isGV_with_GP(sv))
            sv_force_normal_flags(sv, 0);
        if (SvREADONLY(sv)) {
            if (IN_PERL_RUNTIME)
@@ -8012,6 +7981,7 @@ Perl_sv_inc_nomg(pTHX_ register SV *const sv)
        const NV was = SvNVX(sv);
        if (NV_OVERFLOWS_INTEGERS_AT &&
            was >= NV_OVERFLOWS_INTEGERS_AT) {
+           /* diag_listed_as: Lost precision when %s %f by 1 */
            Perl_ck_warner(aTHX_ packWARN(WARN_IMPRECISION),
                           "Lost precision when incrementing %" NVff " by 1",
                           was);
@@ -8113,7 +8083,7 @@ Perl_sv_inc_nomg(pTHX_ register SV *const sv)
 =for apidoc sv_dec
 
 Auto-decrement of the value in the SV, doing string to numeric conversion
-if necessary. Handles 'get' magic and operator overloading.
+if necessary.  Handles 'get' magic and operator overloading.
 
 =cut
 */
@@ -8132,7 +8102,7 @@ Perl_sv_dec(pTHX_ register SV *const sv)
 =for apidoc sv_dec_nomg
 
 Auto-decrement of the value in the SV, doing string to numeric conversion
-if necessary. Handles operator overloading. Skips handling 'get' magic.
+if necessary.  Handles operator overloading.  Skips handling 'get' magic.
 
 =cut
 */
@@ -8146,7 +8116,7 @@ Perl_sv_dec_nomg(pTHX_ register SV *const sv)
     if (!sv)
        return;
     if (SvTHINKFIRST(sv)) {
-       if (SvIsCOW(sv))
+       if (SvIsCOW(sv) || isGV_with_GP(sv))
            sv_force_normal_flags(sv, 0);
        if (SvREADONLY(sv)) {
            if (IN_PERL_RUNTIME)
@@ -8196,6 +8166,7 @@ Perl_sv_dec_nomg(pTHX_ register SV *const sv)
            const NV was = SvNVX(sv);
            if (NV_OVERFLOWS_INTEGERS_AT &&
                was <= -NV_OVERFLOWS_INTEGERS_AT) {
+               /* diag_listed_as: Lost precision when %s %f by 1 */
                Perl_ck_warner(aTHX_ packWARN(WARN_IMPRECISION),
                               "Lost precision when decrementing %" NVff " by 1",
                               was);
@@ -8263,7 +8234,7 @@ Perl_sv_dec_nomg(pTHX_ register SV *const sv)
 =for apidoc sv_mortalcopy
 
 Creates a new SV which is a copy of the original SV (using C<sv_setsv>).
-The new SV is marked as mortal. It will be destroyed "soon", either by an
+The new SV is marked as mortal.  It will be destroyed "soon", either by an
 explicit call to FREETMPS, or by an implicit call at places such as
 statement boundaries.  See also C<sv_newmortal> and C<sv_2mortal>.
 
@@ -8292,7 +8263,7 @@ Perl_sv_mortalcopy(pTHX_ SV *const oldstr)
 =for apidoc sv_newmortal
 
 Creates a new null SV which is mortal.  The reference count of the SV is
-set to 1. It will be destroyed "soon", either by an explicit call to
+set to 1.  It will be destroyed "soon", either by an explicit call to
 FREETMPS, or by an implicit call at places such as statement boundaries.
 See also C<sv_mortalcopy> and C<sv_2mortal>.
 
@@ -8321,7 +8292,8 @@ string.  You are responsible for ensuring that the source string is at least
 C<len> bytes long.  If the C<s> argument is NULL the new SV will be undefined.
 Currently the only flag bits accepted are C<SVf_UTF8> and C<SVs_TEMP>.
 If C<SVs_TEMP> is set, then C<sv_2mortal()> is called on the result before
-returning. If C<SVf_UTF8> is set, C<s> is considered to be in UTF-8 and the
+returning.  If C<SVf_UTF8> is set, C<s>
+is considered to be in UTF-8 and the
 C<SVf_UTF8> flag will be set on the new SV.
 C<newSVpvn_utf8()> is a convenience wrapper for this function, defined as
 
@@ -8366,7 +8338,7 @@ Perl_newSVpvn_flags(pTHX_ const char *const s, const STRLEN len, const U32 flags
 Marks an existing SV as mortal.  The SV will be destroyed "soon", either
 by an explicit call to FREETMPS, or by an implicit call at places such as
 statement boundaries.  SvTEMP() is turned on which means that the SV's
-string buffer can be "stolen" if this SV is copied. See also C<sv_newmortal>
+string buffer can be "stolen" if this SV is copied.  See also C<sv_newmortal>
 and C<sv_mortalcopy>.
 
 =cut
@@ -8409,22 +8381,24 @@ Perl_newSVpv(pTHX_ const char *const s, const STRLEN len)
 /*
 =for apidoc newSVpvn
 
-Creates a new SV and copies a string into it.  The reference count for the
-SV is set to 1.  Note that if C<len> is zero, Perl will create a zero length
-string.  You are responsible for ensuring that the source string is at least
-C<len> bytes long.  If the C<s> argument is NULL the new SV will be undefined.
+Creates a new SV and copies a buffer into it, which may contain NUL characters
+(C<\0>) and other binary data.  The reference count for the SV is set to 1.
+Note that if C<len> is zero, Perl will create a zero length (Perl) string.  You
+are responsible for ensuring that the source buffer is at least
+C<len> bytes long.  If the C<buffer> argument is NULL the new SV will be
+undefined.
 
 =cut
 */
 
 SV *
-Perl_newSVpvn(pTHX_ const char *const s, const STRLEN len)
+Perl_newSVpvn(pTHX_ const char *const buffer, const STRLEN len)
 {
     dVAR;
     register SV *sv;
 
     new_SV(sv);
-    sv_setpvn(sv,s,len);
+    sv_setpvn(sv,buffer,len);
     return sv;
 }
 
@@ -8432,7 +8406,7 @@ Perl_newSVpvn(pTHX_ const char *const s, const STRLEN len)
 =for apidoc newSVhek
 
 Creates a new SV from the hash key structure.  It will generate scalars that
-point to the shared string table where possible. Returns a new (undefined)
+point to the shared string table where possible.  Returns a new (undefined)
 SV if the hek is NULL.
 
 =cut
@@ -8472,7 +8446,7 @@ Perl_newSVhek(pTHX_ const HEK *const hek)
               into an hv routine with a regular hash.
               Similarly, 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_kek on it.  */
+              share_hek_hek on it.  */
 
            SV * const sv = newSVpvn (HEK_KEY(hek), HEK_LEN(hek));
            if (HEK_UTF8(hek))
@@ -8504,10 +8478,11 @@ Perl_newSVhek(pTHX_ const HEK *const hek)
 =for apidoc newSVpvn_share
 
 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 is non-zero, that
-value is used; otherwise the hash is computed. The string's hash can be later
-be retrieved from the SV with the C<SvSHARED_HASH()> macro. The idea here is
+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
+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
 that as the string table is used for shared hash keys these strings will have
 SvPVX_const == HeKEY and hash lookup will avoid string compare.
 
@@ -8744,7 +8719,7 @@ Perl_newRV(pTHX_ SV *const sv)
 =for apidoc newSVsv
 
 Creates a new SV which is an exact duplicate of the original SV.
-(Uses C<sv_setsv>).
+(Uses C<sv_setsv>.)
 
 =cut
 */
@@ -8757,7 +8732,7 @@ Perl_newSVsv(pTHX_ register SV *const old)
 
     if (!old)
        return NULL;
-    if (SvTYPE(old) == SVTYPEMASK) {
+    if (SvTYPE(old) == (svtype)SVTYPEMASK) {
        Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL), "semi-panic: attempt to dup freed string");
        return NULL;
     }
@@ -8879,6 +8854,9 @@ Using various gambits, try to get an IO from an SV: the IO slot if its a
 GV; or the recursive result if we're an RV; or the IO slot of the symbol
 named after the PV if we're a string.
 
+'Get' magic is ignored on the sv passed in, but will be called on
+C<SvRV(sv)> if sv is an RV.
+
 =cut
 */
 
@@ -8900,22 +8878,31 @@ Perl_sv_2io(pTHX_ SV *const sv)
            gv = MUTABLE_GV(sv);
            io = GvIO(gv);
            if (!io)
-               Perl_croak(aTHX_ "Bad filehandle: %s", GvNAME(gv));
+               Perl_croak(aTHX_ "Bad filehandle: %"HEKf,
+                                    HEKfARG(GvNAME_HEK(gv)));
            break;
        }
        /* FALL THROUGH */
     default:
        if (!SvOK(sv))
            Perl_croak(aTHX_ PL_no_usym, "filehandle");
-       if (SvROK(sv))
+       if (SvROK(sv)) {
+           SvGETMAGIC(SvRV(sv));
            return sv_2io(SvRV(sv));
-       gv = gv_fetchsv(sv, 0, SVt_PVIO);
+       }
+       gv = gv_fetchsv_nomg(sv, 0, SVt_PVIO);
        if (gv)
            io = GvIO(gv);
        else
            io = 0;
-       if (!io)
-           Perl_croak(aTHX_ "Bad filehandle: %"SVf, SVfARG(sv));
+       if (!io) {
+           SV *newsv = sv;
+           if (SvGMAGICAL(sv)) {
+               newsv = sv_newmortal();
+               sv_setsv_nomg(newsv, sv);
+           }
+           Perl_croak(aTHX_ "Bad filehandle: %"SVf, SVfARG(newsv));
+       }
        break;
     }
     return io;
@@ -8955,22 +8942,11 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **const st, GV **const gvp, const I32 lref)
        *st = NULL;
        *gvp = NULL;
        return NULL;
-    case SVt_PVGV:
-       if (isGV_with_GP(sv)) {
-           gv = MUTABLE_GV(sv);
-           *gvp = gv;
-           *st = GvESTASH(gv);
-           goto fix_gv;
-       }
-       /* FALL THROUGH */
-
     default:
+       SvGETMAGIC(sv);
        if (SvROK(sv)) {
-           SvGETMAGIC(sv);
            if (SvAMAGIC(sv))
                sv = amagic_deref_call(sv, to_cv_amg);
-           /* At this point I'd like to do SPAGAIN, but really I need to
-              force it upon my callers. Hmmm. This is a mess... */
 
            sv = SvRV(sv);
            if (SvTYPE(sv) == SVt_PVCV) {
@@ -8979,17 +8955,17 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **const st, GV **const gvp, const I32 lref)
                *st = CvSTASH(cv);
                return cv;
            }
-           else if(isGV_with_GP(sv))
+           else if(SvGETMAGIC(sv), isGV_with_GP(sv))
                gv = MUTABLE_GV(sv);
            else
                Perl_croak(aTHX_ "Not a subroutine reference");
        }
        else if (isGV_with_GP(sv)) {
-           SvGETMAGIC(sv);
            gv = MUTABLE_GV(sv);
        }
-       else
-           gv = gv_fetchsv(sv, lref, SVt_PVCV); /* Calls get magic */
+       else {
+           gv = gv_fetchsv_nomg(sv, lref, SVt_PVCV);
+       }
        *gvp = gv;
        if (!gv) {
            *st = NULL;
@@ -9001,22 +8977,11 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **const st, GV **const gvp, const I32 lref)
            return NULL;
        }
        *st = GvESTASH(gv);
-    fix_gv:
-       if (lref && !GvCVu(gv)) {
-           SV *tmpsv;
-           ENTER;
-           tmpsv = newSV(0);
-           gv_efullname3(tmpsv, gv, NULL);
+       if (lref & ~GV_ADDMG && !GvCVu(gv)) {
            /* XXX this is probably not what they think they're getting.
             * It has the same effect as "sub name;", i.e. just a forward
             * declaration! */
-           newSUB(start_subparse(FALSE, 0),
-                  newSVOP(OP_CONST, 0, tmpsv),
-                  NULL, NULL);
-           LEAVE;
-           if (!GvCVu(gv))
-               Perl_croak(aTHX_ "Unable to create sub named \"%"SVf"\"",
-                          SVfARG(SvOK(sv) ? sv : &PL_sv_no));
+           newSTUB(gv,0);
        }
        return GvCVu(gv);
     }
@@ -9063,13 +9028,13 @@ Perl_sv_true(pTHX_ register SV *const sv)
 
 Get a sensible string out of the SV somehow.
 A private implementation of the C<SvPV_force> macro for compilers which
-can't cope with complex macro expressions. Always use the macro instead.
+can't cope with complex macro expressions.  Always use the macro instead.
 
 =for apidoc sv_pvn_force_flags
 
 Get a sensible string out of the SV somehow.
 If C<flags> has C<SV_GMAGIC> bit set, will C<mg_get> on C<sv> if
-appropriate, else not. C<sv_pvn_force> and C<sv_pvn_force_nomg> are
+appropriate, else not.  C<sv_pvn_force> and C<sv_pvn_force_nomg> are
 implemented in terms of this function.
 You normally want to use the various wrapper macros instead: see
 C<SvPV_force> and C<SvPV_force_nomg>
@@ -9084,6 +9049,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))
         sv_force_normal_flags(sv, 0);
 
@@ -9108,7 +9074,10 @@ Perl_sv_pvn_force_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
            /* diag_listed_as: Can't coerce %s to %s in %s */
            Perl_croak(aTHX_ "Can't coerce %s to string in %s", sv_reftype(sv,0),
                OP_DESC(PL_op));
-       s = sv_2pv_flags(sv, &len, flags);
+       s = sv_2pv_flags(sv, &len, flags &~ SV_GMAGIC);
+       if (!s) {
+         s = (char *)"";
+       }
        if (lp)
            *lp = len;
 
@@ -9128,13 +9097,15 @@ Perl_sv_pvn_force_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
                                  PTR2UV(sv),SvPVX_const(sv)));
        }
     }
+    (void)SvPOK_only_UTF8(sv);
     return SvPVX_mutable(sv);
 }
 
 /*
 =for apidoc sv_pvbyten_force
 
-The backend for the C<SvPVbytex_force> macro. Always use the macro instead.
+The backend for the C<SvPVbytex_force> macro.  Always use the macro
+instead.
 
 =cut
 */
@@ -9153,7 +9124,8 @@ Perl_sv_pvbyten_force(pTHX_ SV *const sv, STRLEN *const lp)
 /*
 =for apidoc sv_pvutf8n_force
 
-The backend for the C<SvPVutf8x_force> macro. Always use the macro instead.
+The backend for the C<SvPVutf8x_force> macro.  Always use the macro
+instead.
 
 =cut
 */
@@ -9181,12 +9153,8 @@ const char *
 Perl_sv_reftype(pTHX_ const SV *const sv, const int ob)
 {
     PERL_ARGS_ASSERT_SV_REFTYPE;
-
-    /* The fact that I don't need to downcast to char * everywhere, only in ?:
-       inside return suggests a const propagation bug in g++.  */
     if (ob && SvOBJECT(sv)) {
-       char * const name = HvNAME_get(SvSTASH(sv));
-       return name ? name : (char *) "__ANON__";
+       return SvPV_nolen_const(sv_ref(NULL, sv, ob));
     }
     else {
        switch (SvTYPE(sv)) {
@@ -9224,6 +9192,34 @@ Perl_sv_reftype(pTHX_ const SV *const sv, const int ob)
 }
 
 /*
+=for apidoc sv_ref
+
+Returns a SV describing what the SV passed in is a reference to.
+
+=cut
+*/
+
+SV *
+Perl_sv_ref(pTHX_ register SV *dst, const SV *const sv, const int ob)
+{
+    PERL_ARGS_ASSERT_SV_REF;
+
+    if (!dst)
+        dst = sv_newmortal();
+
+    if (ob && SvOBJECT(sv)) {
+       HvNAME_get(SvSTASH(sv))
+                    ? sv_sethek(dst, HvNAME_HEK(SvSTASH(sv)))
+                    : sv_setpvn(dst, "__ANON__", 8);
+    }
+    else {
+        const char * reftype = sv_reftype(sv, 0);
+        sv_setpv(dst, reftype);
+    }
+    return dst;
+}
+
+/*
 =for apidoc sv_isobject
 
 Returns a boolean indicating whether the SV is an RV pointing to a blessed
@@ -9301,7 +9297,6 @@ Perl_newSVrv(pTHX_ SV *const rv, const char *const classname)
     new_SV(sv);
 
     SV_CHECK_THINKFIRST_COW_DROP(rv);
-    (void)SvAMAGIC_off(rv);
 
     if (SvTYPE(rv) >= SVt_PVMG) {
        const U32 refcnt = SvREFCNT(rv);
@@ -9488,11 +9483,6 @@ Perl_sv_bless(pTHX_ SV *const sv, HV *const stash)
     SvUPGRADE(tmpRef, SVt_PVMG);
     SvSTASH_set(tmpRef, MUTABLE_HV(SvREFCNT_inc_simple(stash)));
 
-    if (Gv_AMG(stash))
-       SvAMAGIC_on(sv);
-    else
-       (void)SvAMAGIC_off(sv);
-
     if(SvSMAGICAL(tmpRef))
         if(mg_find(tmpRef, PERL_MAGIC_ext) || mg_find(tmpRef, PERL_MAGIC_uvar))
             mg_set(tmpRef);
@@ -9502,23 +9492,24 @@ Perl_sv_bless(pTHX_ SV *const sv, HV *const stash)
     return sv;
 }
 
-/* Downgrades a PVGV to a PVMG. If it’s actually a PVLV, we leave the type
+/* Downgrades a PVGV to a PVMG. If it's actually a PVLV, we leave the type
  * as it is after unglobbing it.
  */
 
-STATIC void
-S_sv_unglob(pTHX_ SV *const sv)
+PERL_STATIC_INLINE void
+S_sv_unglob(pTHX_ SV *const sv, U32 flags)
 {
     dVAR;
     void *xpvmg;
     HV *stash;
-    SV * const temp = sv_newmortal();
+    SV * const temp = flags & SV_COW_DROP_PV ? NULL : sv_newmortal();
 
     PERL_ARGS_ASSERT_SV_UNGLOB;
 
     assert(SvTYPE(sv) == SVt_PVGV || SvTYPE(sv) == SVt_PVLV);
     SvFAKE_off(sv);
-    gv_efullname3(temp, MUTABLE_GV(sv), "*");
+    if (!(flags & SV_COW_DROP_PV))
+       gv_efullname3(temp, MUTABLE_GV(sv), "*");
 
     if (GvGP(sv)) {
         if(GvCVu((const GV *)sv) && (stash = GvSTASH(MUTABLE_GV(sv)))
@@ -9549,7 +9540,13 @@ S_sv_unglob(pTHX_ SV *const sv)
 
     /* Intentionally not calling any local SET magic, as this isn't so much a
        set operation as merely an internal storage change.  */
-    sv_setsv_flags(sv, temp, 0);
+    if (flags & SV_COW_DROP_PV) SvOK_off(sv);
+    else sv_setsv_flags(sv, temp, 0);
+
+    if ((const GV *)sv == PL_last_in_gv)
+       PL_last_in_gv = NULL;
+    else if ((const GV *)sv == PL_statgv)
+       PL_statgv = NULL;
 }
 
 /*
@@ -9592,7 +9589,8 @@ Perl_sv_unref_flags(pTHX_ SV *const ref, const U32 flags)
 /*
 =for apidoc sv_untaint
 
-Untaint an SV. Use C<SvTAINTED_off> instead.
+Untaint an SV.  Use C<SvTAINTED_off> instead.
+
 =cut
 */
 
@@ -9611,7 +9609,8 @@ Perl_sv_untaint(pTHX_ SV *const sv)
 /*
 =for apidoc sv_tainted
 
-Test an SV for taintedness. Use C<SvTAINTED> instead.
+Test an SV for taintedness.  Use C<SvTAINTED> instead.
+
 =cut
 */
 
@@ -9831,7 +9830,7 @@ output to an SV.  If the appended data contains "wide" characters
 (including, but not limited to, SVs with a UTF-8 PV formatted with %s,
 and characters >255 formatted with %c), the original SV might get
 upgraded to UTF-8.  Handles 'get' magic, but not 'set' magic.  See
-C<sv_catpvf_mg>. If the original SV was UTF-8, the pattern should be
+C<sv_catpvf_mg>.  If the original SV was UTF-8, the pattern should be
 valid UTF-8; if the original SV was bytes, the pattern should be too.
 
 =cut */
@@ -9924,7 +9923,7 @@ Perl_sv_vsetpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
     PERL_ARGS_ASSERT_SV_VSETPVFN;
 
     sv_setpvs(sv, "");
-    sv_vcatpvfn(sv, pat, patlen, args, svargs, svmax, maybe_tainted);
+    sv_vcatpvfn_flags(sv, pat, patlen, args, svargs, svmax, maybe_tainted, 0);
 }
 
 
@@ -9998,18 +9997,21 @@ S_F0convert(NV nv, char *const endbuf, STRLEN *const len)
 /*
 =for apidoc sv_vcatpvfn
 
+=for apidoc sv_vcatpvfn_flags
+
 Processes its arguments like C<vsprintf> and appends the formatted output
 to an SV.  Uses an array of SVs if the C style variable argument list is
 missing (NULL).  When running with taint checks enabled, indicates via
 C<maybe_tainted> if results are untrustworthy (often due to the use of
 locales).
 
+If called as C<sv_vcatpvfn> or flags include C<SV_GMAGIC>, calls get magic.
+
 Usually used via one of its frontends C<sv_vcatpvf> and C<sv_vcatpvf_mg>.
 
 =cut
 */
 
-
 #define VECTORIZE_ARGS vecsv = va_arg(*args, SV*);\
                        vecstr = (U8*)SvPV_const(vecsv,veclen);\
                        vec_utf8 = DO_UTF8(vecsv);
@@ -10020,6 +10022,16 @@ void
 Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                  va_list *const args, SV **const svargs, const I32 svmax, bool *const maybe_tainted)
 {
+    PERL_ARGS_ASSERT_SV_VCATPVFN;
+
+    sv_vcatpvfn_flags(sv, pat, patlen, args, svargs, svmax, maybe_tainted, SV_GMAGIC|SV_SMAGIC);
+}
+
+void
+Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
+                       va_list *const args, SV **const svargs, const I32 svmax, bool *const maybe_tainted,
+                       const U32 flags)
+{
     dVAR;
     char *p;
     char *q;
@@ -10038,11 +10050,14 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
     /* large enough for "%#.#f" --chip */
     /* what about long double NVs? --jhi */
 
-    PERL_ARGS_ASSERT_SV_VCATPVFN;
+    PERL_ARGS_ASSERT_SV_VCATPVFN_FLAGS;
     PERL_UNUSED_ARG(maybe_tainted);
 
+    if (flags & SV_GMAGIC)
+        SvGETMAGIC(sv);
+
     /* no matter what, this is a string now */
-    (void)SvPV_force(sv, origlen);
+    (void)SvPV_force_nomg(sv, origlen);
 
     /* special-case "", "%s", and "%-p" (SVf - see below) */
     if (patlen == 0)
@@ -10050,10 +10065,12 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
     if (patlen == 2 && pat[0] == '%' && pat[1] == 's') {
        if (args) {
            const char * const s = va_arg(*args, char*);
-           sv_catpv(sv, s ? s : nullstr);
+           sv_catpv_nomg(sv, s ? s : nullstr);
        }
        else if (svix < svmax) {
-           sv_catsv(sv, *svargs);
+           /* we want get magic on the source but not the target. sv_catsv can't do that, though */
+           SvGETMAGIC(*svargs);
+           sv_catsv_nomg(sv, *svargs);
        }
        else
            S_vcatpvfn_missing_argument(aTHX);
@@ -10062,7 +10079,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
     if (args && patlen == 3 && pat[0] == '%' &&
                pat[1] == '-' && pat[2] == 'p') {
        argsv = MUTABLE_SV(va_arg(*args, void*));
-       sv_catsv(sv, argsv);
+       sv_catsv_nomg(sv, argsv);
        return;
     }
 
@@ -10085,7 +10102,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                if (digits && digits < sizeof(ebuf) - NV_DIG - 10) {
                     /* 0, point, slack */
                    Gconvert(nv, (int)digits, 0, ebuf);
-                   sv_catpv(sv, ebuf);
+                   sv_catpv_nomg(sv, ebuf);
                    if (*ebuf)  /* May return an empty string for digits==0 */
                        return;
                }
@@ -10093,7 +10110,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                STRLEN l;
 
                if ((p = F0convert(nv, ebuf + sizeof ebuf, &l))) {
-                   sv_catpvn(sv, p, l);
+                   sv_catpvn_nomg(sv, p, l);
                    return;
                }
            }
@@ -10164,9 +10181,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
        for (q = p; q < patend && *q != '%'; ++q) ;
        if (q > p) {
            if (has_utf8 && !pat_utf8)
-               sv_catpvn_utf8_upgrade(sv, p, q - p, nsv);
+               sv_catpvn_nomg_utf8_upgrade(sv, p, q - p, nsv);
            else
-               sv_catpvn(sv, p, q - p);
+               sv_catpvn_nomg(sv, p, q - p);
            p = q;
        }
        if (q++ >= patend)
@@ -10198,9 +10215,12 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                %p              include pointer address (standard)      
                %-p     (SVf)   include an SV (previously %_)
                %-<num>p        include an SV with precision <num>      
-               %<num>p         reserved for future extensions
+               %2p             include a HEK
+               %3p             include a HEK with precision of 256
+               %<num>p         (where num != 2 or 3) reserved for future
+                               extensions
 
-       Robin Barker 2005-07-14
+       Robin Barker 2005-07-14 (but modified since)
 
                %1p     (VDf)   removed.  RMB 2007-10-19
 */
@@ -10222,6 +10242,14 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                        is_utf8 = TRUE;
                    goto string;
                }
+               else if (n==2 || n==3) {        /* HEKf */
+                   HEK * const hek = va_arg(*args, HEK *);
+                   eptr = HEK_KEY(hek);
+                   elen = HEK_LEN(hek);
+                   if (HEK_UTF8(hek)) is_utf8 = TRUE;
+                   if (n==3) precis = 256, has_precis = TRUE;
+                   goto string;
+               }
                else if (n) {
                    Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL),
                                     "internal %%<num>p might conflict with future printf extensions");
@@ -10374,7 +10402,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                 * back into v-string notation and then let the
                 * vectorize happen normally
                 */
-               if (sv_derived_from(vecsv, "version")) {
+               if (sv_isobject(vecsv) && sv_derived_from(vecsv, "version")) {
                    char *version = savesvpv(vecsv);
                    if ( hv_exists(MUTABLE_HV(SvRV(vecsv)), "alpha", 5 ) ) {
                        Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
@@ -11009,7 +11037,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                }
            }
            else
-               sv_setuv_mg(argsv, (UV)i);
+               sv_setuv_mg(argsv, has_utf8 ? (UV)sv_len_utf8(sv) : (UV)i);
            continue;   /* not "break" */
 
            /* UNKNOWN */
@@ -11029,7 +11057,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                    sv_catpvs(msg, "\"%");
                    for (f = fmtstart; f < fmtend; f++) {
                        if (isPRINT(*f)) {
-                           sv_catpvn(msg, f, 1);
+                           sv_catpvn_nomg(msg, f, 1);
                        } else {
                            Perl_sv_catpvf(aTHX_ msg,
                                           "\\%03"UVof, (UV)*f & 0xFF);
@@ -11147,7 +11175,7 @@ the main function, perl_clone().
 
 The foo_dup() functions make an exact copy of an existing foo thingy.
 During the course of a cloning, a hash table is used to map old addresses
-to new addresses. The table is created and manipulated with the
+to new addresses.  The table is created and manipulated with the
 ptr_table_* functions.
 
 =cut
@@ -11337,7 +11365,7 @@ Perl_dirp_dup(pTHX_ DIR *const dp, CLONE_PARAMS *const param)
     register const Direntry_t *dirent;
     char smallbuf[256];
     char *name = NULL;
-    STRLEN len = -1;
+    STRLEN len = 0;
     long pos;
 #endif
 
@@ -11797,7 +11825,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
 
     PERL_ARGS_ASSERT_SV_DUP_COMMON;
 
-    if (SvTYPE(sstr) == SVTYPEMASK) {
+    if (SvTYPE(sstr) == (svtype)SVTYPEMASK) {
 #ifdef DEBUG_LEAKING_SCALARS_ABORT
        abort();
 #endif
@@ -11815,11 +11843,33 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
            const HEK * const hvname = HvNAME_HEK(sstr);
            if (hvname) {
                /** don't clone stashes if they already exist **/
-               dstr = MUTABLE_SV(gv_stashpvn(HEK_KEY(hvname), HEK_LEN(hvname), 0));
+               dstr = MUTABLE_SV(gv_stashpvn(HEK_KEY(hvname), HEK_LEN(hvname),
+                                                HEK_UTF8(hvname) ? SVf_UTF8 : 0));
                ptr_table_store(PL_ptr_table, sstr, dstr);
                return dstr;
            }
         }
+       else if (SvTYPE(sstr) == SVt_PVGV && !SvFAKE(sstr)) {
+           HV *stash = GvSTASH(sstr);
+           const HEK * hvname;
+           if (stash && (hvname = HvNAME_HEK(stash))) {
+               /** don't clone GVs if they already exist **/
+               SV **svp;
+               stash = gv_stashpvn(HEK_KEY(hvname), HEK_LEN(hvname),
+                                   HEK_UTF8(hvname) ? SVf_UTF8 : 0);
+               svp = hv_fetch(
+                       stash, GvNAME(sstr),
+                       GvNAMEUTF8(sstr)
+                           ? -GvNAMELEN(sstr)
+                           :  GvNAMELEN(sstr),
+                       0
+                     );
+               if (svp && *svp && SvTYPE(*svp) == SVt_PVGV) {
+                   ptr_table_store(PL_ptr_table, sstr, *svp);
+                   return *svp;
+               }
+           }
+        }
     }
 
     /* create anew and remember what it is */
@@ -12056,8 +12106,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                        const struct xpvhv_aux * const saux = HvAUX(sstr);
                        struct xpvhv_aux * const daux = HvAUX(dstr);
                        /* This flag isn't copied.  */
-                       /* SvOOK_on(hv) attacks the IV flags.  */
-                       SvFLAGS(dstr) |= SVf_OOK;
+                       SvOOK_on(dstr);
 
                        if (saux->xhv_name_count) {
                            HEK ** const sname = saux->xhv_name_u.xhvnameu_names;
@@ -12132,11 +12181,13 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                    OP_REFCNT_LOCK;
                    CvROOT(dstr) = OpREFCNT_inc(CvROOT(dstr));
                    OP_REFCNT_UNLOCK;
-                   CvFILE(dstr) = SAVEPV(CvFILE(dstr));
+                   CvSLABBED_off(dstr);
                } else if (CvCONST(dstr)) {
                    CvXSUBANY(dstr).any_ptr =
                        sv_dup_inc((const SV *)CvXSUBANY(dstr).any_ptr, param);
                }
+               assert(!CvSLABBED(dstr));
+               if (CvDYNFILE(dstr)) CvFILE(dstr) = SAVEPV(CvFILE(dstr));
                /* don't dup if copying back - CvGV isn't refcounted, so the
                 * duped GV may never be freed. A bit of a hack! DAPM */
                SvANY(MUTABLE_CV(dstr))->xcv_gv =
@@ -12225,6 +12276,7 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param)
            Perl_croak(aTHX_ "Cloning substitution context is unimplemented");
        }
        else {
+           ncx->blk_oldcop = (COP*)any_dup(ncx->blk_oldcop, param->proto_perl);
            switch (CxTYPE(ncx)) {
            case CXt_SUB:
                ncx->blk_sub.cv         = (ncx->blk_sub.olddepth == 0
@@ -12243,6 +12295,7 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param)
                ncx->blk_eval.old_namesv = sv_dup_inc(ncx->blk_eval.old_namesv,
                                                      param);
                ncx->blk_eval.cur_text  = sv_dup(ncx->blk_eval.cur_text, param);
+               ncx->blk_eval.cv = cv_dup(ncx->blk_eval.cv, param);
                break;
            case CXt_LOOP_LAZYSV:
                ncx->blk_loop.state_u.lazysv.end
@@ -12276,6 +12329,8 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param)
                break;
            case CXt_BLOCK:
            case CXt_NULL:
+           case CXt_WHEN:
+           case CXt_GIVEN:
                break;
            }
        }
@@ -12455,7 +12510,6 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
            TOPLONG(nss,ix) = longval;
            break;
        case SAVEt_I32:                         /* I32 reference */
-       case SAVEt_COP_ARYBASE:                 /* call CopARYBASE_set */
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = any_dup(ptr, proto_perl);
            i = POPINT(ss,ix);
@@ -12622,28 +12676,6 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
                    = pv_dup(old_state->re_state_reginput);
                new_state->re_state_regeol
                    = pv_dup(old_state->re_state_regeol);
-               new_state->re_state_regoffs
-                   = (regexp_paren_pair*)
-                       any_dup(old_state->re_state_regoffs, proto_perl);
-               new_state->re_state_reglastparen
-                   = (U32*) any_dup(old_state->re_state_reglastparen, 
-                             proto_perl);
-               new_state->re_state_reglastcloseparen
-                   = (U32*)any_dup(old_state->re_state_reglastcloseparen,
-                             proto_perl);
-               /* XXX This just has to be broken. The old save_re_context
-                  code did SAVEGENERICPV(PL_reg_start_tmp);
-                  PL_reg_start_tmp is char **.
-                  Look above to what the dup code does for
-                  SAVEt_GENERIC_PVREF
-                  It can never have worked.
-                  So this is merely a faithful copy of the exiting bug:  */
-               new_state->re_state_reg_start_tmp
-                   = (char **) pv_dup((char *)
-                                     old_state->re_state_reg_start_tmp);
-               /* I assume that it only ever "worked" because no-one called
-                  (pseudo)fork while the regexp engine had re-entered itself.
-               */
 #ifdef PERL_OLD_COPY_ON_WRITE
                new_state->re_state_nrs
                    = sv_dup(old_state->re_state_nrs, param);
@@ -12731,19 +12763,19 @@ ready to run at the exact same point as the previous one.
 The pseudo-fork code uses COPY_STACKS while the
 threads->create doesn't.
 
-CLONEf_KEEP_PTR_TABLE
+CLONEf_KEEP_PTR_TABLE -
 perl_clone keeps a ptr_table with the pointer of the old
 variable as a key and the new variable as a value,
 this allows it to check if something has been cloned and not
 clone it again but rather just use the value and increase the
-refcount. If KEEP_PTR_TABLE is not set then perl_clone will kill
+refcount.  If KEEP_PTR_TABLE is not set then perl_clone will kill
 the ptr_table using the function
 C<ptr_table_free(PL_ptr_table); PL_ptr_table = NULL;>,
 reason to keep it around is if you want to dup some of your own
 variable who are outside the graph perl scans, example of this
-code is in threads.xs create
+code is in threads.xs create.
 
-CLONEf_CLONE_HOST
+CLONEf_CLONE_HOST -
 This is a win32 thing, it is ignored on unix, it tells perls
 win32host code (which is c++) to clone itself, this is needed on
 win32 if you want to run two threads at the same time,
@@ -12874,28 +12906,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_hash_seed       = proto_perl->Ihash_seed;
     PL_rehash_seed     = proto_perl->Irehash_seed;
 
-    SvANY(&PL_sv_undef)                = NULL;
-    SvREFCNT(&PL_sv_undef)     = (~(U32)0)/2;
-    SvFLAGS(&PL_sv_undef)      = SVf_READONLY|SVt_NULL;
-    SvREFCNT(&PL_sv_no)                = (~(U32)0)/2;
-    SvFLAGS(&PL_sv_no)         = SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
-                                 |SVp_POK|SVf_POK|SVf_READONLY|SVt_PVNV;
-
-    SvANY(&PL_sv_yes)          = new_XPVNV();
-    SvREFCNT(&PL_sv_yes)       = (~(U32)0)/2;
-    SvFLAGS(&PL_sv_yes)                = SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
-                                 |SVp_POK|SVf_POK|SVf_READONLY|SVt_PVNV;
-
     /* dbargs array probably holds garbage */
     PL_dbargs          = NULL;
 
     PL_compiling = proto_perl->Icompiling;
 
-#ifdef PERL_DEBUG_READONLY_OPS
-    PL_slabs = NULL;
-    PL_slab_count = 0;
-#endif
-
     /* pseudo environmental stuff */
     PL_origargc                = proto_perl->Iorigargc;
     PL_origargv                = proto_perl->Iorigargv;
@@ -12935,7 +12950,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* RE engine related */
     Zero(&PL_reg_state, 1, struct re_save_state);
-    PL_reginterp_cnt   = 0;
     PL_regmatch_slab   = NULL;
 
     PL_sub_generation  = proto_perl->Isub_generation;
@@ -12968,10 +12982,10 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_in_clean_objs   = proto_perl->Iin_clean_objs;
     PL_in_clean_all    = proto_perl->Iin_clean_all;
 
-    PL_uid             = proto_perl->Iuid;
-    PL_euid            = proto_perl->Ieuid;
-    PL_gid             = proto_perl->Igid;
-    PL_egid            = proto_perl->Iegid;
+    PL_delaymagic_uid  = proto_perl->Idelaymagic_uid;
+    PL_delaymagic_euid = proto_perl->Idelaymagic_euid;
+    PL_delaymagic_gid  = proto_perl->Idelaymagic_gid;
+    PL_delaymagic_egid = proto_perl->Idelaymagic_egid;
     PL_nomemok         = proto_perl->Inomemok;
     PL_an              = proto_perl->Ian;
     PL_evalseq         = proto_perl->Ievalseq;
@@ -12990,8 +13004,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_hints           = proto_perl->Ihints;
 
-    PL_amagic_generation       = proto_perl->Iamagic_generation;
-
 #ifdef USE_LOCALE_COLLATE
     PL_collation_ix    = proto_perl->Icollation_ix;
     PL_collation_standard      = proto_perl->Icollation_standard;
@@ -13033,9 +13045,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_destroyhook     = proto_perl->Idestroyhook;
     PL_signalhook      = proto_perl->Isignalhook;
 
-#ifdef THREADS_HAVE_PIDS
-    PL_ppid            = proto_perl->Ippid;
-#endif
+    PL_globhook                = proto_perl->Iglobhook;
 
     /* swatch cache */
     PL_last_swash_hv   = NULL; /* reinits on demand */
@@ -13102,12 +13112,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* regex stuff */
 
-    PL_screamfirst     = NULL;
-    PL_screamnext      = NULL;
-    PL_maxscream       = -1;                   /* reinits on demand */
-    PL_lastscream      = NULL;
-
-
     PL_regdummy                = proto_perl->Iregdummy;
     PL_colorset                = 0;            /* reinits PL_colors[] */
     /*PL_colors[6]     = {0,0,0,0,0,0};*/
@@ -13130,21 +13134,9 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_ptr_table = ptr_table_new();
 
     /* initialize these special pointers as early as possible */
+    init_constants();
     ptr_table_store(PL_ptr_table, &proto_perl->Isv_undef, &PL_sv_undef);
-
-    SvANY(&PL_sv_no)           = new_XPVNV();
-    SvPV_set(&PL_sv_no, savepvn(PL_No, 0));
-    SvCUR_set(&PL_sv_no, 0);
-    SvLEN_set(&PL_sv_no, 1);
-    SvIV_set(&PL_sv_no, 0);
-    SvNV_set(&PL_sv_no, 0);
     ptr_table_store(PL_ptr_table, &proto_perl->Isv_no, &PL_sv_no);
-
-    SvPV_set(&PL_sv_yes, savepvn(PL_Yes, 1));
-    SvCUR_set(&PL_sv_yes, 1);
-    SvLEN_set(&PL_sv_yes, 2);
-    SvIV_set(&PL_sv_yes, 1);
-    SvNV_set(&PL_sv_yes, 1);
     ptr_table_store(PL_ptr_table, &proto_perl->Isv_yes, &PL_sv_yes);
 
     /* create (a non-shared!) shared string table */
@@ -13153,10 +13145,7 @@ 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);
 
-    /* These two PVs will be free'd special way so must set them same way op.c does */
-    PL_compiling.cop_stashpv = savesharedpv(PL_compiling.cop_stashpv);
-    ptr_table_store(PL_ptr_table, proto_perl->Icompiling.cop_stashpv, PL_compiling.cop_stashpv);
-
+    /* 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);
 
@@ -13214,6 +13203,15 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_regex_padav = av_dup_inc(proto_perl->Iregex_padav, param);
     PL_regex_pad = AvARRAY(PL_regex_padav);
 
+    PL_stashpadmax     = proto_perl->Istashpadmax;
+    PL_stashpadix      = proto_perl->Istashpadix ;
+    Newx(PL_stashpad, PL_stashpadmax, HV *);
+    {
+       PADOFFSET o = 0;
+       for (; o < PL_stashpadmax; ++o)
+           PL_stashpad[o] = hv_dup(proto_perl->Istashpad[o], param);
+    }
+
     /* shortcuts to various I/O objects */
     PL_ofsgv            = gv_dup_inc(proto_perl->Iofsgv, param);
     PL_stdingv         = gv_dup(proto_perl->Istdingv, param);
@@ -13239,7 +13237,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* symbol tables */
     PL_defstash                = hv_dup_inc(proto_perl->Idefstash, param);
-    PL_curstash                = hv_dup(proto_perl->Icurstash, param);
+    PL_curstash                = hv_dup_inc(proto_perl->Icurstash, param);
     PL_debstash                = hv_dup(proto_perl->Idebstash, param);
     PL_globalstash     = hv_dup(proto_perl->Iglobalstash, param);
     PL_curstname       = sv_dup_inc(proto_perl->Icurstname, param);
@@ -13340,12 +13338,60 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_numeric_radix_sv        = sv_dup_inc(proto_perl->Inumeric_radix_sv, param);
 #endif /* !USE_LOCALE_NUMERIC */
 
-    /* utf8 character classes */
+    /* 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);
+
+    /* utf8 character class swashes */
     PL_utf8_alnum      = sv_dup_inc(proto_perl->Iutf8_alnum, param);
-    PL_utf8_ascii      = sv_dup_inc(proto_perl->Iutf8_ascii, 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_cntrl      = sv_dup_inc(proto_perl->Iutf8_cntrl, 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);
@@ -13370,9 +13416,14 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_utf8_tofold     = sv_dup_inc(proto_perl->Iutf8_tofold, param);
     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_idcont     = sv_dup_inc(proto_perl->Iutf8_idcont, param);
     PL_utf8_xidcont    = sv_dup_inc(proto_perl->Iutf8_xidcont, param);
-    PL_utf8_foldable   = hv_dup_inc(proto_perl->Iutf8_foldable, param);
+    PL_utf8_foldable   = sv_dup_inc(proto_perl->Iutf8_foldable, param);
+    PL_utf8_quotemeta  = sv_dup_inc(proto_perl->Iutf8_quotemeta, 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) {
@@ -13615,6 +13666,38 @@ Perl_clone_params_new(PerlInterpreter *const from, PerlInterpreter *const to)
 
 #endif /* USE_ITHREADS */
 
+void
+Perl_init_constants(pTHX)
+{
+    SvREFCNT(&PL_sv_undef)     = (~(U32)0)/2;
+    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;
+    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;
+    SvFLAGS(&PL_sv_yes)                = SVt_PVNV|SVf_READONLY
+                                 |SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
+                                 |SVp_POK|SVf_POK;
+
+    SvPV_set(&PL_sv_no, (char*)PL_No);
+    SvCUR_set(&PL_sv_no, 0);
+    SvLEN_set(&PL_sv_no, 0);
+    SvIV_set(&PL_sv_no, 0);
+    SvNV_set(&PL_sv_no, 0);
+
+    SvPV_set(&PL_sv_yes, (char*)PL_Yes);
+    SvCUR_set(&PL_sv_yes, 1);
+    SvLEN_set(&PL_sv_yes, 0);
+    SvIV_set(&PL_sv_yes, 1);
+    SvNV_set(&PL_sv_yes, 1);
+}
+
 /*
 =head1 Unicode Support
 
@@ -13627,7 +13710,7 @@ will be converted into Unicode (and UTF-8).
 If the sv already is UTF-8 (or if it is not POK), or if the encoding
 is not a reference, nothing is done to the sv.  If the encoding is not
 an C<Encode::XS> Encoding object, bad things will happen.
-(See F<lib/encoding.pm> and L<Encode>).
+(See F<lib/encoding.pm> and L<Encode>.)
 
 The PV of the sv is returned.
 
@@ -13697,7 +13780,7 @@ assumed to be octets in that encoding and decoding the input starts
 from the position which (PV + *offset) pointed to.  The dsv will be
 concatenated the decoded UTF-8 string from ssv.  Decoding will terminate
 when the string tstr appears in decoding output or the input ends on
-the PV of the ssv. The value which the offset points will be modified
+the PV of the ssv.  The value which the offset points will be modified
 to the last input position on the ssv.
 
 Returns TRUE if the terminator was found, else returns FALSE.
@@ -13813,7 +13896,7 @@ S_find_array_subscript(pTHX_ const AV *const av, const SV *const val)
     return -1;
 }
 
-/* S_varname(): return the name of a variable, optionally with a subscript.
+/* varname(): return the name of a variable, optionally with a subscript.
  * If gv is non-zero, use the name of that global, along with gvtype (one
  * of "$", "@", "%"); otherwise use the name of the lexical at pad offset
  * targ.  Depending on the value of the subscript_type flag, return:
@@ -13824,13 +13907,13 @@ S_find_array_subscript(pTHX_ const AV *const av, const SV *const val)
 #define FUV_SUBSCRIPT_HASH     3       /* "$foo{keyname}" */
 #define FUV_SUBSCRIPT_WITHIN   4       /* "within @foo"   */
 
-STATIC SV*
-S_varname(pTHX_ const GV *const gv, const char gvtype, PADOFFSET targ,
+SV*
+Perl_varname(pTHX_ const GV *const gv, const char gvtype, PADOFFSET targ,
        const SV *const keyname, I32 aindex, int subscript_type)
 {
 
     SV * const name = sv_newmortal();
-    if (gv) {
+    if (gv && isGV(gv)) {
        char buffer[2];
        buffer[0] = gvtype;
        buffer[1] = 0;
@@ -13849,22 +13932,25 @@ S_varname(pTHX_ const GV *const gv, const char gvtype, PADOFFSET targ,
        }
     }
     else {
-       CV * const cv = find_runcv(NULL);
+       CV * const cv = gv ? ((CV *)gv) : find_runcv(NULL);
        SV *sv;
        AV *av;
 
+       assert(!cv || SvTYPE(cv) == SVt_PVCV);
+
        if (!cv || !CvPADLIST(cv))
            return NULL;
        av = MUTABLE_AV((*av_fetch(CvPADLIST(cv), 0, FALSE)));
        sv = *av_fetch(av, targ, FALSE);
-       sv_setpvn(name, SvPV_nolen_const(sv), SvCUR(sv));
+       sv_setsv(name, sv);
     }
 
     if (subscript_type == FUV_SUBSCRIPT_HASH) {
        SV * const sv = newSV(0);
        *SvPVX(name) = '$';
        Perl_sv_catpvf(aTHX_ name, "{%s}",
-           pv_display(sv,SvPVX_const(keyname), SvCUR(keyname), 0, 32));
+           pv_pretty(sv, SvPVX_const(keyname), SvCUR(keyname), 32, NULL, NULL,
+                   PERL_PV_PRETTY_DUMP | PERL_PV_ESCAPE_UNI_DETECT ));
        SvREFCNT_dec(sv);
     }
     else if (subscript_type == FUV_SUBSCRIPT_ARRAY) {
@@ -13883,12 +13969,12 @@ S_varname(pTHX_ const GV *const gv, const char gvtype, PADOFFSET targ,
 /*
 =for apidoc find_uninit_var
 
-Find the name of the undefined variable (if any) that caused the operator o
+Find the name of the undefined variable (if any) that caused the operator
 to issue a "Use of uninitialized value" warning.
-If match is true, only return a name if it's value matches uninit_sv.
+If match is true, only return a name if its value matches uninit_sv.
 So roughly speaking, if a unary operator (such as OP_COS) generates a
 warning, then following the direct child of the op may yield an
-OP_PADSV or OP_GV that gives the name of the undefined variable. On the
+OP_PADSV or OP_GV that gives the name of the undefined variable.  On the
 other hand, with OP_ADD there are two branches to follow, so we only print
 the variable name if we get an exact match.
 
@@ -13938,9 +14024,11 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
                    break;
                sv = hash ? MUTABLE_SV(GvHV(gv)): MUTABLE_SV(GvAV(gv));
            }
-           else /* @{expr}, %{expr} */
+           else if (obase == PL_op) /* @{expr}, %{expr} */
                return find_uninit_var(cUNOPx(obase)->op_first,
                                                    uninit_sv, match);
+           else /* @{expr}, %{expr} as a sub-expression */
+               return NULL;
        }
 
        /* attempt to find a match within the aggregate */
@@ -13962,6 +14050,19 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
                                    keysv, index, subscript_type);
       }
 
+    case OP_RV2SV:
+       if (cUNOPx(obase)->op_first->op_type == OP_GV) {
+           /* $global */
+           gv = cGVOPx_gv(cUNOPx(obase)->op_first);
+           if (!gv || !GvSTASH(gv))
+               break;
+           if (match && (GvSV(gv) != uninit_sv))
+               break;
+           return varname(gv, '$', 0, NULL, 0, FUV_SUBSCRIPT_NONE);
+       }
+       /* ${expr} */
+       return find_uninit_var(cUNOPx(obase)->op_first, uninit_sv, 1);
+
     case OP_PADSV:
        if (match && PAD_SVl(obase->op_targ) != uninit_sv)
            break;
@@ -13974,21 +14075,20 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
            break;
        return varname(gv, '$', 0, NULL, 0, FUV_SUBSCRIPT_NONE);
 
-    case OP_AELEMFAST:
-       if (obase->op_flags & OPf_SPECIAL) { /* lexical array */
-           if (match) {
-               SV **svp;
-               AV *av = MUTABLE_AV(PAD_SV(obase->op_targ));
-               if (!av || SvRMAGICAL(av))
-                   break;
-               svp = av_fetch(av, (I32)obase->op_private, FALSE);
-               if (!svp || *svp != uninit_sv)
-                   break;
-           }
-           return varname(NULL, '$', obase->op_targ,
-                   NULL, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
+    case OP_AELEMFAST_LEX:
+       if (match) {
+           SV **svp;
+           AV *av = MUTABLE_AV(PAD_SV(obase->op_targ));
+           if (!av || SvRMAGICAL(av))
+               break;
+           svp = av_fetch(av, (I32)obase->op_private, FALSE);
+           if (!svp || *svp != uninit_sv)
+               break;
        }
-       else {
+       return varname(NULL, '$', obase->op_targ,
+                      NULL, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
+    case OP_AELEMFAST:
+       {
            gv = cGVOPx_gv(obase);
            if (!gv)
                break;
@@ -14015,6 +14115,9 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
 
     case OP_AELEM:
     case OP_HELEM:
+    {
+       bool negate = FALSE;
+
        if (PL_op == obase)
            /* $a[uninit_expr] or $h{uninit_expr} */
            return find_uninit_var(cBINOPx(obase)->op_last, uninit_sv, match);
@@ -14040,28 +14143,43 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
        if (!sv)
            break;
 
+       if (kid && kid->op_type == OP_NEGATE) {
+           negate = TRUE;
+           kid = cUNOPx(kid)->op_first;
+       }
+
        if (kid && kid->op_type == OP_CONST && SvOK(cSVOPx_sv(kid))) {
            /* index is constant */
+           SV* kidsv;
+           if (negate) {
+               kidsv = sv_2mortal(newSVpvs("-"));
+               sv_catsv(kidsv, cSVOPx_sv(kid));
+           }
+           else
+               kidsv = cSVOPx_sv(kid);
            if (match) {
                if (SvMAGICAL(sv))
                    break;
                if (obase->op_type == OP_HELEM) {
-                   HE* he = hv_fetch_ent(MUTABLE_HV(sv), cSVOPx_sv(kid), 0, 0);
+                   HE* he = hv_fetch_ent(MUTABLE_HV(sv), kidsv, 0, 0);
                    if (!he || HeVAL(he) != uninit_sv)
                        break;
                }
                else {
-                   SV * const * const svp = av_fetch(MUTABLE_AV(sv), SvIV(cSVOPx_sv(kid)), FALSE);
+                   SV * const * const svp = av_fetch(MUTABLE_AV(sv),
+                       negate ? - SvIV(cSVOPx_sv(kid)) : SvIV(cSVOPx_sv(kid)),
+                       FALSE);
                    if (!svp || *svp != uninit_sv)
                        break;
                }
            }
            if (obase->op_type == OP_HELEM)
                return varname(gv, '%', o->op_targ,
-                           cSVOPx_sv(kid), 0, FUV_SUBSCRIPT_HASH);
+                           kidsv, 0, FUV_SUBSCRIPT_HASH);
            else
                return varname(gv, '@', o->op_targ, NULL,
-                           SvIV(cSVOPx_sv(kid)), FUV_SUBSCRIPT_ARRAY);
+                   negate ? - SvIV(cSVOPx_sv(kid)) : SvIV(cSVOPx_sv(kid)),
+                   FUV_SUBSCRIPT_ARRAY);
        }
        else  {
            /* index is an expression;
@@ -14087,6 +14205,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
                o->op_targ, NULL, 0, FUV_SUBSCRIPT_WITHIN);
        }
        break;
+    }
 
     case OP_AASSIGN:
        /* only examine RHS */
@@ -14117,6 +14236,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
 
     /* ops where $_ may be an implicit arg */
     case OP_TRANS:
+    case OP_TRANSR:
     case OP_SUBST:
     case OP_MATCH:
        if ( !(obase->op_flags & OPf_STACKED)) {
@@ -14143,7 +14263,6 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
 
 
     case OP_ENTEREVAL: /* could be eval $undef or $x='$undef'; eval $x */
-    case OP_RV2SV:
     case OP_CUSTOM: /* XS or custom code could trigger random warnings */
 
        /* the following ops are capable of returning PL_sv_undef even for
@@ -14260,8 +14379,13 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
        if (!o)
            break;
 
-       /* if all except one arg are constant, or have no side-effects,
-        * or are optimized away, then it's unambiguous */
+       /* This loop checks all the kid ops, skipping any that cannot pos-
+        * sibly be responsible for the uninitialized value; i.e., defined
+        * constants and ops that return nothing.  If there is only one op
+        * 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.
+        */
        o2 = NULL;
        for (kid=o; kid; kid = kid->op_sibling) {
            if (kid) {
@@ -14269,12 +14393,6 @@ 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)
-                 || (
-                     /* @$a and %$a, but not @a or %a */
-                       (type == OP_RV2AV || type == OP_RV2HV)
-                    && cUNOPx(kid)->op_first
-                    && cUNOPx(kid)->op_first->op_type != OP_GV
-                    )
                )
                continue;
            }
@@ -14303,7 +14421,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
 /*
 =for apidoc report_uninit
 
-Print appropriate "Use of uninitialized variable" warning
+Print appropriate "Use of uninitialized variable" warning.
 
 =cut
 */
@@ -14314,13 +14432,14 @@ Perl_report_uninit(pTHX_ const SV *uninit_sv)
     dVAR;
     if (PL_op) {
        SV* varname = NULL;
-       if (uninit_sv) {
+       if (uninit_sv && PL_curpad) {
            varname = find_uninit_var(PL_op, uninit_sv,0);
            if (varname)
                sv_insert(varname, 0, 0, " ", 1);
        }
-       Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED), PL_warn_uninit,
-               varname ? SvPV_nolen_const(varname) : "",
+       /* diag_listed_as: Use of uninitialized value%s */
+       Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED), PL_warn_uninit_sv,
+               SVfARG(varname ? varname : &PL_sv_no),
                " in ", OP_DESC(PL_op));
     }
     else
@@ -14332,8 +14451,8 @@ Perl_report_uninit(pTHX_ const SV *uninit_sv)
  * Local variables:
  * c-indentation-style: bsd
  * c-basic-offset: 4
- * indent-tabs-mode: t
+ * indent-tabs-mode: nil
  * End:
  *
- * ex: set ts=8 sts=4 sw=4 noet:
+ * ex: set ts=8 sts=4 sw=4 et:
  */