This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Use HEKf
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index 75238bc..3360bf4 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);
     }
@@ -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,
@@ -1729,7 +1719,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;
@@ -2971,6 +2961,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
                if (lp) {
                    *lp = SvCUR(buffer);
                }
+                if ( SvUTF8(buffer) ) SvUTF8_on(sv);
                return SvPVX(buffer);
            }
            else {
@@ -3675,7 +3666,8 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
        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 */
     }
 
@@ -3854,16 +3846,21 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
                            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)));
+                                        ? "Constant subroutine %"HEKf
+                                          "::%"HEKf" redefined"
+                                        : "Subroutine %"HEKf"::%"HEKf
+                                          " redefined"),
+                               HEKfARG(
+                                HvNAME_HEK(GvSTASH((const GV *)dstr))
+                               ),
+                               HEKfARG(GvENAME_HEK(MUTABLE_GV(dstr))));
                        }
                    }
                if (!intro)
-                   cv_ckproto_len(cv, (const GV *)dstr,
+                   cv_ckproto_len_flags(cv, (const GV *)dstr,
                                   SvPOK(sref) ? SvPVX_const(sref) : NULL,
-                                  SvPOK(sref) ? SvCUR(sref) : 0);
+                                  SvPOK(sref) ? SvCUR(sref)  : 0,
+                                   SvPOK(sref) ? SvUTF8(sref) : 0);
            }
            GvCVGEN(dstr) = 0; /* Switch off cacheness. */
            GvASSUMECV_on(dstr);
@@ -4171,7 +4168,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);
@@ -4588,6 +4585,49 @@ 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);
+            return;
+       }
+        {
+           sv_upgrade(sv, SVt_PV);
+           sv_usepvn_flags(sv, (char *)HEK_KEY(share_hek_hek(hek)), HEK_LEN(hek), SV_HAS_TRAILING_NUL);
+           SvLEN_set(sv, 0);
+           SvREADONLY_on(sv);
+           SvFAKE_on(sv);
+           SvPOK_on(sv);
+           if (HEK_UTF8(hek))
+               SvUTF8_on(sv);
+            return;
+       }
+    }
+}
+
+
 /*
 =for apidoc sv_usepvn_flags
 
@@ -4776,7 +4816,7 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
     }
 #else
     if (SvREADONLY(sv)) {
-       if (SvFAKE(sv)) {
+       if (SvFAKE(sv) && !isGV_with_GP(sv)) {
            const char * const pvx = SvPVX_const(sv);
            const STRLEN len = SvCUR(sv);
            SvFAKE_off(sv);
@@ -4954,12 +4994,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);
+        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);
+       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);
@@ -5405,6 +5476,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);
@@ -5857,7 +5929,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;
 
@@ -5877,10 +5948,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);
 
@@ -5927,7 +5998,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
@@ -6008,7 +6079,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);
                }
 
@@ -6285,8 +6356,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;
        }
@@ -7857,7 +7928,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)
@@ -8038,7 +8109,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)
@@ -8364,7 +8435,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))
@@ -8649,7 +8720,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;
     }
@@ -8792,7 +8863,8 @@ 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 */
@@ -8847,18 +8919,9 @@ 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
@@ -8877,11 +8940,11 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **const st, GV **const gvp, const I32 lref)
                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;
@@ -8893,8 +8956,7 @@ 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)) {
+       if (lref & ~GV_ADDMG && !GvCVu(gv)) {
            SV *tmpsv;
            ENTER;
            tmpsv = newSV(0);
@@ -9073,12 +9135,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)) {
@@ -9116,6 +9174,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
@@ -9485,6 +9571,7 @@ Perl_sv_unref_flags(pTHX_ SV *const ref, const U32 flags)
 =for apidoc sv_untaint
 
 Untaint an SV. Use C<SvTAINTED_off> instead.
+
 =cut
 */
 
@@ -9504,6 +9591,7 @@ Perl_sv_untaint(pTHX_ SV *const sv)
 =for apidoc sv_tainted
 
 Test an SV for taintedness. Use C<SvTAINTED> instead.
+
 =cut
 */
 
@@ -10090,9 +10178,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
 */
@@ -10114,6 +10205,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");
@@ -11689,7 +11788,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
@@ -11707,7 +11806,8 @@ 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;
            }
@@ -12024,11 +12124,11 @@ 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));
                } else if (CvCONST(dstr)) {
                    CvXSUBANY(dstr).any_ptr =
                        sv_dup_inc((const SV *)CvXSUBANY(dstr).any_ptr, param);
                }
+               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 =
@@ -12347,7 +12447,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);
@@ -12994,11 +13093,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* regex stuff */
 
-    PL_screamfirst     = 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};*/
@@ -13233,10 +13327,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* utf8 character classes */
     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_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);
@@ -13261,9 +13353,10 @@ 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);
 
 
     if (proto_perl->Ipsig_pend) {
@@ -13748,7 +13841,7 @@ S_varname(pTHX_ const GV *const gv, const char gvtype, PADOFFSET targ,
            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) {
@@ -13853,6 +13946,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;
@@ -13905,6 +14011,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);
@@ -13930,28 +14039,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;
@@ -13977,6 +14101,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 */
@@ -14033,7 +14158,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
@@ -14209,8 +14333,9 @@ Perl_report_uninit(pTHX_ const SV *uninit_sv)
            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