This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
In sv.c, remove comments with structure sizes from bodies_by_type[].
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index fe096ba..557db93 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -582,9 +582,7 @@ Perl_sv_clean_objs(pTHX)
     visit(do_clean_named_io_objs, SVt_PVGV|SVpgv_GP, SVTYPEMASK|SVp_POK|SVpgv_GP);
     /* And if there are some very tenacious barnacles clinging to arrays,
        closures, or what have you.... */
-    /* XXX This line breaks Tk and Gtk2. See [perl #82542].
     visit(do_curse, SVs_OBJECT, SVs_OBJECT);
-    */
     olddef = PL_defoutgv;
     PL_defoutgv = NULL; /* disable skip of PL_defoutgv */
     if (olddef && isGV_with_GP(olddef))
@@ -895,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,
@@ -933,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)) },
 
@@ -953,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,
@@ -966,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,
@@ -1578,6 +1566,7 @@ Perl_sv_setiv(pTHX_ register SV *const sv, const IV i)
     case SVt_PVCV:
     case SVt_PVFM:
     case SVt_PVIO:
+       /* diag_listed_as: Can't coerce %s to %s in %s */
        Perl_croak(aTHX_ "Can't coerce %s to integer in %s", sv_reftype(sv,0),
                   OP_DESC(PL_op));
     default: NOOP;
@@ -1687,6 +1676,7 @@ Perl_sv_setnv(pTHX_ register SV *const sv, const NV num)
     case SVt_PVCV:
     case SVt_PVFM:
     case SVt_PVIO:
+       /* diag_listed_as: Can't coerce %s to %s in %s */
        Perl_croak(aTHX_ "Can't coerce %s to number in %s", sv_reftype(sv,0),
                   OP_DESC(PL_op));
     default: NOOP;
@@ -2267,11 +2257,13 @@ Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags)
     dVAR;
     if (!sv)
        return 0;
-    if (SvGMAGICAL(sv) || (SvTYPE(sv) == SVt_PVGV && SvVALID(sv))) {
-       /* FBMs use the same flag bit as SVf_IVisUV, so must let them
-          cache IVs just in case. In practice it seems that they never
-          actually anywhere accessible by user Perl code, let alone get used
-          in anything other than a string context.  */
+    if (SvGMAGICAL(sv) || 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))
@@ -2354,9 +2346,9 @@ Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags)
     dVAR;
     if (!sv)
        return 0;
-    if (SvGMAGICAL(sv) || (SvTYPE(sv) == SVt_PVGV && SvVALID(sv))) {
-       /* FBMs use the same flag bit as SVf_IVisUV, so must let them
-          cache IVs just in case.  */
+    if (SvGMAGICAL(sv) || 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))
@@ -2434,9 +2426,9 @@ Perl_sv_2nv_flags(pTHX_ register SV *const sv, const I32 flags)
     dVAR;
     if (!sv)
        return 0.0;
-    if (SvGMAGICAL(sv) || (SvTYPE(sv) == SVt_PVGV && SvVALID(sv))) {
-       /* FBMs use the same flag bit as SVf_IVisUV, so must let them
-          cache IVs just in case.  */
+    if (SvGMAGICAL(sv) || 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 NVs.  */
        if (flags & SV_GMAGIC)
            mg_get(sv);
        if (SvNOKp(sv))
@@ -3221,7 +3213,7 @@ Perl_sv_utf8_upgrade_flags_grow(pTHX_ register SV *const sv, const I32 flags, ST
                return len;
            }
        } else {
-           (void) SvPV_force(sv,len);
+           (void) SvPV_force_flags(sv,len,flags & SV_GMAGIC);
        }
     }
 
@@ -3429,6 +3421,29 @@ must_be_utf8:
                    }
                }
            }
+
+           if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
+               /* Update pos. We do it at the end rather than during
+                * the upgrade, to avoid slowing down the common case
+                * (upgrade without pos) */
+               MAGIC * mg = mg_find(sv, PERL_MAGIC_regex_global);
+               if (mg) {
+                   I32 pos = mg->mg_len;
+                   if (pos > 0 && (U32)pos > invariant_head) {
+                       U8 *d = (U8*) SvPVX(sv) + invariant_head;
+                       STRLEN n = (U32)pos - invariant_head;
+                       while (n > 0) {
+                           if (UTF8_IS_START(*d))
+                               d++;
+                           d++;
+                           n--;
+                       }
+                       mg->mg_len  = d - (U8*)SvPVX(sv);
+                   }
+               }
+               if ((mg = mg_find(sv, PERL_MAGIC_utf8)))
+                   magic_setutf8(sv,mg); /* clear UTF8 cache */
+           }
        }
     }
 
@@ -3463,11 +3478,28 @@ Perl_sv_utf8_downgrade(pTHX_ register SV *const sv, const bool fail_ok)
         if (SvCUR(sv)) {
            U8 *s;
            STRLEN len;
+           int mg_flags = SV_GMAGIC;
 
             if (SvIsCOW(sv)) {
                 sv_force_normal_flags(sv, 0);
             }
-           s = (U8 *) SvPV(sv, len);
+           if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
+               /* update pos */
+               MAGIC * mg = mg_find(sv, PERL_MAGIC_regex_global);
+               if (mg) {
+                   I32 pos = mg->mg_len;
+                   if (pos > 0) {
+                       sv_pos_b2u(sv, &pos);
+                       mg_flags = 0; /* sv_pos_b2u does get magic */
+                       mg->mg_len  = pos;
+                   }
+               }
+               if ((mg = mg_find(sv, PERL_MAGIC_utf8)))
+                   magic_setutf8(sv,mg); /* clear UTF8 cache */
+
+           }
+           s = (U8 *) SvPV_flags(sv, len, mg_flags);
+
            if (!utf8_to_bytes(s, &len)) {
                if (fail_ok)
                    return FALSE;
@@ -3516,7 +3548,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
-characters, the C<SvUTF8> flag stays being off.
+characters, the C<SvUTF8> flag stays off.
 Scans PV for validity and returns false if the PV is invalid UTF-8.
 
 =cut
@@ -3528,7 +3560,7 @@ Perl_sv_utf8_decode(pTHX_ register SV *const sv)
     PERL_ARGS_ASSERT_SV_UTF8_DECODE;
 
     if (SvPOKp(sv)) {
-        const U8 *c;
+        const U8 *start, *c;
         const U8 *e;
 
        /* The octets may have got themselves encoded - get them back as
@@ -3540,7 +3572,7 @@ Perl_sv_utf8_decode(pTHX_ register SV *const sv)
         /* it is actually just a matter of turning the utf8 flag on, but
          * we want to make sure everything inside is valid utf8 first.
          */
-        c = (const U8 *) SvPVX_const(sv);
+        c = start = (const U8 *) SvPVX_const(sv);
        if (!is_utf8_string(c, SvCUR(sv)+1))
            return FALSE;
         e = (const U8 *) SvEND(sv);
@@ -3551,6 +3583,22 @@ Perl_sv_utf8_decode(pTHX_ register SV *const sv)
                break;
            }
         }
