This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Allow PADTMPs’ strings to be swiped
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index 8ba0505..4c3fdbb 100644 (file)
--- a/sv.c
+++ b/sv.c
 # include <stdint.h>
 #endif
 
-#define FCALL *f
-
 #ifdef __Lynx__
 /* Missing proto on LynxOS */
   char *gconvert(double, int, int,  char *);
 #endif
 
+/* void Gconvert: on Linux at least, gcvt (which Gconvert gets deffed to),
+ * has a mandatory return value, even though that value is just the same
+ * as the buf arg */
+
+#define V_Gconvert(x,n,t,b) \
+{ \
+    char *rc = Gconvert(x,n,t,b); \
+    PERL_UNUSED_VAR(rc); \
+}
+
+
 #ifdef PERL_UTF8_CACHE_ASSERT
 /* if adding more checks watch out for the following tests:
  *   t/op/index.t t/op/length.t t/op/pat.t t/op/substr.t
@@ -419,7 +428,7 @@ S_visit(pTHX_ SVFUNC_t f, const U32 flags, const U32 mask)
                    && (sv->sv_flags & mask) == flags
                    && SvREFCNT(sv))
            {
-               (FCALL)(aTHX_ sv);
+               (*f)(aTHX_ sv);
                ++visited;
            }
        }
@@ -772,19 +781,19 @@ is "not there", because you'll be overwriting the last members of the
 preceding structure in memory.)
 
 We calculate the correction using the STRUCT_OFFSET macro on the first
-member present. If the allocated structure is smaller (no initial NV
+member present.  If the allocated structure is smaller (no initial NV
 actually allocated) then the net effect is to subtract the size of the NV
 from the pointer, to return a new pointer as if an initial NV were actually
-allocated. (We were using structures named *_allocated for this, but
+allocated.  (We were using structures named *_allocated for this, but
 this turned out to be a subtle bug, because a structure without an NV
 could have a lower alignment constraint, but the compiler is allowed to
 optimised accesses based on the alignment constraint of the actual pointer
 to the full structure, for example, using a single 64 bit load instruction
 because it "knows" that two adjacent 32 bit members will be 8-byte aligned.)
 
-This is the same trick as was used for NV and IV bodies. Ironically it
+This is the same trick as was used for NV and IV bodies.  Ironically it
 doesn't need to be used for NV bodies any more, because NV is now at
-the start of the structure. IV bodies don't need it either, because
+the start of the structure.  IV bodies don't need it either, because
 they are no longer allocated.
 
 In turn, the new_body_* allocators call S_new_body(), which invokes
@@ -1479,13 +1488,6 @@ Perl_sv_grow(pTHX_ SV *const sv, STRLEN newlen)
 
     PERL_ARGS_ASSERT_SV_GROW;
 
-#ifdef HAS_64K_LIMIT
-    if (newlen >= 0x10000) {
-       PerlIO_printf(Perl_debug_log,
-                     "Allocation too large: %"UVxf"\n", (UV)newlen);
-       my_exit(1);
-    }
-#endif /* HAS_64K_LIMIT */
     if (SvROK(sv))
        sv_unref(sv);
     if (SvTYPE(sv) < SVt_PV) {
@@ -1497,10 +1499,6 @@ Perl_sv_grow(pTHX_ SV *const sv, STRLEN newlen)
        s = SvPVX_mutable(sv);
        if (newlen > SvLEN(sv))
            newlen += 10 * (newlen - SvCUR(sv)); /* avoid copy each time */
-#ifdef HAS_64K_LIMIT
-       if (newlen >= 0x10000)
-           newlen = 0xFFFF;
-#endif
     }
     else
     {
@@ -1749,10 +1747,12 @@ S_sv_display(pTHX_ SV *const sv, char *tmpbuf, STRLEN tmpbuf_size) {
          const char * const end = s + SvCUR(sv);
          for ( ; s < end && d < limit; s++ ) {
               int ch = *s & 0xFF;
-              if (ch & 128 && !isPRINT_LC(ch)) {
+              if (! isASCII(ch) && !isPRINT_LC(ch)) {
                    *d++ = 'M';
                    *d++ = '-';
-                   ch &= 127;
+
+                    /* Map to ASCII "equivalent" of Latin1 */
+                   ch = LATIN1_TO_NATIVE(NATIVE_TO_LATIN1(ch) & 127);
               }
               if (ch == '\n') {
                    *d++ = '\\';
@@ -2300,8 +2300,7 @@ Perl_sv_2iv_flags(pTHX_ SV *const sv, const I32 flags)
 {
     dVAR;
 
-    if (!sv)
-       return 0;
+    PERL_ARGS_ASSERT_SV_2IV_FLAGS;
 
     assert (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV
         && SvTYPE(sv) != SVt_PVFM);
@@ -2396,8 +2395,7 @@ Perl_sv_2uv_flags(pTHX_ SV *const sv, const I32 flags)
 {
     dVAR;
 
-    if (!sv)
-       return 0;
+    PERL_ARGS_ASSERT_SV_2UV_FLAGS;
 
     if (SvGMAGICAL(sv) && (flags & SV_GMAGIC))
        mg_get(sv);
@@ -2478,8 +2476,9 @@ NV
 Perl_sv_2nv_flags(pTHX_ SV *const sv, const I32 flags)
 {
     dVAR;
-    if (!sv)
-       return 0.0;
+
+    PERL_ARGS_ASSERT_SV_2NV_FLAGS;
+
     assert (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV
         && SvTYPE(sv) != SVt_PVFM);
     if (SvGMAGICAL(sv) || SvVALID(sv) || isREGEXP(sv)) {
@@ -2782,11 +2781,8 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
     dVAR;
     char *s;
 
-    if (!sv) {
-       if (lp)
-           *lp = 0;
-       return (char *)"";
-    }
+    PERL_ARGS_ASSERT_SV_2PV_FLAGS;
+
     assert (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV
         && SvTYPE(sv) != SVt_PVFM);
     if (SvGMAGICAL(sv) && (flags & SV_GMAGIC))
@@ -2958,7 +2954,7 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
            /* some Xenix systems wipe out errno here */
 
 #ifndef USE_LOCALE_NUMERIC
-            Gconvert(SvNVX(sv), NV_DIG, 0, s);
+            V_Gconvert(SvNVX(sv), NV_DIG, 0, s);
             SvPOK_on(sv);
 #else
             /* Gconvert always uses the current locale.  That's the right thing
@@ -2968,7 +2964,7 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
              * But if we're already in the C locale (PL_numeric_standard is
              * TRUE in that case), no need to do any changing */
             if (PL_numeric_standard || IN_SOME_LOCALE_FORM_RUNTIME) {
-                Gconvert(SvNVX(sv), NV_DIG, 0, s);
+                V_Gconvert(SvNVX(sv), NV_DIG, 0, s);
 
                 /* If the radix character is UTF-8, and actually is in the
                  * output, turn on the UTF-8 flag for the scalar */
@@ -2982,7 +2978,7 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
             else {
                 char *loc = savepv(setlocale(LC_NUMERIC, NULL));
                 setlocale(LC_NUMERIC, "C");
-                Gconvert(SvNVX(sv), NV_DIG, 0, s);
+                V_Gconvert(SvNVX(sv), NV_DIG, 0, s);
                 setlocale(LC_NUMERIC, loc);
                 Safefree(loc);
 
@@ -2996,10 +2992,6 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
            RESTORE_ERRNO;
            while (*s) s++;
        }
-#ifdef hcx
-       if (s[-1] == '.')
-           *--s = '\0';
-#endif
     }
     else if (isGV_with_GP(sv)) {
        GV *const gv = MUTABLE_GV(sv);
@@ -3167,12 +3159,13 @@ contain SV_GMAGIC, then it does an mg_get() first.
 */
 
 bool
-Perl_sv_2bool_flags(pTHX_ SV *const sv, const I32 flags)
+Perl_sv_2bool_flags(pTHX_ SV *sv, I32 flags)
 {
     dVAR;
 
     PERL_ARGS_ASSERT_SV_2BOOL_FLAGS;
 
+    restart:
     if(flags & SV_GMAGIC) SvGETMAGIC(sv);
 
     if (!SvOK(sv))
@@ -3180,8 +3173,30 @@ Perl_sv_2bool_flags(pTHX_ SV *const sv, const I32 flags)
     if (SvROK(sv)) {
        if (SvAMAGIC(sv)) {
            SV * const tmpsv = AMG_CALLunary(sv, bool__amg);
-           if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv))))
-               return cBOOL(SvTRUE(tmpsv));
+           if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv)))) {
+                bool svb;
+                sv = tmpsv;
+                if(SvGMAGICAL(sv)) {
+                    flags = SV_GMAGIC;
+                    goto restart; /* call sv_2bool */
+                }
+                /* expanded SvTRUE_common(sv, (flags = 0, goto restart)) */
+                else if(!SvOK(sv)) {
+                    svb = 0;
+                }
+                else if(SvPOK(sv)) {
+                    svb = SvPVXtrue(sv);
+                }
+                else if((SvFLAGS(sv) & (SVf_IOK|SVf_NOK))) {
+                    svb = (SvIOK(sv) && SvIVX(sv) != 0)
+                        || (SvNOK(sv) && SvNVX(sv) != 0.0);
+                }
+                else {
+                    flags = 0;
+                    goto restart; /* call sv_2bool_nomg */
+                }
+                return cBOOL(svb);
+            }
        }
        return SvRV(sv) != 0;
     }
@@ -3314,7 +3329,7 @@ Perl_sv_utf8_upgrade_flags_grow(pTHX_ SV *const sv, const I32 flags, STRLEN extr
 
        while (t < e) {
            const U8 ch = *t++;
-           if (NATIVE_IS_INVARIANT(ch)) continue;
+           if (NATIVE_BYTE_IS_INVARIANT(ch)) continue;
 
            t--;    /* t already incremented; re-point to first variant */
            two_byte_count = 1;
@@ -3449,7 +3464,7 @@ must_be_utf8:
 
                while (d < e) {
                    const U8 chr = *d++;
-                   if (! NATIVE_IS_INVARIANT(chr)) two_byte_count++;
+                   if (! NATIVE_BYTE_IS_INVARIANT(chr)) two_byte_count++;
                }
 
                /* The string will expand by just the number of bytes that
@@ -3469,13 +3484,13 @@ must_be_utf8:
 
                e--;
                while (e >= t) {
-                   const U8 ch = NATIVE8_TO_UNI(*e--);
-                   if (UNI_IS_INVARIANT(ch)) {
-                       *d-- = UNI_TO_NATIVE(ch);
+                   if (NATIVE_BYTE_IS_INVARIANT(*e)) {
+                       *d-- = *e;
                    } else {
-                       *d-- = (U8)UTF8_EIGHT_BIT_LO(ch);
-                       *d-- = (U8)UTF8_EIGHT_BIT_HI(ch);
+                       *d-- = UTF8_EIGHT_BIT_LO(*e);
+                       *d-- = UTF8_EIGHT_BIT_HI(*e);
                    }
+                    e--;
                }
            }
 
@@ -3654,9 +3669,10 @@ Perl_sv_utf8_decode(pTHX_ 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.
-Loosely speaking, it performs a copy-by-value, obliterating any previous
-content of the destination.
+function if the source SV needs to be reused.  Does not handle 'set' magic on
+destination SV.  Calls 'get' magic on source SV.  Loosely speaking, it
+performs a copy-by-value, obliterating any previous content of the
+destination.
 
 You probably want to use one of the assortment of wrappers, such as
 C<SvSetSV>, C<SvSetSV_nosteal>, C<SvSetMagicSV> and
@@ -3671,7 +3687,7 @@ 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
+parameter has the C<SV_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.
 
@@ -4342,12 +4358,20 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags)
             )
             &&
             !(isSwipe =
+                 (              /* Either ... */
 #ifdef PERL_NEW_COPY_ON_WRITE
                                /* slated for free anyway (and not COW)? */
-                 (sflags & (SVs_TEMP|SVf_IsCOW)) == SVs_TEMP &&
+                    (sflags & (SVs_TEMP|SVf_IsCOW)) == SVs_TEMP
 #else
-                 (sflags & SVs_TEMP) &&   /* slated for free anyway? */
-#endif
+                    (sflags & SVs_TEMP)   /* slated for free anyway? */
+#endif
+                                /* or a swipable TARG */
+                 || ((sflags & (SVs_PADTMP|SVf_READONLY|SVf_IsCOW))
+                       == SVs_PADTMP
+                                /* whose buffer is worth stealing */
+                     && GE_COWBUF_THRESHOLD(cur)
+                    )
+                 ) &&
                  !(sflags & SVf_OOK) &&   /* and not involved in OOK hack? */
                 (!(flags & SV_NOSTEAL)) &&
                                        /* and we're allowed to steal temps */
@@ -5694,12 +5718,10 @@ Perl_sv_add_backref(pTHX_ SV *const tsv, SV *const sv)
     if (SvTYPE(tsv) == SVt_PVHV) {
        svp = (SV**)Perl_hv_backreferences_p(aTHX_ MUTABLE_HV(tsv));
     } else {
-       if (! ((mg =
-           (SvMAGICAL(tsv) ? mg_find(tsv, PERL_MAGIC_backref) : NULL))))
-       {
-           sv_magic(tsv, NULL, PERL_MAGIC_backref, NULL, 0);
-           mg = mg_find(tsv, PERL_MAGIC_backref);
-       }
+        if (SvMAGICAL(tsv))
+            mg = mg_find(tsv, PERL_MAGIC_backref);
+       if (!mg)
+            mg = sv_magicext(tsv, NULL, PERL_MAGIC_backref, &PL_vtbl_backref, NULL, 0);
        svp = &(mg->mg_obj);
     }
 
@@ -5709,32 +5731,32 @@ Perl_sv_add_backref(pTHX_ SV *const tsv, SV *const sv)
        || (*svp && SvTYPE(*svp) != SVt_PVAV)
     ) {
        /* create array */
+       if (mg)
+           mg->mg_flags |= MGf_REFCOUNTED;
        av = newAV();
        AvREAL_off(av);
-       SvREFCNT_inc_simple_void(av);
+       SvREFCNT_inc_simple_void_NN(av);
        /* av now has a refcnt of 2; see discussion above */
+       av_extend(av, *svp ? 2 : 1);
        if (*svp) {
            /* move single existing backref to the array */
-           av_extend(av, 1);
            AvARRAY(av)[++AvFILLp(av)] = *svp; /* av_push() */
        }
        *svp = (SV*)av;
-       if (mg)
-           mg->mg_flags |= MGf_REFCOUNTED;
     }
-    else
+    else {
        av = MUTABLE_AV(*svp);
-
-    if (!av) {
-       /* optimisation: store single backref directly in HvAUX or mg_obj */
-       *svp = sv;
-       return;
+        if (!av) {
+            /* optimisation: store single backref directly in HvAUX or mg_obj */
+            *svp = sv;
+            return;
+        }
+        assert(SvTYPE(av) == SVt_PVAV);
+        if (AvFILLp(av) >= AvMAX(av)) {
+            av_extend(av, AvFILLp(av)+1);
+        }
     }
     /* push new backref */
-    assert(SvTYPE(av) == SVt_PVAV);
-    if (AvFILLp(av) >= AvMAX(av)) {
-        av_extend(av, AvFILLp(av)+1);
-    }
     AvARRAY(av)[++AvFILLp(av)] = sv; /* av_push() */
 }
 
@@ -6295,8 +6317,8 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                    if (PL_stashcache) {
                     DEBUG_o(Perl_deb(aTHX_ "sv_clear clearing PL_stashcache for '%"SVf"'\n",
                                      sv));
-                       (void)hv_delete(PL_stashcache, name,
-                           HvNAMEUTF8((HV*)sv) ? -HvNAMELEN_get((HV*)sv) : HvNAMELEN_get((HV*)sv), G_DISCARD);
+                       (void)hv_deletehek(PL_stashcache,
+                                          HvNAME_HEK((HV*)sv), G_DISCARD);
                     }
                    hv_name_set((HV*)sv, NULL, 0, 0);
                }
@@ -7926,8 +7948,8 @@ 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. If C<append> is not 0, the
-line is appended to the SV instead of overwriting it. C<append> should
+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).
 
@@ -7942,9 +7964,9 @@ Perl_sv_gets(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
     STRLEN rslen;
     STDCHAR rslast;
     STDCHAR *bp;
-    I32 cnt;
-    I32 i = 0;
-    I32 rspara = 0;
+    SSize_t cnt;
+    int i = 0;
+    int rspara = 0;
 
     PERL_ARGS_ASSERT_SV_GETS;
 
@@ -8089,8 +8111,9 @@ Perl_sv_gets(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
     DEBUG_P(PerlIO_printf(Perl_debug_log,
        "Screamer: entering, ptr=%"UVuf", cnt=%ld\n",PTR2UV(ptr),(long)cnt));
     DEBUG_P(PerlIO_printf(Perl_debug_log,
-       "Screamer: entering: PerlIO * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n",
-              PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
+       "Screamer: entering: PerlIO * thinks ptr=%"UVuf", cnt=%zd, base=%"
+        UVuf"\n",
+              PTR2UV(PerlIO_get_ptr(fp)), PerlIO_get_cnt(fp),
               PTR2UV(PerlIO_has_base(fp) ? PerlIO_get_base(fp) : 0)));
     for (;;) {
       screamer:
@@ -8124,13 +8147,13 @@ Perl_sv_gets(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
 
     cannot_be_shortbuffered:
        DEBUG_P(PerlIO_printf(Perl_debug_log,
-                             "Screamer: going to getc, ptr=%"UVuf", cnt=%ld\n",
-                             PTR2UV(ptr),(long)cnt));
+                            "Screamer: going to getc, ptr=%"UVuf", cnt=%zd\n",
+                             PTR2UV(ptr),cnt));
        PerlIO_set_ptrcnt(fp, (STDCHAR*)ptr, cnt); /* deregisterize cnt and ptr */
 
        DEBUG_Pv(PerlIO_printf(Perl_debug_log,
-           "Screamer: pre: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n",
-           PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
+          "Screamer: pre: FILE * thinks ptr=%"UVuf", cnt=%zd, base=%"UVuf"\n",
+           PTR2UV(PerlIO_get_ptr(fp)), PerlIO_get_cnt(fp),
            PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0)));
 
        /* This used to call 'filbuf' in stdio form, but as that behaves like
@@ -8139,14 +8162,15 @@ Perl_sv_gets(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
        i   = PerlIO_getc(fp);          /* get more characters */
 
        DEBUG_Pv(PerlIO_printf(Perl_debug_log,
-           "Screamer: post: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n",
-           PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
+          "Screamer: post: FILE * thinks ptr=%"UVuf", cnt=%zd, base=%"UVuf"\n",
+           PTR2UV(PerlIO_get_ptr(fp)), PerlIO_get_cnt(fp),
            PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0)));
 
        cnt = PerlIO_get_cnt(fp);
        ptr = (STDCHAR*)PerlIO_get_ptr(fp);     /* reregisterize cnt and ptr */
        DEBUG_P(PerlIO_printf(Perl_debug_log,
-           "Screamer: after getc, ptr=%"UVuf", cnt=%ld\n",PTR2UV(ptr),(long)cnt));
+           "Screamer: after getc, ptr=%"UVuf", cnt=%zd\n",
+            PTR2UV(ptr),cnt));
 
        if (i == EOF)                   /* all done for ever? */
            goto thats_really_all_folks;