+       if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
+           /* adjust pos to the start of a UTF8 char sequence */
+           MAGIC * mg = mg_find(sv, PERL_MAGIC_regex_global);
+           if (mg) {
+               I32 pos = mg->mg_len;
+               if (pos > 0) {
+                   for (c = start + pos; c > start; c--) {
+                       if (UTF8_IS_START(*c))
+                           break;
+                   }
+                   mg->mg_len  = c - start;
+               }
+           }
+           if ((mg = mg_find(sv, PERL_MAGIC_utf8)))
+               magic_setutf8(sv,mg); /* clear UTF8 cache */
+       }
     }
     return TRUE;
 }
@@ -3659,7 +3707,8 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
             mro_changes = 2;
         else {
             const STRLEN len = GvNAMELEN(dstr);
-            if (len > 1 && name[len-2] == ':' && name[len-1] == ':') {
+            if ((len > 1 && name[len-2] == ':' && name[len-1] == ':')
+             || (len == 1 && name[0] == ':')) {
                 mro_changes = 3;
 
                 /* Set aside the old stash, so we can reset isa caches on
@@ -3819,7 +3868,10 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
            const char * const name = GvNAME((GV*)dstr);
            const STRLEN len = GvNAMELEN(dstr);
            if (
-               len > 1 && name[len-2] == ':' && name[len-1] == ':'
+               (
+                  (len > 1 && name[len-2] == ':' && name[len-1] == ':')
+               || (len == 1 && name[0] == ':')
+               )
             && (!dref || HvENAME_get(dref))
            ) {
                mro_package_moved(
@@ -4026,8 +4078,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
        /* case SVt_BIND: */
     case SVt_PVLV:
     case SVt_PVGV:
-       /* SvVALID means that this PVGV is playing at being an FBM.  */
-
     case SVt_PVMG:
        if (SvGMAGICAL(sstr) && (flags & SV_GMAGIC)) {
            mg_get(sstr);
@@ -4117,7 +4167,8 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
                const STRLEN len = GvNAMELEN(dstr);
                HV *old_stash = NULL;
                bool reset_isa = FALSE;
-               if (len > 1 && name[len-2] == ':' && name[len-1] == ':') {
+               if ((len > 1 && name[len-2] == ':' && name[len-1] == ':')
+                || (len == 1 && name[0] == ':')) {
                    /* Set aside the old stash, so we can reset isa caches
                       on its subclasses. */
                    if((old_stash = GvHV(dstr))) {
@@ -4657,7 +4708,7 @@ we do the copy, and is also used locally. 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 unrefing. C<sv_force_normal> calls this function
+C<sv_unref_flags()> when unreffing. C<sv_force_normal> calls this function
 with flags set to 0.
 
 =cut
@@ -5044,7 +5095,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
@@ -5178,9 +5229,25 @@ 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);
@@ -5192,11 +5259,7 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how,
            !(SvFAKE(sv) && SvTYPE(sv) < SVt_PVMG)
 
            && 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);
@@ -5218,127 +5281,6 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how,
        }
     }
 
-    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;
-    case PERL_MAGIC_sig:
-       vtable = &PL_vtbl_sig;
-       break;
-    case PERL_MAGIC_sigelem:
-       vtable = &PL_vtbl_sigelem;
-       break;
-    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_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);
 
@@ -5353,7 +5295,7 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how,
     }
 }
 
-int
+static int
 S_sv_unmagicext_flags(pTHX_ SV *const sv, const int type, MGVTBL *vtbl, const U32 flags)
 {
     MAGIC* mg;
@@ -5467,16 +5409,13 @@ Perl_sv_rvweaken(pTHX_ SV *const sv)
  * store it directly in the HvAUX or mg_obj slot, avoiding the need to
  * allocate an AV. (Whether the slot holds an AV tells us whether this is
  * active.)
- *
- * If an HV's backref is stored in magic, it is moved back to HvAUX.
  */
 
 /* A discussion about the backreferences array and its refcount:
  *
  * The AV holding the backreferences is pointed to either as the mg_obj of
- * PERL_MAGIC_backref, or in the specific case of a HV that has the hv_aux
- * structure, from the xhv_backreferences field. (A HV without hv_aux will
- * have the standard magic instead.) The array is created with a refcount
+ * PERL_MAGIC_backref, or in the specific case of a HV, from the
+ * xhv_backreferences field. The array is created with a refcount
  * of 2. This means that if during global destruction the array gets
  * picked on before its parent to have its refcount decremented by the
  * random zapper, it won't actually be freed, meaning it's still there for
@@ -5504,21 +5443,6 @@ 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));
-
-       if (!*svp) {
-           if ((mg = mg_find(tsv, PERL_MAGIC_backref))) {
-               /* Aha. They've got it stowed in magic instead.
-                * Move it back to xhv_backreferences */
-               *svp = mg->mg_obj;
-               /* Stop mg_free decreasing the reference count.  */
-               mg->mg_obj = NULL;
-               /* Stop mg_free even calling the destructor, given that
-                  there's no AV to free up.  */
-               mg->mg_virtual = 0;
-               sv_unmagic(tsv, PERL_MAGIC_backref);
-               mg = NULL;
-           }
-       }
     } else {
        if (! ((mg =
            (SvMAGICAL(tsv) ? mg_find(tsv, PERL_MAGIC_backref) : NULL))))
@@ -5576,10 +5500,11 @@ Perl_sv_del_backref(pTHX_ SV *const tsv, SV *const sv)
 
     PERL_ARGS_ASSERT_SV_DEL_BACKREF;
 
-    if (SvTYPE(tsv) == SVt_PVHV && SvOOK(tsv)) {
-       svp = (SV**)Perl_hv_backreferences_p(aTHX_ MUTABLE_HV(tsv));
+    if (SvTYPE(tsv) == SVt_PVHV) {
+       if (SvOOK(tsv))
+           svp = (SV**)Perl_hv_backreferences_p(aTHX_ MUTABLE_HV(tsv));
     }
-    if (!svp || !*svp) {
+    else {
        MAGIC *const mg
            = SvMAGICAL(tsv) ? mg_find(tsv, PERL_MAGIC_backref) : NULL;
        svp =  mg ? &(mg->mg_obj) : NULL;
@@ -5659,6 +5584,17 @@ 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
+     * 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)) {
+       if (PL_in_clean_all) /* All is fair */
+           return;
+       Perl_croak(aTHX_
+                  "panic: magic_killbackrefs (freed backref AV/SV)");
+    }
+
+
     is_array = (SvTYPE(av) == SVt_PVAV);
     if (is_array) {
        assert(!SvIS_FREED(av));
@@ -5931,7 +5867,8 @@ S_anonymise_cv_maybe(pTHX_ GV *gv, CV* cv)
     }
 
     /* if not, anonymise: */
-    stash  = GvSTASH(gv) ? HvNAME(GvSTASH(gv)) : NULL;
+    stash  = GvSTASH(gv) && HvNAME(GvSTASH(gv))
+              ? HvENAME(GvSTASH(gv)) : NULL;
     gvname = Perl_newSVpvf(aTHX_ "%s::__ANON__",
                                        stash ? stash : "__ANON__");
     anongv = gv_fetchsv(gvname, GV_ADDMULTI, SVt_PVCV);
@@ -5967,6 +5904,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
     SV* iter_sv = NULL;
     SV* next_sv = NULL;
     register SV *sv = orig_sv;
+    STRLEN hash_index;
 
     PERL_ARGS_ASSERT_SV_CLEAR;
 
@@ -5992,14 +5930,27 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
            goto free_head;
        }
 
-       if (SvOBJECT(sv)) {
-           if (!curse(sv, 1)) goto get_next_sv;
-       }
+       assert(!SvOBJECT(sv) || type >= SVt_PVMG); /* objs are always >= MG */
+
        if (type >= SVt_PVMG) {
-           if (type == SVt_PVMG && SvPAD_OUR(sv)) {
+           if (SvOBJECT(sv)) {
+               if (!curse(sv, 1)) goto get_next_sv;
+               type = SvTYPE(sv); /* destructor may have changed it */
+           }
+           /* Free back-references before magic, in case the magic calls
+            * Perl code that has weak references to sv. */
+           if (type == SVt_PVHV) {
+               Perl_hv_kill_backrefs(aTHX_ MUTABLE_HV(sv));
+               if (SvMAGIC(sv))
+                   mg_free(sv);
+           }
+           else if (type == SVt_PVMG && SvPAD_OUR(sv)) {
                SvREFCNT_dec(SvOURSTASH(sv));
-           } else if (SvMAGIC(sv))
+           } else if (SvMAGIC(sv)) {
+               /* Free back-references before other types of magic. */
+               sv_unmagic(sv, PERL_MAGIC_backref);
                mg_free(sv);
+           }
            if (type == SVt_PVMG && SvPAD_TYPED(sv))
                SvREFCNT_dec(SvSTASH(sv));
        }
@@ -6038,8 +5989,38 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
            if (PL_last_swash_hv == (const HV *)sv) {
                PL_last_swash_hv = NULL;
            }
-           Perl_hv_kill_backrefs(aTHX_ MUTABLE_HV(sv));
+           if (HvTOTALKEYS((HV*)sv) > 0) {
+               const char *name;
+               /* this statement should match the one at the beginning of
+                * hv_undef_flags() */
+               if (   PL_phase != PERL_PHASE_DESTRUCT
+                   && (name = HvNAME((HV*)sv)))
+               {
+                   if (PL_stashcache)
+                       (void)hv_delete(PL_stashcache, name,
+                           HvNAMELEN_get((HV*)sv), G_DISCARD);
+                   hv_name_set((HV*)sv, NULL, 0, 0);
+               }
+
+               /* save old iter_sv in unused SvSTASH field */
+               assert(!SvOBJECT(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. */
+               hash_index = 0;
+               next_sv = Perl_hfree_next_entry(aTHX_ (HV*)sv, &hash_index);
+               goto get_next_sv; /* process this new sv */
+           }
+           /* free empty hash */
            Perl_hv_undef_flags(aTHX_ MUTABLE_HV(sv), HV_NAME_SETALL);
+           assert(!HvARRAY((HV*)sv));
            break;
        case SVt_PVAV:
            {
@@ -6188,6 +6169,25 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                    Safefree(AvALLOC(av));
                    goto free_body;
                }
+           } else if (SvTYPE(iter_sv) == SVt_PVHV) {
+               sv = Perl_hfree_next_entry(aTHX_ (HV*)iter_sv, &hash_index);
+               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 */
+                   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;
+
+                   /* free any remaining detritus from the hash struct */
+                   Perl_hv_undef_flags(aTHX_ MUTABLE_HV(sv), HV_NAME_SETALL);
+                   assert(!HvARRAY((HV*)sv));
+                   goto free_body;
+               }
            }
 
            /* unrolled SvREFCNT_dec and sv_free2 follows: */
@@ -8987,6 +8987,7 @@ Perl_sv_pvn_force_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
        }
        if ((SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM)
            || isGV_with_GP(sv))
+           /* 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);
@@ -10180,59 +10181,28 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            width = expect_number(&q);
        }
 
-       if (vectorize) {
-           if (vectorarg) {
-               if (args)
-                   vecsv = va_arg(*args, SV*);
-               else if (evix) {
-                   vecsv = (evix > 0 && evix <= svmax)
-                       ? svargs[evix-1] : S_vcatpvfn_missing_argument(aTHX);
-               } else {
-                   vecsv = svix < svmax
-                       ? svargs[svix++] : S_vcatpvfn_missing_argument(aTHX);
-               }
-               dotstr = SvPV_const(vecsv, dotstrlen);
-               /* Keep the DO_UTF8 test *after* the SvPV call, else things go
-                  bad with tied or overloaded values that return UTF8.  */
-               if (DO_UTF8(vecsv))
-                   is_utf8 = TRUE;
-               else if (has_utf8) {
-                   vecsv = sv_mortalcopy(vecsv);
-                   sv_utf8_upgrade(vecsv);
-                   dotstr = SvPV_const(vecsv, dotstrlen);
-                   is_utf8 = TRUE;
-               }                   
-           }
-           if (args) {
-               VECTORIZE_ARGS
-           }
-           else if (efix ? (efix > 0 && efix <= svmax) : svix < svmax) {
-               vecsv = svargs[efix ? efix-1 : svix++];
-               vecstr = (U8*)SvPV_const(vecsv,veclen);
-               vec_utf8 = DO_UTF8(vecsv);
-
-               /* if this is a version object, we need to convert
-                * back into v-string notation and then let the
-                * vectorize happen normally
-                */
-               if (sv_derived_from(vecsv, "version")) {
-                   char *version = savesvpv(vecsv);
-                   if ( hv_exists(MUTABLE_HV(SvRV(vecsv)), "alpha", 5 ) ) {
-                       Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
-                       "vector argument not supported with alpha versions");
-                       goto unknown;
-                   }
-                   vecsv = sv_newmortal();
-                   scan_vstring(version, version + veclen, vecsv);
-                   vecstr = (U8*)SvPV_const(vecsv, veclen);
-                   vec_utf8 = DO_UTF8(vecsv);
-                   Safefree(version);
-               }
-           }
-           else {
-               vecstr = (U8*)"";
-               veclen = 0;
+       if (vectorize && vectorarg) {
+           /* vectorizing, but not with the default "." */
+           if (args)
+               vecsv = va_arg(*args, SV*);
+           else if (evix) {
+               vecsv = (evix > 0 && evix <= svmax)
+                   ? svargs[evix-1] : S_vcatpvfn_missing_argument(aTHX);
+           } else {
+               vecsv = svix < svmax
+                   ? svargs[svix++] : S_vcatpvfn_missing_argument(aTHX);
            }
+           dotstr = SvPV_const(vecsv, dotstrlen);
+           /* Keep the DO_UTF8 test *after* the SvPV call, else things go
+              bad with tied or overloaded values that return UTF8.  */
+           if (DO_UTF8(vecsv))
+               is_utf8 = TRUE;
+           else if (has_utf8) {
+               vecsv = sv_mortalcopy(vecsv);
+               sv_utf8_upgrade(vecsv);
+               dotstr = SvPV_const(vecsv, dotstrlen);
+               is_utf8 = TRUE;
+           }               
        }
 
        if (asterisk) {
@@ -10273,6 +10243,39 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            }
        }
 