@@ -8170,11 +8194,12 @@ thats_really_all_folks:
     if (shortbuffered)
        cnt += shortbuffered;
        DEBUG_P(PerlIO_printf(Perl_debug_log,
-           "Screamer: quitting, ptr=%"UVuf", cnt=%ld\n",PTR2UV(ptr),(long)cnt));
+           "Screamer: quitting, ptr=%"UVuf", cnt=%zd\n",PTR2UV(ptr),cnt));
     PerlIO_set_ptrcnt(fp, (STDCHAR*)ptr, cnt); /* put these back or we're in trouble */
     DEBUG_P(PerlIO_printf(Perl_debug_log,
-       "Screamer: end: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n",
-       PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
+       "Screamer: end: FILE * thinks ptr=%"UVuf", cnt=%zd, base=%"UVuf
+       "\n",
+       PTR2UV(PerlIO_get_ptr(fp)), PerlIO_get_cnt(fp),
        PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0)));
     *bp = '\0';
     SvCUR_set(sv, bp - (STDCHAR*)SvPVX_const(sv));     /* set length */
@@ -9617,7 +9642,7 @@ Perl_sv_isa(pTHX_ SV *sv, const char *const name)
 Creates a new SV for the existing RV, C<rv>, to point to.  If C<rv> is not an
 RV then it will be upgraded to one.  If C<classname> is non-null then the new
 SV will be blessed in the specified package.  The new SV is returned and its