+       if (vectorize) {
+           if (args) {
+               VECTORIZE_ARGS
+           }
+           else if (efix ? (efix > 0 && efix <= svmax) : svix < svmax) {
+               vecsv = svargs[efix ? efix-1 : svix++];
+               vecstr = (U8*)SvPV_const(vecsv,veclen);
+               vec_utf8 = DO_UTF8(vecsv);
+
+               /* if this is a version object, we need to convert
+                * back into v-string notation and then let the
+                * vectorize happen normally
+                */
+               if (sv_derived_from(vecsv, "version")) {
+                   char *version = savesvpv(vecsv);
+                   if ( hv_exists(MUTABLE_HV(SvRV(vecsv)), "alpha", 5 ) ) {
+                       Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
+                       "vector argument not supported with alpha versions");
+                       goto unknown;
+                   }
+                   vecsv = sv_newmortal();
+                   scan_vstring(version, version + veclen, vecsv);
+                   vecstr = (U8*)SvPV_const(vecsv, veclen);
+                   vec_utf8 = DO_UTF8(vecsv);
+                   Safefree(version);
+               }
+           }
+           else {
+               vecstr = (U8*)"";
+               veclen = 0;
+           }
+       }
+
        /* SIZE */
 
        switch (*q) {
@@ -10306,8 +10309,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            break;
 #endif
        case 'l':
+           ++q;
 #if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE)
-           if (*++q == 'l') {  /* lld, llf */
+           if (*q == 'l') {    /* lld, llf */
                intsize = 'q';
                ++q;
            }
@@ -12698,6 +12702,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PoisonNew(my_perl, 1, PerlInterpreter);
     PL_op = NULL;
     PL_curcop = NULL;
+    PL_defstash = NULL; /* may be used by perl malloc() */
     PL_markstack = 0;
     PL_scopestack = 0;
     PL_scopestack_name = 0;
@@ -12751,67 +12756,23 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_hash_seed       = proto_perl->Ihash_seed;
     PL_rehash_seed     = proto_perl->Irehash_seed;
 
-#ifdef USE_REENTRANT_API
-    /* XXX: things like -Dm will segfault here in perlio, but doing
-     *  PERL_SET_CONTEXT(proto_perl);
-     * breaks too many other things
-     */
-    Perl_reentrant_init(aTHX);
-#endif
-
-    /* create SV map for pointer relocation */
-    PL_ptr_table = ptr_table_new();
-
-    /* initialize these special pointers as early as possible */
     SvANY(&PL_sv_undef)                = NULL;
     SvREFCNT(&PL_sv_undef)     = (~(U32)0)/2;
     SvFLAGS(&PL_sv_undef)      = SVf_READONLY|SVt_NULL;
-    ptr_table_store(PL_ptr_table, &proto_perl->Isv_undef, &PL_sv_undef);
-
-    SvANY(&PL_sv_no)           = new_XPVNV();
     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;
-    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);
 
     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;
-    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);
 
     /* dbargs array probably holds garbage */
     PL_dbargs          = NULL;
 
-    /* create (a non-shared!) shared string table */
-    PL_strtab          = newHV();
-    HvSHAREKEYS_off(PL_strtab);
-    hv_ksplit(PL_strtab, HvTOTALKEYS(proto_perl->Istrtab));
-    ptr_table_store(PL_ptr_table, proto_perl->Istrtab, PL_strtab);
-
     PL_compiling = proto_perl->Icompiling;
 
-    /* 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);
-
-    PL_compiling.cop_file    = savesharedpv(PL_compiling.cop_file);
-    ptr_table_store(PL_ptr_table, proto_perl->Icompiling.cop_file, PL_compiling.cop_file);
-
-    ptr_table_store(PL_ptr_table, &proto_perl->Icompiling, &PL_compiling);
-    PL_compiling.cop_warnings = DUP_WARNINGS(PL_compiling.cop_warnings);
-    CopHINTHASH_set(&PL_compiling, cophh_copy(CopHINTHASH_get(&PL_compiling)));
-    PL_curcop          = (COP*)any_dup(proto_perl->Icurcop, proto_perl);
 #ifdef PERL_DEBUG_READONLY_OPS
     PL_slabs = NULL;
     PL_slab_count = 0;
@@ -12821,39 +12782,12 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_origargc                = proto_perl->Iorigargc;
     PL_origargv                = proto_perl->Iorigargv;
 
-    param->stashes      = newAV();  /* Setup array of objects to call clone on */
-    /* This makes no difference to the implementation, as it always pushes
-       and shifts pointers to other SVs without changing their reference
-       count, with the array becoming empty before it is freed. However, it
-       makes it conceptually clear what is going on, and will avoid some
-       work inside av.c, filling slots between AvFILL() and AvMAX() with
-       &PL_sv_undef, and SvREFCNT_dec()ing those.  */
-    AvREAL_off(param->stashes);
-
-    if (!(flags & CLONEf_COPY_STACKS)) {
-       param->unreferenced = newAV();
-    }
-
     /* Set tainting stuff before PerlIO_debug can possibly get called */
     PL_tainting                = proto_perl->Itainting;
     PL_taint_warn      = proto_perl->Itaint_warn;
 