-reference count is 1. The reference count 1 is owned by C<rv>.
+reference count is 1.  The reference count 1 is owned by C<rv>.
 
 =cut
 */
@@ -9659,6 +9684,19 @@ Perl_newSVrv(pTHX_ SV *const rv, const char *const classname)
     return sv;
 }
 
+SV *
+Perl_newSVavdefelem(pTHX_ AV *av, SSize_t ix, bool extendible)
+{
+    SV * const lv = newSV_type(SVt_PVLV);
+    PERL_ARGS_ASSERT_NEWSVAVDEFELEM;
+    LvTYPE(lv) = 'y';
+    sv_magic(lv, NULL, PERL_MAGIC_defelem, NULL, 0);
+    LvTARG(lv) = SvREFCNT_inc_simple_NN(av);
+    LvSTARGOFF(lv) = ix;
+    LvTARGLEN(lv) = extendible ? 1 : (STRLEN)UV_MAX;
+    return lv;
+}
+
 /*
 =for apidoc sv_setref_pv
 
@@ -9796,6 +9834,7 @@ Perl_sv_bless(pTHX_ SV *const sv, HV *const stash)
 {
     dVAR;
     SV *tmpRef;
+    HV *oldstash = NULL;
 
     PERL_ARGS_ASSERT_SV_BLESS;
 
@@ -9807,12 +9846,13 @@ Perl_sv_bless(pTHX_ SV *const sv, HV *const stash)
        if (SvREADONLY(tmpRef))
            Perl_croak_no_modify();
        if (SvOBJECT(tmpRef)) {
-           SvREFCNT_dec(SvSTASH(tmpRef));
+           oldstash = SvSTASH(tmpRef);
        }
     }
     SvOBJECT_on(tmpRef);
     SvUPGRADE(tmpRef, SVt_PVMG);
     SvSTASH_set(tmpRef, MUTABLE_HV(SvREFCNT_inc_simple(stash)));
+    SvREFCNT_dec(oldstash);
 
     if(SvSMAGICAL(tmpRef))
         if(mg_find(tmpRef, PERL_MAGIC_ext) || mg_find(tmpRef, PERL_MAGIC_uvar))
@@ -10380,6 +10420,9 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
     char ebuf[IV_DIG * 4 + NV_DIG + 32];
     /* large enough for "%#.#f" --chip */
     /* what about long double NVs? --jhi */
+#ifdef USE_LOCALE_NUMERIC
+    SV* oldlocale = NULL;
+#endif
 
     PERL_ARGS_ASSERT_SV_VCATPVFN_FLAGS;
     PERL_UNUSED_ARG(maybe_tainted);
@@ -10432,7 +10475,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                   a Configure test for this.  */
                if (digits && digits < sizeof(ebuf) - NV_DIG - 10) {
                     /* 0, point, slack */
-                   Gconvert(nv, (int)digits, 0, ebuf);
+                   V_Gconvert(nv, (int)digits, 0, ebuf);
                    sv_catpv_nomg(sv, ebuf);
                    if (*ebuf)  /* May return an empty string for digits==0 */
                        return;
@@ -10785,10 +10828,10 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
            q++;
            break;
 #endif
-#if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE)
+#if IVSIZE >= 8 || defined(HAS_LONG_DOUBLE)
        case 'L':                       /* Ld */
            /*FALLTHROUGH*/
-#ifdef HAS_QUAD
+#if IVSIZE >= 8
        case 'q':                       /* qd */
 #endif
            intsize = 'q';
@@ -10797,7 +10840,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
 #endif
        case 'l':
            ++q;
-#if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE)
+#if IVSIZE >= 8 || defined(HAS_LONG_DOUBLE)
            if (*q == 'l') {    /* lld, llf */
                intsize = 'q';
                ++q;
@@ -10856,7 +10899,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                goto unknown;
            uv = (args) ? va_arg(*args, int) : SvIV(argsv);
            if ((uv > 255 ||
-                (!UNI_IS_INVARIANT(uv) && SvUTF8(sv)))
+                (!UVCHR_IS_INVARIANT(uv) && SvUTF8(sv)))
                && !IN_BYTES) {
                eptr = (char*)utf8buf;
                elen = uvchr_to_utf8((U8*)eptr, uv) - utf8buf;
@@ -10957,7 +11000,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                case 'j':       iv = va_arg(*args, intmax_t); break;
 #endif
                case 'q':
-#ifdef HAS_QUAD
+#if IVSIZE >= 8
                                iv = va_arg(*args, Quad_t); break;
 #else
                                goto unknown;
@@ -10973,7 +11016,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                case 'V':
                default:        iv = tiv; break;
                case 'q':
-#ifdef HAS_QUAD
+#if IVSIZE >= 8
                                iv = (Quad_t)tiv; break;
 #else
                                goto unknown;
@@ -11055,7 +11098,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
 #endif
                default:   uv = va_arg(*args, unsigned); break;
                case 'q':
-#ifdef HAS_QUAD
+#if IVSIZE >= 8
                           uv = va_arg(*args, Uquad_t); break;
 #else
                           goto unknown;
@@ -11071,7 +11114,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                case 'V':
                default:        uv = tuv; break;
                case 'q':
-#ifdef HAS_QUAD
+#if IVSIZE >= 8
                                uv = (Uquad_t)tuv; break;
 #else
                                goto unknown;
@@ -11292,7 +11335,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                /* See earlier comment about buggy Gconvert when digits,
                   aka precis is 0  */
                if ( c == 'g' && precis) {
-                   Gconvert((NV)nv, (int)precis, 0, PL_efloatbuf);
+                   V_Gconvert((NV)nv, (int)precis, 0, PL_efloatbuf);
                    /* May return an empty string for digits==0 */
                    if (*PL_efloatbuf) {
                        elen = strlen(PL_efloatbuf);
@@ -11340,6 +11383,24 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                /* No taint.  Otherwise we are in the strange situation
                 * where printf() taints but print($float) doesn't.
                 * --jhi */
+
+#ifdef USE_LOCALE_NUMERIC
+                if (! PL_numeric_standard && ! IN_SOME_LOCALE_FORM) {
+
+                    /* We use a mortal SV, so that any failures (such as if
+                     * warnings are made fatal) won't leak */
+                    char *oldlocale_string = setlocale(LC_NUMERIC, NULL);
+                    oldlocale = newSVpvn_flags(oldlocale_string,
+                                               strlen(oldlocale_string),
+                                               SVs_TEMP);
+                    PL_numeric_standard = TRUE;
+                    setlocale(LC_NUMERIC, "C");
+                }
+#endif
+
+                /* hopefully the above makes ptr a very constrained format
+                 * that is safe to use, even though it's not literal */
+                GCC_DIAG_IGNORE(-Wformat-nonliteral);
 #if defined(HAS_LONG_DOUBLE)
                elen = ((intsize == 'q')
                        ? my_snprintf(PL_efloatbuf, PL_efloatsize, ptr, nv)
@@ -11347,6 +11408,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
 #else
                elen = my_sprintf(PL_efloatbuf, ptr, nv);
 #endif
+                GCC_DIAG_RESTORE;
            }
        float_converted:
            eptr = PL_efloatbuf;
@@ -11380,7 +11442,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                case 'j':       *(va_arg(*args, intmax_t*)) = i; break;
 #endif
                case 'q':
-#ifdef HAS_QUAD
+#if IVSIZE >= 8
                                *(va_arg(*args, Quad_t*)) = i; break;
 #else
                                goto unknown;
@@ -11515,6 +11577,14 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
        }
     }
     SvTAINT(sv);
+
+#ifdef USE_LOCALE_NUMERIC   /* Done outside loop, so don't have to save/restore
+                               each iteration. */
+    if (oldlocale) {
+        setlocale(LC_NUMERIC, SvPVX(oldlocale));
+        PL_numeric_standard = FALSE;
+    }
+#endif
 }
 
 /* =========================================================================
@@ -11711,6 +11781,7 @@ Perl_dirp_dup(pTHX_ DIR *const dp, CLONE_PARAMS *const param)
     DIR *ret;
 
 #ifdef HAS_FCHDIR
+    int rc = 0;
     DIR *pwd;
     const Direntry_t *dirent;
     char smallbuf[256];
@@ -11747,7 +11818,9 @@ Perl_dirp_dup(pTHX_ DIR *const dp, CLONE_PARAMS *const param)
     /* Now we should have two dir handles pointing to the same dir. */
 
     /* Be nice to the calling code and chdir back to where we were. */
-    fchdir(my_dirfd(pwd)); /* If this fails, then what? */
+    rc = fchdir(my_dirfd(pwd));
+    /* XXX If this fails, then what? */
+    PERL_UNUSED_VAR(rc);
 
     /* We have no need of the pwd handle any more. */
     PerlDir_close(pwd);
@@ -13393,6 +13466,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_last_swash_slen = 0;
 
     PL_srand_called    = proto_perl->Isrand_called;
+    Copy(&(proto_perl->Irandom_state), &PL_random_state, 1, PL_RANDOM_STATE_TYPE);
 
     if (flags & CLONEf_COPY_STACKS) {
        /* next allocation will be PL_tmps_stack[PL_tmps_ix+1] */
@@ -13514,9 +13588,9 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PerlIO_clone(aTHX_ proto_perl, param);
 #endif
 
-    PL_envgv           = gv_dup(proto_perl->Ienvgv, param);
-    PL_incgv           = gv_dup(proto_perl->Iincgv, param);
-    PL_hintgv          = gv_dup(proto_perl->Ihintgv, param);
+    PL_envgv           = gv_dup_inc(proto_perl->Ienvgv, param);
+    PL_incgv           = gv_dup_inc(proto_perl->Iincgv, param);
+    PL_hintgv          = gv_dup_inc(proto_perl->Ihintgv, param);
     PL_origfilename    = SAVEPV(proto_perl->Iorigfilename);
     PL_diehook         = sv_dup_inc(proto_perl->Idiehook, param);
     PL_warnhook                = sv_dup_inc(proto_perl->Iwarnhook, param);
@@ -13558,20 +13632,20 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_stdingv         = gv_dup(proto_perl->Istdingv, param);
     PL_stderrgv                = gv_dup(proto_perl->Istderrgv, param);
     PL_defgv           = gv_dup(proto_perl->Idefgv, param);
-    PL_argvgv          = gv_dup(proto_perl->Iargvgv, param);
+    PL_argvgv          = gv_dup_inc(proto_perl->Iargvgv, param);
     PL_argvoutgv       = gv_dup(proto_perl->Iargvoutgv, param);
     PL_argvout_stack   = av_dup_inc(proto_perl->Iargvout_stack, param);
 
     /* shortcuts to regexp stuff */
-    PL_replgv          = gv_dup(proto_perl->Ireplgv, param);
+    PL_replgv          = gv_dup_inc(proto_perl->Ireplgv, param);
 
     /* shortcuts to misc objects */
     PL_errgv           = gv_dup(proto_perl->Ierrgv, param);
 
     /* shortcuts to debugging objects */
-    PL_DBgv            = gv_dup(proto_perl->IDBgv, param);
-    PL_DBline          = gv_dup(proto_perl->IDBline, param);
-    PL_DBsub           = gv_dup(proto_perl->IDBsub, param);
+    PL_DBgv            = gv_dup_inc(proto_perl->IDBgv, param);
+    PL_DBline          = gv_dup_inc(proto_perl->IDBline, param);
+    PL_DBsub           = gv_dup_inc(proto_perl->IDBsub, param);
     PL_DBsingle                = sv_dup(proto_perl->IDBsingle, param);
     PL_DBtrace         = sv_dup(proto_perl->IDBtrace, param);
     PL_DBsignal                = sv_dup(proto_perl->IDBsignal, param);
@@ -13680,8 +13754,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 #endif /* !USE_LOCALE_NUMERIC */
 
     /* Unicode inversion lists */
-    PL_ASCII           = sv_dup_inc(proto_perl->IASCII, param);
     PL_Latin1          = sv_dup_inc(proto_perl->ILatin1, param);
+    PL_UpperLatin1     = sv_dup_inc(proto_perl->IUpperLatin1, param);
     PL_AboveLatin1     = sv_dup_inc(proto_perl->IAboveLatin1, param);
 
     PL_NonL1NonFinalFold = sv_dup_inc(proto_perl->INonL1NonFinalFold, param);
@@ -13794,8 +13868,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_errors          = sv_dup_inc(proto_perl->Ierrors, param);
 
     PL_sortcop         = (OP*)any_dup(proto_perl->Isortcop, proto_perl);
-    PL_firstgv         = gv_dup(proto_perl->Ifirstgv, param);
-    PL_secondgv                = gv_dup(proto_perl->Isecondgv, param);
+    PL_firstgv         = gv_dup_inc(proto_perl->Ifirstgv, param);
+    PL_secondgv                = gv_dup_inc(proto_perl->Isecondgv, param);
 
     PL_stashcache       = newHV();
 
@@ -14019,13 +14093,19 @@ Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding)
        STRLEN len;
        const char *s;
        dSP;
+       SV *nsv = sv;
        ENTER;
+       PUSHSTACK;
        SAVETMPS;
+       if (SvPADTMP(nsv)) {
+           nsv = sv_newmortal();
+           SvSetSV_nosteal(nsv, sv);
+       }
        save_re_context();
        PUSHMARK(sp);
        EXTEND(SP, 3);
        PUSHs(encoding);
-       PUSHs(sv);
+       PUSHs(nsv);
 /*
   NI-S 2002/07/09
   Passing sv_yes is wrong - it needs to be or'ed set of constants
@@ -14048,6 +14128,7 @@ Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding)
            SvCUR_set(sv, len);
        }
        FREETMPS;
+       POPSTACK;
        LEAVE;
        if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
            /* clear pos and any utf8 cache */
@@ -14746,14 +14827,21 @@ Perl_report_uninit(pTHX_ const SV *uninit_sv)
            if (varname)
                sv_insert(varname, 0, 0, " ", 1);
        }
+        /* PL_warn_uninit_sv is constant */
+        GCC_DIAG_IGNORE(-Wformat-nonliteral);
        /* 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));
+        GCC_DIAG_RESTORE;
     }
-    else
+    else {
+        /* PL_warn_uninit is constant */
+        GCC_DIAG_IGNORE(-Wformat-nonliteral);
        Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED), PL_warn_uninit,
                    "", "", "");
+        GCC_DIAG_RESTORE;
+    }
 }
 
 /*