-#ifdef PERLIO_LAYERS
-    /* Clone PerlIO tables as soon as we can handle general xx_dup() */
-    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_origfilename    = SAVEPV(proto_perl->Iorigfilename);
-    PL_diehook         = sv_dup_inc(proto_perl->Idiehook, param);
-    PL_warnhook                = sv_dup_inc(proto_perl->Iwarnhook, param);
-
-    /* switches */
     PL_minus_c         = proto_perl->Iminus_c;
-    PL_patchlevel      = sv_dup_inc(proto_perl->Ipatchlevel, param);
-    PL_apiversion      = sv_dup_inc(proto_perl->Iapiversion, param);
+
     PL_localpatches    = proto_perl->Ilocalpatches;
     PL_splitstr                = proto_perl->Isplitstr;
     PL_minus_n         = proto_perl->Iminus_n;
@@ -12866,16 +12800,12 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_dowarn          = proto_perl->Idowarn;
     PL_sawampersand    = proto_perl->Isawampersand;
     PL_unsafe          = proto_perl->Iunsafe;
-    PL_inplace         = SAVEPV(proto_perl->Iinplace);
-    PL_e_script                = sv_dup_inc(proto_perl->Ie_script, param);
     PL_perldb          = proto_perl->Iperldb;
     PL_perl_destruct_level = proto_perl->Iperl_destruct_level;
     PL_exit_flags       = proto_perl->Iexit_flags;
 
-    /* magical thingies */
     /* XXX time(&PL_basetime) when asked for? */
     PL_basetime                = proto_perl->Ibasetime;
-    PL_formfeed                = sv_dup(proto_perl->Iformfeed, param);
 
     PL_maxsysfd                = proto_perl->Imaxsysfd;
     PL_statusvalue     = proto_perl->Istatusvalue;
@@ -12884,27 +12814,283 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 #else
     PL_statusvalue_posix = proto_perl->Istatusvalue_posix;
 #endif
-    PL_encoding                = sv_dup(proto_perl->Iencoding, param);
-
-    sv_setpvs(PERL_DEBUG_PAD(0), "");  /* For regex debugging. */
-    sv_setpvs(PERL_DEBUG_PAD(1), "");  /* ext/re needs these */
-    sv_setpvs(PERL_DEBUG_PAD(2), "");  /* even without DEBUGGING. */
 
-   
     /* RE engine related */
     Zero(&PL_reg_state, 1, struct re_save_state);
     PL_reginterp_cnt   = 0;
     PL_regmatch_slab   = NULL;
-    
-    /* Clone the regex array */
-    /* ORANGE FIXME for plugins, probably in the SV dup code.
-       newSViv(PTR2IV(CALLREGDUPE(
-       INT2PTR(REGEXP *, SvIVX(regex)), param))))
-    */
-    PL_regex_padav = av_dup_inc(proto_perl->Iregex_padav, param);
-    PL_regex_pad = AvARRAY(PL_regex_padav);
 
-    /* shortcuts to various I/O objects */
+    PL_sub_generation  = proto_perl->Isub_generation;
+
+    /* funky return mechanisms */
+    PL_forkprocess     = proto_perl->Iforkprocess;
+
+    /* internal state */
+    PL_maxo            = proto_perl->Imaxo;
+
+    PL_main_start      = proto_perl->Imain_start;
+    PL_eval_root       = proto_perl->Ieval_root;
+    PL_eval_start      = proto_perl->Ieval_start;
+
+    PL_filemode                = proto_perl->Ifilemode;
+    PL_lastfd          = proto_perl->Ilastfd;
+    PL_oldname         = proto_perl->Ioldname;         /* XXX not quite right */
+    PL_Argv            = NULL;
+    PL_Cmd             = NULL;
+    PL_gensym          = proto_perl->Igensym;
+
+    PL_laststatval     = proto_perl->Ilaststatval;
+    PL_laststype       = proto_perl->Ilaststype;
+    PL_mess_sv         = NULL;
+
+    PL_profiledata     = NULL;
+
+    PL_generation      = proto_perl->Igeneration;
+
+    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_nomemok         = proto_perl->Inomemok;
+    PL_an              = proto_perl->Ian;
+    PL_evalseq         = proto_perl->Ievalseq;
+    PL_origenviron     = proto_perl->Iorigenviron;     /* XXX not quite right */
+    PL_origalen                = proto_perl->Iorigalen;
+
+    PL_sighandlerp     = proto_perl->Isighandlerp;
+
+    PL_runops          = proto_perl->Irunops;
+
+    PL_subline         = proto_perl->Isubline;
+
+#ifdef FCRYPT
+    PL_cryptseen       = proto_perl->Icryptseen;
+#endif
+
+    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;
+    PL_collxfrm_base   = proto_perl->Icollxfrm_base;
+    PL_collxfrm_mult   = proto_perl->Icollxfrm_mult;
+#endif /* USE_LOCALE_COLLATE */
+
+#ifdef USE_LOCALE_NUMERIC
+    PL_numeric_standard        = proto_perl->Inumeric_standard;
+    PL_numeric_local   = proto_perl->Inumeric_local;
+#endif /* !USE_LOCALE_NUMERIC */
+
+    /* Did the locale setup indicate UTF-8? */
+    PL_utf8locale      = proto_perl->Iutf8locale;
+    /* Unicode features (see perlrun/-C) */
+    PL_unicode         = proto_perl->Iunicode;
+
+    /* Pre-5.8 signals control */
+    PL_signals         = proto_perl->Isignals;
+
+    /* times() ticks per second */
+    PL_clocktick       = proto_perl->Iclocktick;
+
+    /* Recursion stopper for PerlIO_find_layer */
+    PL_in_load_module  = proto_perl->Iin_load_module;
+
+    /* sort() routine */
+    PL_sort_RealCmp    = proto_perl->Isort_RealCmp;
+
+    /* Not really needed/useful since the reenrant_retint is "volatile",
+     * but do it for consistency's sake. */
+    PL_reentrant_retint        = proto_perl->Ireentrant_retint;
+
+    /* Hooks to shared SVs and locks. */
+    PL_sharehook       = proto_perl->Isharehook;
+    PL_lockhook                = proto_perl->Ilockhook;
+    PL_unlockhook      = proto_perl->Iunlockhook;
+    PL_threadhook      = proto_perl->Ithreadhook;
+    PL_destroyhook     = proto_perl->Idestroyhook;
+    PL_signalhook      = proto_perl->Isignalhook;
+
+#ifdef THREADS_HAVE_PIDS
+    PL_ppid            = proto_perl->Ippid;
+#endif
+
+    /* swatch cache */
+    PL_last_swash_hv   = NULL; /* reinits on demand */
+    PL_last_swash_klen = 0;
+    PL_last_swash_key[0]= '\0';
+    PL_last_swash_tmps = (U8*)NULL;
+    PL_last_swash_slen = 0;
+
+    PL_glob_index      = proto_perl->Iglob_index;
+    PL_srand_called    = proto_perl->Isrand_called;
+
+    if (flags & CLONEf_COPY_STACKS) {
+       /* next allocation will be PL_tmps_stack[PL_tmps_ix+1] */
+       PL_tmps_ix              = proto_perl->Itmps_ix;
+       PL_tmps_max             = proto_perl->Itmps_max;
+       PL_tmps_floor           = proto_perl->Itmps_floor;
+
+       /* next push_scope()/ENTER sets PL_scopestack[PL_scopestack_ix]
+        * NOTE: unlike the others! */
+       PL_scopestack_ix        = proto_perl->Iscopestack_ix;
+       PL_scopestack_max       = proto_perl->Iscopestack_max;
+
+       /* next SSPUSHFOO() sets PL_savestack[PL_savestack_ix]
+        * NOTE: unlike the others! */
+       PL_savestack_ix         = proto_perl->Isavestack_ix;
+       PL_savestack_max        = proto_perl->Isavestack_max;
+    }
+
+    PL_start_env       = proto_perl->Istart_env;       /* XXXXXX */
+    PL_top_env         = &PL_start_env;
+
+    PL_op              = proto_perl->Iop;
+
+    PL_Sv              = NULL;
+    PL_Xpv             = (XPV*)NULL;
+    my_perl->Ina       = proto_perl->Ina;
+
+    PL_statbuf         = proto_perl->Istatbuf;
+    PL_statcache       = proto_perl->Istatcache;
+
+#ifdef HAS_TIMES
+    PL_timesbuf                = proto_perl->Itimesbuf;
+#endif
+
+    PL_tainted         = proto_perl->Itainted;
+    PL_curpm           = proto_perl->Icurpm;   /* XXX No PMOP ref count */
+
+    PL_chopset         = proto_perl->Ichopset; /* XXX never deallocated */
+
+    PL_restartjmpenv   = proto_perl->Irestartjmpenv;
+    PL_restartop       = proto_perl->Irestartop;
+    PL_in_eval         = proto_perl->Iin_eval;
+    PL_delaymagic      = proto_perl->Idelaymagic;
+    PL_phase           = proto_perl->Iphase;
+    PL_localizing      = proto_perl->Ilocalizing;
+
+    PL_hv_fetch_ent_mh = NULL;
+    PL_modcount                = proto_perl->Imodcount;
+    PL_lastgotoprobe   = NULL;
+    PL_dumpindent      = proto_perl->Idumpindent;
+
+    PL_efloatbuf       = NULL;         /* reinits on demand */
+    PL_efloatsize      = 0;                    /* reinits on demand */
+
+    /* regex stuff */
+
+    PL_regdummy                = proto_perl->Iregdummy;
+    PL_colorset                = 0;            /* reinits PL_colors[] */
+    /*PL_colors[6]     = {0,0,0,0,0,0};*/
+
+    /* Pluggable optimizer */
+    PL_peepp           = proto_perl->Ipeepp;
+    PL_rpeepp          = proto_perl->Irpeepp;
+    /* op_free() hook */
+    PL_opfreehook      = proto_perl->Iopfreehook;
+
+#ifdef USE_REENTRANT_API
+    /* XXX: things like -Dm will segfault here in perlio, but doing
+     *  PERL_SET_CONTEXT(proto_perl);
+     * breaks too many other things
+     */
+    Perl_reentrant_init(aTHX);
+#endif
+
+    /* create SV map for pointer relocation */
+    PL_ptr_table = ptr_table_new();
+
+    /* initialize these special pointers as early as possible */
+    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 */
+    PL_strtab          = newHV();
+    HvSHAREKEYS_off(PL_strtab);
+    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);
+
+    PL_compiling.cop_file    = savesharedpv(PL_compiling.cop_file);
+    ptr_table_store(PL_ptr_table, proto_perl->Icompiling.cop_file, PL_compiling.cop_file);
+
+    ptr_table_store(PL_ptr_table, &proto_perl->Icompiling, &PL_compiling);
+    PL_compiling.cop_warnings = DUP_WARNINGS(PL_compiling.cop_warnings);
+    CopHINTHASH_set(&PL_compiling, cophh_copy(CopHINTHASH_get(&PL_compiling)));
+    PL_curcop          = (COP*)any_dup(proto_perl->Icurcop, proto_perl);
+
+    param->stashes      = newAV();  /* Setup array of objects to call clone on */
+    /* This makes no difference to the implementation, as it always pushes
+       and shifts pointers to other SVs without changing their reference
+       count, with the array becoming empty before it is freed. However, it
+       makes it conceptually clear what is going on, and will avoid some
+       work inside av.c, filling slots between AvFILL() and AvMAX() with
+       &PL_sv_undef, and SvREFCNT_dec()ing those.  */
+    AvREAL_off(param->stashes);
+
+    if (!(flags & CLONEf_COPY_STACKS)) {
+       param->unreferenced = newAV();
+    }
+
+#ifdef PERLIO_LAYERS
+    /* Clone PerlIO tables as soon as we can handle general xx_dup() */
+    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_origfilename    = SAVEPV(proto_perl->Iorigfilename);
+    PL_diehook         = sv_dup_inc(proto_perl->Idiehook, param);
+    PL_warnhook                = sv_dup_inc(proto_perl->Iwarnhook, param);
+
+    /* switches */
+    PL_patchlevel      = sv_dup_inc(proto_perl->Ipatchlevel, param);
+    PL_apiversion      = sv_dup_inc(proto_perl->Iapiversion, param);
+    PL_inplace         = SAVEPV(proto_perl->Iinplace);
+    PL_e_script                = sv_dup_inc(proto_perl->Ie_script, param);
+
+    /* magical thingies */
+    PL_formfeed                = sv_dup(proto_perl->Iformfeed, param);
+
+    PL_encoding                = sv_dup(proto_perl->Iencoding, param);
+
+    sv_setpvs(PERL_DEBUG_PAD(0), "");  /* For regex debugging. */
+    sv_setpvs(PERL_DEBUG_PAD(1), "");  /* ext/re needs these */
+    sv_setpvs(PERL_DEBUG_PAD(2), "");  /* even without DEBUGGING. */
+
+   
+    /* Clone the regex array */
+    /* ORANGE FIXME for plugins, probably in the SV dup code.
+       newSViv(PTR2IV(CALLREGDUPE(
+       INT2PTR(REGEXP *, SvIVX(regex)), param))))
+    */
+    PL_regex_padav = av_dup_inc(proto_perl->Iregex_padav, param);
+    PL_regex_pad = AvARRAY(PL_regex_padav);
+
+    /* shortcuts to various I/O objects */
     PL_ofsgv            = gv_dup_inc(proto_perl->Iofsgv, param);
     PL_stdingv         = gv_dup(proto_perl->Istdingv, param);
     PL_stderrgv                = gv_dup(proto_perl->Istderrgv, param);
@@ -12943,17 +13129,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_checkav         = av_dup_inc(proto_perl->Icheckav, param);
     PL_initav          = av_dup_inc(proto_perl->Iinitav, param);
 
-    PL_sub_generation  = proto_perl->Isub_generation;
     PL_isarev          = hv_dup_inc(proto_perl->Iisarev, param);
 
-    /* funky return mechanisms */
-    PL_forkprocess     = proto_perl->Iforkprocess;
-
     /* subprocess state */
     PL_fdpid           = av_dup_inc(proto_perl->Ifdpid, param);
 
-    /* internal state */
-    PL_maxo            = proto_perl->Imaxo;
     if (proto_perl->Iop_mask)
        PL_op_mask      = SAVEPVN(proto_perl->Iop_mask, PL_maxo);
     else
@@ -12965,23 +13145,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     OP_REFCNT_LOCK;
     PL_main_root       = OpREFCNT_inc(proto_perl->Imain_root);
     OP_REFCNT_UNLOCK;
-    PL_main_start      = proto_perl->Imain_start;
-    PL_eval_root       = proto_perl->Ieval_root;
-    PL_eval_start      = proto_perl->Ieval_start;
 
     /* runtime control stuff */
     PL_curcopdb                = (COP*)any_dup(proto_perl->Icurcopdb, proto_perl);
 
-    PL_filemode                = proto_perl->Ifilemode;
-    PL_lastfd          = proto_perl->Ilastfd;
-    PL_oldname         = proto_perl->Ioldname;         /* XXX not quite right */
-    PL_Argv            = NULL;
-    PL_Cmd             = NULL;
-    PL_gensym          = proto_perl->Igensym;
     PL_preambleav      = av_dup_inc(proto_perl->Ipreambleav, param);
-    PL_laststatval     = proto_perl->Ilaststatval;
-    PL_laststype       = proto_perl->Ilaststype;
-    PL_mess_sv         = NULL;
 
     PL_ors_sv          = sv_dup_inc(proto_perl->Iors_sv, param);
 
@@ -13014,8 +13182,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_custom_op_descs  = hv_dup_inc(proto_perl->Icustom_op_descs,param);
     PL_custom_ops      = hv_dup_inc(proto_perl->Icustom_ops, param);
 
-    PL_profiledata     = NULL;
-
     PL_compcv                  = cv_dup(proto_perl->Icompcv, param);
 
     PAD_CLONE_VARS(proto_perl, param);
@@ -13024,30 +13190,12 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     sys_intern_dup(&proto_perl->Isys_intern, &PL_sys_intern);
 #endif
 
-    /* more statics moved here */
-    PL_generation      = proto_perl->Igeneration;
     PL_DBcv            = cv_dup(proto_perl->IDBcv, param);
 
-    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_nomemok         = proto_perl->Inomemok;
-    PL_an              = proto_perl->Ian;
-    PL_evalseq         = proto_perl->Ievalseq;
-    PL_origenviron     = proto_perl->Iorigenviron;     /* XXX not quite right */
-    PL_origalen                = proto_perl->Iorigalen;
 #ifdef PERL_USES_PL_PIDSTATUS
     PL_pidstatus       = newHV();                      /* XXX flag for cloning? */
 #endif
     PL_osname          = SAVEPV(proto_perl->Iosname);
-    PL_sighandlerp     = proto_perl->Isighandlerp;
-
-    PL_runops          = proto_perl->Irunops;
-
     PL_parser          = parser_dup(proto_perl->Iparser, param);
 
     /* XXX this only works if the saved cop has already been cloned */
@@ -13057,29 +13205,14 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
                                    proto_perl);
     }
 
-    PL_subline         = proto_perl->Isubline;
     PL_subname         = sv_dup_inc(proto_perl->Isubname, param);
 
-#ifdef FCRYPT
-    PL_cryptseen       = proto_perl->Icryptseen;
-#endif
-
-    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_name  = SAVEPV(proto_perl->Icollation_name);
-    PL_collation_standard      = proto_perl->Icollation_standard;
-    PL_collxfrm_base   = proto_perl->Icollxfrm_base;
-    PL_collxfrm_mult   = proto_perl->Icollxfrm_mult;
 #endif /* USE_LOCALE_COLLATE */
 
 #ifdef USE_LOCALE_NUMERIC
     PL_numeric_name    = SAVEPV(proto_perl->Inumeric_name);
-    PL_numeric_standard        = proto_perl->Inumeric_standard;
-    PL_numeric_local   = proto_perl->Inumeric_local;
     PL_numeric_radix_sv        = sv_dup_inc(proto_perl->Inumeric_radix_sv, param);
 #endif /* !USE_LOCALE_NUMERIC */
 
@@ -13112,50 +13245,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_utf8_tolower    = sv_dup_inc(proto_perl->Iutf8_tolower, param);
     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_idcont     = sv_dup_inc(proto_perl->Iutf8_idcont, param);
+    PL_utf8_xidcont    = sv_dup_inc(proto_perl->Iutf8_xidcont, param);
+    PL_utf8_foldable   = sv_dup_inc(proto_perl->Iutf8_foldable, param);
 
-    /* Did the locale setup indicate UTF-8? */
-    PL_utf8locale      = proto_perl->Iutf8locale;
-    /* Unicode features (see perlrun/-C) */
-    PL_unicode         = proto_perl->Iunicode;
-
-    /* Pre-5.8 signals control */
-    PL_signals         = proto_perl->Isignals;
-
-    /* times() ticks per second */
-    PL_clocktick       = proto_perl->Iclocktick;
-
-    /* Recursion stopper for PerlIO_find_layer */
-    PL_in_load_module  = proto_perl->Iin_load_module;
-
-    /* sort() routine */
-    PL_sort_RealCmp    = proto_perl->Isort_RealCmp;
-
-    /* Not really needed/useful since the reenrant_retint is "volatile",
-     * but do it for consistency's sake. */
-    PL_reentrant_retint        = proto_perl->Ireentrant_retint;
-
-    /* Hooks to shared SVs and locks. */
-    PL_sharehook       = proto_perl->Isharehook;
-    PL_lockhook                = proto_perl->Ilockhook;
-    PL_unlockhook      = proto_perl->Iunlockhook;
-    PL_threadhook      = proto_perl->Ithreadhook;
-    PL_destroyhook     = proto_perl->Idestroyhook;
-    PL_signalhook      = proto_perl->Isignalhook;
-
-#ifdef THREADS_HAVE_PIDS
-    PL_ppid            = proto_perl->Ippid;
-#endif
-
-    /* swatch cache */
-    PL_last_swash_hv   = NULL; /* reinits on demand */
-    PL_last_swash_klen = 0;
-    PL_last_swash_key[0]= '\0';
-    PL_last_swash_tmps = (U8*)NULL;
-    PL_last_swash_slen = 0;
-
-    PL_glob_index      = proto_perl->Iglob_index;
-    PL_srand_called    = proto_perl->Isrand_called;
 
     if (proto_perl->Ipsig_pend) {
        Newxz(PL_psig_pend, SIG_SIZE, int);
@@ -13175,13 +13269,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        PL_psig_name    = (SV**)NULL;
     }
 
-    /* intrpvar.h stuff */
-
     if (flags & CLONEf_COPY_STACKS) {
-       /* next allocation will be PL_tmps_stack[PL_tmps_ix+1] */
-       PL_tmps_ix              = proto_perl->Itmps_ix;
-       PL_tmps_max             = proto_perl->Itmps_max;
-       PL_tmps_floor           = proto_perl->Itmps_floor;
        Newx(PL_tmps_stack, PL_tmps_max, SV*);
        sv_dup_inc_multiple(proto_perl->Itmps_stack, PL_tmps_stack,
                            PL_tmps_ix+1, param);
@@ -13198,8 +13286,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
        /* next push_scope()/ENTER sets PL_scopestack[PL_scopestack_ix]
         * NOTE: unlike the others! */
-       PL_scopestack_ix        = proto_perl->Iscopestack_ix;
-       PL_scopestack_max       = proto_perl->Iscopestack_max;
        Newxz(PL_scopestack, PL_scopestack_max, I32);
        Copy(proto_perl->Iscopestack, PL_scopestack, PL_scopestack_ix, I32);
 
@@ -13220,10 +13306,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
                                                   - proto_perl->Istack_base);
        PL_stack_max            = PL_stack_base + AvMAX(PL_curstack);
 
-       /* next SSPUSHFOO() sets PL_savestack[PL_savestack_ix]
-        * NOTE: unlike the others! */
-       PL_savestack_ix         = proto_perl->Isavestack_ix;
-       PL_savestack_max        = proto_perl->Isavestack_max;
        /*Newxz(PL_savestack, PL_savestack_max, ANY);*/
        PL_savestack            = ss_dup(proto_perl, param);
     }
@@ -13232,72 +13314,22 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        ENTER;                  /* perl_destruct() wants to LEAVE; */
     }
 
-    PL_start_env       = proto_perl->Istart_env;       /* XXXXXX */
-    PL_top_env         = &PL_start_env;
-
-    PL_op              = proto_perl->Iop;
-
-    PL_Sv              = NULL;
-    PL_Xpv             = (XPV*)NULL;
-    my_perl->Ina       = proto_perl->Ina;
-
-    PL_statbuf         = proto_perl->Istatbuf;
-    PL_statcache       = proto_perl->Istatcache;
     PL_statgv          = gv_dup(proto_perl->Istatgv, param);
     PL_statname                = sv_dup_inc(proto_perl->Istatname, param);
-#ifdef HAS_TIMES
-    PL_timesbuf                = proto_perl->Itimesbuf;
-#endif
 
-    PL_tainted         = proto_perl->Itainted;
-    PL_curpm           = proto_perl->Icurpm;   /* XXX No PMOP ref count */
     PL_rs              = sv_dup_inc(proto_perl->Irs, param);
     PL_last_in_gv      = gv_dup(proto_perl->Ilast_in_gv, param);
     PL_defoutgv                = gv_dup_inc(proto_perl->Idefoutgv, param);
-    PL_chopset         = proto_perl->Ichopset; /* XXX never deallocated */
     PL_toptarget       = sv_dup_inc(proto_perl->Itoptarget, param);
     PL_bodytarget      = sv_dup_inc(proto_perl->Ibodytarget, param);
     PL_formtarget      = sv_dup(proto_perl->Iformtarget, param);
 
-    PL_restartjmpenv   = proto_perl->Irestartjmpenv;
-    PL_restartop       = proto_perl->Irestartop;
-    PL_in_eval         = proto_perl->Iin_eval;
-    PL_delaymagic      = proto_perl->Idelaymagic;
-    PL_phase           = proto_perl->Iphase;
-    PL_localizing      = proto_perl->Ilocalizing;
-
     PL_errors          = sv_dup_inc(proto_perl->Ierrors, param);
-    PL_hv_fetch_ent_mh = NULL;
-    PL_modcount                = proto_perl->Imodcount;
-    PL_lastgotoprobe   = NULL;
-    PL_dumpindent      = proto_perl->Idumpindent;
 
     PL_sortcop         = (OP*)any_dup(proto_perl->Isortcop, proto_perl);
     PL_sortstash       = hv_dup(proto_perl->Isortstash, param);
     PL_firstgv         = gv_dup(proto_perl->Ifirstgv, param);
     PL_secondgv                = gv_dup(proto_perl->Isecondgv, param);
-    PL_efloatbuf       = NULL;         /* reinits on demand */
-    PL_efloatsize      = 0;                    /* reinits on demand */
-
-    /* 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};*/
-
-
-
-    /* Pluggable optimizer */
-    PL_peepp           = proto_perl->Ipeepp;
-    PL_rpeepp          = proto_perl->Irpeepp;
-    /* op_free() hook */
-    PL_opfreehook      = proto_perl->Iopfreehook;
 
     PL_stashcache       = newHV();
 
@@ -13519,6 +13551,14 @@ Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding)
        }
        FREETMPS;
        LEAVE;
+       if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
+           /* clear pos and any utf8 cache */
+           MAGIC * mg = mg_find(sv, PERL_MAGIC_regex_global);
+           if (mg)
+               mg->mg_len = -1;
+           if ((mg = mg_find(sv, PERL_MAGIC_utf8)))
+               magic_setutf8(sv,mg); /* clear UTF8 cache */
+       }
        SvUTF8_on(sv);
        return SvPVX(sv);
     }
@@ -13810,21 +13850,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;