This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
A couple of POD fixes by Steven Schubiger
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index 276b8c7..5230175 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -246,8 +246,13 @@ S_new_SV(pTHX)
     SvREFCNT(sv) = 1;
     SvFLAGS(sv) = 0;
     sv->sv_debug_optype = PL_op ? PL_op->op_type : 0;
-    sv->sv_debug_line = (U16) ((PL_parser && PL_parser->copline == NOLINE) ?
-        (PL_curcop ? CopLINE(PL_curcop) : 0) : PL_parser->copline);
+    sv->sv_debug_line = (U16) (PL_parser
+           ?  PL_parser->copline == NOLINE
+               ?  PL_curcop
+                   ? CopLINE(PL_curcop)
+                   : 0
+               : PL_parser->copline
+           : 0);
     sv->sv_debug_inpad = 0;
     sv->sv_debug_cloned = 0;
     sv->sv_debug_file = PL_curcop ? savepv(CopFILE(PL_curcop)): NULL;
@@ -349,7 +354,7 @@ Perl_sv_add_arena(pTHX_ char *ptr, U32 size, U32 flags)
 #ifdef DEBUGGING
        SvREFCNT(sv) = 0;
 #endif
-       /* Must always set typemask because it's awlays checked in on cleanup
+       /* Must always set typemask because it's always checked in on cleanup
           when the arenas are walked looking for objects.  */
        SvFLAGS(sv) = SVTYPEMASK;
        sv++;
@@ -462,7 +467,8 @@ do_clean_named_objs(pTHX_ SV *sv)
             SvOBJECT(GvSV(sv))) ||
             (GvAV(sv) && SvOBJECT(GvAV(sv))) ||
             (GvHV(sv) && SvOBJECT(GvHV(sv))) ||
-            (GvIO(sv) && SvOBJECT(GvIO(sv))) ||
+            /* In certain rare cases GvIOp(sv) can be NULL, which would make SvOBJECT(GvIO(sv)) dereference NULL. */
+            (GvIO(sv) ? (SvFLAGS(GvIOp(sv)) & SVs_OBJECT) : 0) ||
             (GvCV(sv) && SvOBJECT(GvCV(sv))) )
        {
            DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning named glob object:\n "), sv_dump(sv)));
@@ -538,7 +544,8 @@ Perl_sv_clean_all(pTHX)
   memory in the last arena-set (1/2 on average).  In trade, we get
   back the 1st slot in each arena (ie 1.7% of a CV-arena, less for
   smaller types).  The recovery of the wasted space allows use of
-  small arenas for large, rare body types,
+  small arenas for large, rare body types, by changing array* fields
+  in body_details_by_type[] below.
 */
 struct arena_desc {
     char       *arena;         /* the raw storage, allocated aligned */
@@ -549,7 +556,7 @@ struct arena_desc {
 struct arena_set;
 
 /* Get the maximum number of elements in set[] such that struct arena_set
-   will fit within PERL_ARENA_SIZE, which is probabably just under 4K, and
+   will fit within PERL_ARENA_SIZE, which is probably just under 4K, and
    therefore likely to be 1 aligned memory page.  */
 
 #define ARENAS_PER_SET  ((PERL_ARENA_SIZE - sizeof(struct arena_set*) \
@@ -780,16 +787,16 @@ are used for this, except for arena_size.
 For the sv-types that have no bodies, arenas are not used, so those
 PL_body_roots[sv_type] are unused, and can be overloaded.  In
 something of a special case, SVt_NULL is borrowed for HE arenas;
-PL_body_roots[SVt_NULL] is filled by S_more_he, but the
+PL_body_roots[HE_SVSLOT=SVt_NULL] is filled by S_more_he, but the
 bodies_by_type[SVt_NULL] slot is not used, as the table is not
-available in hv.c,
+available in hv.c.
 
-PTEs also use arenas, but are never seen in Perl_sv_upgrade.
-Nonetheless, they get their own slot in bodies_by_type[SVt_NULL], so
-they can just use the same allocation semantics.  At first, PTEs were
-also overloaded to a non-body sv-type, but this yielded hard-to-find
-malloc bugs, so was simplified by claiming a new slot.  This choice
-has no consequence at this time.
+PTEs also use arenas, but are never seen in Perl_sv_upgrade. Nonetheless,
+they get their own slot in bodies_by_type[PTE_SVSLOT =SVt_IV], so they can
+just use the same allocation semantics.  At first, PTEs were also
+overloaded to a non-body sv-type, but this yielded hard-to-find malloc
+bugs, so was simplified by claiming a new slot.  This choice has no
+consequence at this time.
 
 */
 
@@ -869,7 +876,7 @@ static const struct body_details bodies_by_type[] = {
       FALSE, NONV, NOARENA, FIT_ARENA(0, sizeof(HE)) },
 
     /* The bind placeholder pretends to be an RV for now.
-       Also it's marked as "can't upgrade" top stop anyone using it before it's
+       Also it's marked as "can't upgrade" to stop anyone using it before it's
        implemented.  */
     { 0, 0, 0, SVt_BIND, TRUE, NONV, NOARENA, 0 },
 
@@ -887,9 +894,6 @@ static const struct body_details bodies_by_type[] = {
     { sizeof(NV), sizeof(NV), 0, SVt_NV, FALSE, HADNV, HASARENA,
       FIT_ARENA(0, sizeof(NV)) },
 
-    /* RVs are in the head now.  */
-    { 0, 0, 0, SVt_RV, FALSE, NONV, NOARENA, 0 },
-
     /* 8 bytes on most ILP32 with IEEE doubles */
     { sizeof(xpv_allocated),
       copy_length(XPV, xpv_len)
@@ -911,7 +915,14 @@ static const struct body_details bodies_by_type[] = {
     /* 28 */
     { sizeof(XPVMG), copy_length(XPVMG, xmg_stash), 0, SVt_PVMG, FALSE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVMG)) },
-    
+
+    /* something big */
+    { sizeof(struct regexp_allocated), sizeof(struct regexp_allocated),
+      + relative_STRUCT_OFFSET(struct regexp_allocated, regexp, xpv_cur),
+      SVt_REGEXP, FALSE, NONV, HASARENA,
+      FIT_ARENA(0, sizeof(struct regexp_allocated))
+    },
+
     /* 48 */
     { sizeof(XPVGV), sizeof(XPVGV), 0, SVt_PVGV, TRUE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVGV)) },
@@ -1088,6 +1099,9 @@ S_new_body(pTHX_ svtype sv_type)
 
 #endif
 
+static const struct body_details fake_rv =
+    { 0, 0, 0, SVt_IV, FALSE, NONV, NOARENA, 0 };
+
 /*
 =for apidoc sv_upgrade
 
@@ -1106,8 +1120,9 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
     void*      new_body;
     const svtype old_type = SvTYPE(sv);
     const struct body_details *new_type_details;
-    const struct body_details *const old_type_details
+    const struct body_details *old_type_details
        = bodies_by_type + old_type;
+    SV *referant = NULL;
 
     if (new_type != SVt_PV && SvIsCOW(sv)) {
        sv_force_normal_flags(sv, 0);
@@ -1116,11 +1131,6 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
     if (old_type == new_type)
        return;
 
-    if (old_type > new_type)
-       Perl_croak(aTHX_ "sv_upgrade from type %d down to type %d",
-               (int)old_type, (int)new_type);
-
-
     old_body = SvANY(sv);
 
     /* Copying structures onto other structures that have been neatly zeroed
@@ -1165,9 +1175,16 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
     case SVt_NULL:
        break;
     case SVt_IV:
-       if (new_type < SVt_PVIV) {
-           new_type = (new_type == SVt_NV)
-               ? SVt_PVNV : SVt_PVIV;
+       if (SvROK(sv)) {
+           referant = SvRV(sv);
+           old_type_details = &fake_rv;
+           if (new_type == SVt_NV)
+               new_type = SVt_PVNV;
+       } else {
+           if (new_type < SVt_PVIV) {
+               new_type = (new_type == SVt_NV)
+                   ? SVt_PVNV : SVt_PVIV;
+           }
        }
        break;
     case SVt_NV:
@@ -1175,8 +1192,6 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
            new_type = SVt_PVNV;
        }
        break;
-    case SVt_RV:
-       break;
     case SVt_PV:
        assert(new_type > SVt_PV);
        assert(SVt_IV < SVt_PV);
@@ -1201,6 +1216,11 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
            Perl_croak(aTHX_ "Can't upgrade %s (%" UVuf ") to %" UVuf,
                       sv_reftype(sv, 0), (UV) old_type, (UV) new_type);
     }
+
+    if (old_type > new_type)
+       Perl_croak(aTHX_ "sv_upgrade from type %d down to type %d",
+               (int)old_type, (int)new_type);
+
     new_type_details = bodies_by_type + new_type;
 
     SvFLAGS(sv) &= ~SVTYPEMASK;
@@ -1220,11 +1240,6 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
        SvANY(sv) = new_XNV();
        SvNV_set(sv, 0);
        return;
-    case SVt_RV:
-       assert(old_type == SVt_NULL);
-       SvANY(sv) = &sv->sv_u.svu_rv;
-       SvRV_set(sv, 0);
-       return;
     case SVt_PVHV:
     case SVt_PVAV:
        assert(new_type_details->body_size);
@@ -1246,13 +1261,36 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
            AvMAX(sv)   = -1;
            AvFILLp(sv) = -1;
            AvREAL_only(sv);
+           if (old_type_details->body_size) {
+               AvALLOC(sv) = 0;
+           } else {
+               /* It will have been zeroed when the new body was allocated.
+                  Lets not write to it, in case it confuses a write-back
+                  cache.  */
+           }
+       } else {
+           assert(!SvOK(sv));
+           SvOK_off(sv);
+#ifndef NODEFAULT_SHAREKEYS
+           HvSHAREKEYS_on(sv);         /* key-sharing on by default */
+#endif
+           HvMAX(sv) = 7; /* (start with 8 buckets) */
+           if (old_type_details->body_size) {
+               HvFILL(sv) = 0;
+           } else {
+               /* It will have been zeroed when the new body was allocated.
+                  Lets not write to it, in case it confuses a write-back
+                  cache.  */
+           }
        }
 
        /* SVt_NULL isn't the only thing upgraded to AV or HV.
           The target created by newSVrv also is, and it can have magic.
           However, it never has SvPVX set.
        */
-       if (old_type >= SVt_RV) {
+       if (old_type == SVt_IV) {
+           assert(!SvROK(sv));
+       } else if (old_type >= SVt_PV) {
            assert(SvPVX_const(sv) == 0);
        }
 
@@ -1275,6 +1313,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
     case SVt_PVGV:
     case SVt_PVCV:
     case SVt_PVLV:
+    case SVt_REGEXP:
     case SVt_PVMG:
     case SVt_PVNV:
     case SVt_PV:
@@ -1323,8 +1362,11 @@ Perl_sv_upgrade(pTHX_ register SV *sv, svtype new_type)
 
        if (new_type == SVt_PVIO)
            IoPAGE_LEN(sv) = 60;
-       if (old_type < SVt_RV)
-           SvPV_set(sv, NULL);
+       if (old_type < SVt_PV) {
+           /* referant will be NULL unless the old type was SVt_IV emulating
+              SVt_RV */
+           sv->sv_u.svu_rv = referant;
+       }
        break;
     default:
        Perl_croak(aTHX_ "panic: sv_upgrade to unknown type %lu",
@@ -1357,17 +1399,18 @@ wrapper instead.
 int
 Perl_sv_backoff(pTHX_ register SV *sv)
 {
+    STRLEN delta;
+    const char * const s = SvPVX_const(sv);
     PERL_UNUSED_CONTEXT;
     assert(SvOOK(sv));
     assert(SvTYPE(sv) != SVt_PVHV);
     assert(SvTYPE(sv) != SVt_PVAV);
-    if (SvIVX(sv)) {
-       const char * const s = SvPVX_const(sv);
-       SvLEN_set(sv, SvLEN(sv) + SvIVX(sv));
-       SvPV_set(sv, SvPVX(sv) - SvIVX(sv));
-       SvIV_set(sv, 0);
-       Move(s, SvPVX(sv), SvCUR(sv)+1, char);
-    }
+
+    SvOOK_offset(sv, delta);
+    
+    SvLEN_set(sv, SvLEN(sv) + delta);
+    SvPV_set(sv, SvPVX(sv) - delta);
+    Move(s, SvPVX(sv), SvCUR(sv)+1, char);
     SvFLAGS(sv) &= ~SVf_OOK;
     return 0;
 }
@@ -1457,12 +1500,9 @@ Perl_sv_setiv(pTHX_ register SV *sv, IV i)
     SV_CHECK_THINKFIRST_COW_DROP(sv);
     switch (SvTYPE(sv)) {
     case SVt_NULL:
-       sv_upgrade(sv, SVt_IV);
-       break;
     case SVt_NV:
-       sv_upgrade(sv, SVt_PVNV);
+       sv_upgrade(sv, SVt_IV);
        break;
-    case SVt_RV:
     case SVt_PV:
        sv_upgrade(sv, SVt_PVIV);
        break;
@@ -1560,7 +1600,6 @@ Perl_sv_setnv(pTHX_ register SV *sv, NV num)
     case SVt_IV:
        sv_upgrade(sv, SVt_NV);
        break;
-    case SVt_RV:
     case SVt_PV:
     case SVt_PVIV:
        sv_upgrade(sv, SVt_PVNV);
@@ -1609,7 +1648,7 @@ S_not_a_number(pTHX_ SV *sv)
      const char *pv;
 
      if (DO_UTF8(sv)) {
-          dsv = sv_2mortal(newSVpvs(""));
+          dsv = newSVpvs_flags("", SVs_TEMP);
           pv = sv_uni_display(dsv, sv, 10, 0);
      } else {
          char *d = tmpbuf;
@@ -1907,7 +1946,11 @@ S_sv_2iuv_common(pTHX_ SV *sv) {
                   we're outside the range of NV integer precision */
 #endif
                ) {
-               SvIOK_on(sv);  /* Can this go wrong with rounding? NWC */
+               if (SvNOK(sv))
+                   SvIOK_on(sv);  /* Can this go wrong with rounding? NWC */
+               else {
+                   /* scalar has trailing garbage, eg "42a" */
+               }
                DEBUG_c(PerlIO_printf(Perl_debug_log,
                                      "0x%"UVxf" iv(%"NVgf" => %"IVdf") (precise)\n",
                                      PTR2UV(sv),
@@ -1946,6 +1989,7 @@ S_sv_2iuv_common(pTHX_ SV *sv) {
                   came from a (by definition imprecise) NV operation, and
                   we're outside the range of NV integer precision */
 #endif
+               && SvNOK(sv)
                )
                SvIOK_on(sv);
            SvIsUV_on(sv);
@@ -2103,6 +2147,12 @@ S_sv_2iuv_common(pTHX_ SV *sv) {
                 }
             }
 #endif /* NV_PRESERVES_UV */
+       /* It might be more code efficient to go through the entire logic above
+          and conditionally set with SvIOKp_on() rather than SvIOK(), but it
+          gets complex and potentially buggy, so more programmer efficient
+          to do it this way, by turning off the public flags:  */
+       if (!numtype)
+           SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK);
        }
     }
     else  {
@@ -2371,11 +2421,15 @@ Perl_sv_2nv(pTHX_ register SV *sv)
     if (SvIOKp(sv)) {
        SvNV_set(sv, SvIsUV(sv) ? (NV)SvUVX(sv) : (NV)SvIVX(sv));
 #ifdef NV_PRESERVES_UV
-       SvNOK_on(sv);
+       if (SvIOK(sv))
+           SvNOK_on(sv);
+       else
+           SvNOKp_on(sv);
 #else
        /* Only set the public NV OK flag if this NV preserves the IV  */
        /* Check it's not 0xFFFFFFFFFFFFFFFF */
-       if (SvIsUV(sv) ? ((SvUVX(sv) != UV_MAX)&&(SvUVX(sv) == U_V(SvNVX(sv))))
+       if (SvIOK(sv) &&
+           SvIsUV(sv) ? ((SvUVX(sv) != UV_MAX)&&(SvUVX(sv) == U_V(SvNVX(sv))))
                       : (SvIVX(sv) == I_V(SvNVX(sv))))
            SvNOK_on(sv);
        else
@@ -2394,7 +2448,10 @@ Perl_sv_2nv(pTHX_ register SV *sv)
            SvNV_set(sv, (numtype & IS_NUMBER_NEG) ? -(NV)value : (NV)value);
        } else
            SvNV_set(sv, Atof(SvPVX_const(sv)));
-       SvNOK_on(sv);
+       if (numtype)
+           SvNOK_on(sv);
+       else
+           SvNOKp_on(sv);
 #else
        SvNV_set(sv, Atof(SvPVX_const(sv)));
        /* Only set the public NV OK flag if this NV preserves the value in
@@ -2461,6 +2518,12 @@ Perl_sv_2nv(pTHX_ register SV *sv)
                 }
             }
         }
+       /* It might be more code efficient to go through the entire logic above
+          and conditionally set with SvNOKp_on() rather than SvNOK(), but it
+          gets complex and potentially buggy, so more programmer efficient
+          to do it this way, by turning off the public flags:  */
+       if (!numtype)
+           SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK);
 #endif /* NV_PRESERVES_UV */
     }
     else  {
@@ -2495,6 +2558,29 @@ Perl_sv_2nv(pTHX_ register SV *sv)
     return SvNVX(sv);
 }
 
+/*
+=for apidoc sv_2num
+
+Return an SV with the numeric value of the source SV, doing any necessary
+reference or overload conversion.  You must use the C<SvNUM(sv)> macro to
+access this function.
+
+=cut
+*/
+
+SV *
+Perl_sv_2num(pTHX_ register SV *sv)
+{
+    if (!SvROK(sv))
+       return sv;
+    if (SvAMAGIC(sv)) {
+       SV * const tmpsv = AMG_CALLun(sv,numer);
+       if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv))))
+           return sv_2num(tmpsv);
+    }
+    return sv_2mortal(newSVuv(PTR2UV(SvRV(sv))));
+}
+
 /* uiv_2buf(): private routine for use by sv_2pv_flags(): print an IV or
  * UV as a string towards the end of buf, and return pointers to start and
  * end of it.
@@ -2634,28 +2720,31 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                STRLEN len;
                char *retval;
                char *buffer;
-               MAGIC *mg;
                const SV *const referent = (SV*)SvRV(sv);
 
                if (!referent) {
                    len = 7;
                    retval = buffer = savepvn("NULLREF", len);
-               } else if (SvTYPE(referent) == SVt_PVMG
-                          && ((SvFLAGS(referent) &
-                               (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG))
-                              == (SVs_OBJECT|SVs_SMG))
-                          && (mg = mg_find(referent, PERL_MAGIC_qr)))
-                {
-                    char *str = NULL;
-                    I32 haseval = 0;
-                    U32 flags = 0;
-                    (str) = CALLREG_AS_STR(mg,lp,&flags,&haseval);
-                    if (flags & 1)
-                       SvUTF8_on(sv);
-                    else
-                       SvUTF8_off(sv);
-                    PL_reginterp_cnt += haseval;
-                   return str;
+               } else if (SvTYPE(referent) == SVt_REGEXP) {
+                   const REGEXP * const re = (REGEXP *)referent;
+                   I32 seen_evals = 0;
+
+                   assert(re);
+                       
+                   /* If the regex is UTF-8 we want the containing scalar to
+                      have an UTF-8 flag too */
+                   if (RX_UTF8(re))
+                       SvUTF8_on(sv);
+                   else
+                       SvUTF8_off(sv); 
+
+                   if ((seen_evals = RX_SEEN_EVALS(re)))
+                       PL_reginterp_cnt += seen_evals;
+
+                   if (lp)
+                       *lp = RX_WRAPLEN(re);
+                   return RX_WRAPPED(re);
                } else {
                    const char *const typestr = sv_reftype(referent, 0);
                    const STRLEN typelen = strlen(typestr);
@@ -2721,10 +2810,12 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
            }
        }
        if (SvREADONLY(sv) && !SvOK(sv)) {
-           if (ckWARN(WARN_UNINITIALIZED))
-               report_uninit(sv);
            if (lp)
                *lp = 0;
+           if (flags & SV_UNDEF_RETURNS_NULL)
+               return NULL;
+           if (ckWARN(WARN_UNINITIALIZED))
+               report_uninit(sv);
            return (char *)"";
        }
     }
@@ -2734,15 +2825,16 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
        const U32 isUIOK = SvIsUV(sv);
        char buf[TYPE_CHARS(UV)];
        char *ebuf, *ptr;
+       STRLEN len;
 
        if (SvTYPE(sv) < SVt_PVIV)
            sv_upgrade(sv, SVt_PVIV);
        ptr = uiv_2buf(buf, SvIVX(sv), SvUVX(sv), isUIOK, &ebuf);
+       len = ebuf - ptr;
        /* inlined from sv_setpvn */
-       SvGROW_mutable(sv, (STRLEN)(ebuf - ptr + 1));
-       Move(ptr,SvPVX_mutable(sv),ebuf - ptr,char);
-       SvCUR_set(sv, ebuf - ptr);
-       s = SvEND(sv);
+       s = SvGROW_mutable(sv, len + 1);
+       Move(ptr, s, len, char);
+       s += len;
        *s = '\0';
     }
     else if (SvNOKp(sv)) {
@@ -2762,8 +2854,10 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
        }
        errno = olderrno;
 #ifdef FIXNEGATIVEZERO
-        if (*s == '-' && s[1] == '0' && !s[2])
-           my_strlcpy(s, "0", SvLEN(s));
+        if (*s == '-' && s[1] == '0' && !s[2]) {
+           s[0] = '0';
+           s[1] = 0;
+       }
 #endif
        while (*s) s++;
 #ifdef hcx
@@ -2775,10 +2869,12 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
        if (isGV_with_GP(sv))
            return glob_2pv((GV *)sv, lp);
 
-       if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
-           report_uninit(sv);
        if (lp)
            *lp = 0;
+       if (flags & SV_UNDEF_RETURNS_NULL)
+           return NULL;
+       if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
+           report_uninit(sv);
        if (SvTYPE(sv) < SVt_PV)
            /* Typically the caller expects that sv_any is not NULL now.  */
            sv_upgrade(sv, SVt_PV);
@@ -3145,7 +3241,7 @@ copy-ish functions and macros use this underneath.
 static void
 S_glob_assign_glob(pTHX_ SV *dstr, SV *sstr, const int dtype)
 {
-    I32 method_changed = 0;
+    I32 mro_changes = 0; /* 1 = method, 2 = isa */
 
     if (dtype != SVt_PVGV) {
        const char * const name = GvNAME(sstr);
@@ -3186,15 +3282,18 @@ S_glob_assign_glob(pTHX_ SV *dstr, SV *sstr, const int dtype)
         /* If source has a real method, then a method is
            going to change */
         else if(GvCV((GV*)sstr)) {
-            method_changed = 1;
+            mro_changes = 1;
         }
     }
 
     /* If dest already had a real method, that's a change as well */
-    if(!method_changed && GvGP((GV*)dstr) && GvCVu((GV*)dstr)) {
-        method_changed = 1;
+    if(!mro_changes && GvGP((GV*)dstr) && GvCVu((GV*)dstr)) {
+        mro_changes = 1;
     }
 
+    if(strEQ(GvNAME((GV*)dstr),"ISA"))
+        mro_changes = 2;
+
     gp_free((GV*)dstr);
     isGV_with_GP_off(dstr);
     (void)SvOK_off(dstr);
@@ -3209,7 +3308,8 @@ S_glob_assign_glob(pTHX_ SV *dstr, SV *sstr, const int dtype)
            GvIMPORTED_on(dstr);
        }
     GvMULTI_on(dstr);
-    if(method_changed) mro_method_changed_in(GvSTASH(dstr));
+    if(mro_changes == 2) mro_isa_changed_in(GvSTASH(dstr));
+    else if(mro_changes) mro_method_changed_in(GvSTASH(dstr));
     return;
 }
 
@@ -3374,7 +3474,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                sv_upgrade(dstr, SVt_IV);
                break;
            case SVt_NV:
-           case SVt_RV:
            case SVt_PV:
                sv_upgrade(dstr, SVt_PVIV);
                break;
@@ -3392,7 +3491,11 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            assert(!SvTAINTED(sstr));
            return;
        }
-       goto undef_sstr;
+       if (!SvROK(sstr))
+           goto undef_sstr;
+       if (dtype < SVt_PV && dtype != SVt_IV)
+           sv_upgrade(dstr, SVt_IV);
+       break;
 
     case SVt_NV:
        if (SvNOK(sstr)) {
@@ -3401,7 +3504,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            case SVt_IV:
                sv_upgrade(dstr, SVt_NV);
                break;
-           case SVt_RV:
            case SVt_PV:
            case SVt_PVIV:
                sv_upgrade(dstr, SVt_PVNV);
@@ -3420,10 +3522,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        }
        goto undef_sstr;
 
-    case SVt_RV:
-       if (dtype < SVt_RV)
-           sv_upgrade(dstr, SVt_RV);
-       break;
     case SVt_PVFM:
 #ifdef PERL_OLD_COPY_ON_WRITE
        if ((SvFLAGS(sstr) & CAN_COW_MASK) == CAN_COW_FLAGS) {
@@ -3433,6 +3531,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        }
        /* Fall through */
 #endif
+    case SVt_REGEXP:
     case SVt_PV:
        if (dtype < SVt_PV)
            sv_upgrade(dstr, SVt_PV);
@@ -3525,7 +3624,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        }
 
        if (dtype >= SVt_PV) {
-           if (dtype == SVt_PVGV) {
+           if (dtype == SVt_PVGV && isGV_with_GP(dstr)) {
                glob_assign_ref(dstr, sstr);
                return;
            }
@@ -3612,9 +3711,11 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                                /* and won't be needed again, potentially */
              !(PL_op && PL_op->op_type == OP_AASSIGN))
 #ifdef PERL_OLD_COPY_ON_WRITE
-            && !((sflags & CAN_COW_MASK) == CAN_COW_FLAGS
-                && (SvFLAGS(dstr) & CAN_COW_MASK) == CAN_COW_FLAGS
-                 && SvTYPE(sstr) >= SVt_PVIV)
+            && ((flags & SV_COW_SHARED_HASH_KEYS)
+               ? (!((sflags & CAN_COW_MASK) == CAN_COW_FLAGS
+                    && (SvFLAGS(dstr) & CAN_COW_MASK) == CAN_COW_FLAGS
+                    && SvTYPE(sstr) >= SVt_PVIV))
+               : 1)
 #endif
             ) {
             /* Failed the swipe test, and it's not a shared hash key either.
@@ -3704,7 +3805,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            SvNV_set(dstr, SvNVX(sstr));
        }
        if (sflags & SVp_IOK) {
-           SvOOK_off(dstr);
            SvIV_set(dstr, SvIVX(sstr));
            /* Must do this otherwise some other overloaded use of 0x80000000
               gets confused. I guess SVpbm_VALID */
@@ -3994,7 +4094,7 @@ Perl_sv_usepvn_flags(pTHX_ SV *sv, char *ptr, STRLEN len, U32 flags)
     SvCUR_set(sv, len);
     SvLEN_set(sv, allocate);
     if (!(flags & SV_HAS_TRAILING_NUL)) {
-       *SvEND(sv) = '\0';
+       ptr[len] = '\0';
     }
     (void)SvPOK_only_UTF8(sv);         /* validate pointer */
     SvTAINT(sv);
@@ -4143,13 +4243,22 @@ refer to the same chunk of data.
 void
 Perl_sv_chop(pTHX_ register SV *sv, register const char *ptr)
 {
-    register STRLEN delta;
+    STRLEN delta;
+    STRLEN old_delta;
+    U8 *p;
+#ifdef DEBUGGING
+    const U8 *real_start;
+#endif
+
     if (!ptr || !SvPOKp(sv))
        return;
     delta = ptr - SvPVX_const(sv);
+    if (!delta) {
+       /* Nothing to do.  */
+       return;
+    }
+    assert(ptr > SvPVX_const(sv));
     SV_CHECK_THINKFIRST(sv);
-    if (SvTYPE(sv) < SVt_PVIV)
-       sv_upgrade(sv,SVt_PVIV);
 
     if (!SvOOK(sv)) {
        if (!SvLEN(sv)) { /* make copy of shared string */
@@ -4159,17 +4268,40 @@ Perl_sv_chop(pTHX_ register SV *sv, register const char *ptr)
            Move(pvx,SvPVX(sv),len,char);
            *SvEND(sv) = '\0';
        }
-       SvIV_set(sv, 0);
-       /* Same SvOOK_on but SvOOK_on does a SvIOK_off
-          and we do that anyway inside the SvNIOK_off
-       */
        SvFLAGS(sv) |= SVf_OOK;
+       old_delta = 0;
+    } else {
+       SvOOK_offset(sv, old_delta);
     }
-    SvNIOK_off(sv);
     SvLEN_set(sv, SvLEN(sv) - delta);
     SvCUR_set(sv, SvCUR(sv) - delta);
     SvPV_set(sv, SvPVX(sv) + delta);
-    SvIV_set(sv, SvIVX(sv) + delta);
+
+    p = (U8 *)SvPVX_const(sv);
+
+    delta += old_delta;
+
+#ifdef DEBUGGING
+    real_start = p - delta;
+#endif
+
+    assert(delta);
+    if (delta < 0x100) {
+       *--p = (U8) delta;
+    } else {
+       *--p = 0;
+       p -= sizeof(STRLEN);
+       Copy((U8*)&delta, p, sizeof(STRLEN), U8);
+    }
+
+#ifdef DEBUGGING
+    /* Fill the preceding buffer with sentinals to verify that no-one is
+       using it.  */
+    while (p > real_start) {
+       --p;
+       *p = (U8)PTR2UV(p);
+    }
+#endif
 }
 
 /*
@@ -4252,7 +4384,7 @@ Perl_sv_catsv_flags(pTHX_ SV *dsv, register SV *ssv, I32 flags)
            if (dutf8 != sutf8) {
                if (dutf8) {
                    /* Not modifying source SV, so taking a temporary copy. */
-                   SV* const csv = sv_2mortal(newSVpvn(spv, slen));
+                   SV* const csv = newSVpvn_flags(spv, slen, SVs_TEMP);
 
                    sv_utf8_upgrade(csv);
                    spv = SvPV_const(csv, slen);
@@ -4384,7 +4516,6 @@ Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, const MGVTBL *vtable,
     */
     if (!obj || obj == sv ||
        how == PERL_MAGIC_arylen ||
-       how == PERL_MAGIC_qr ||
        how == PERL_MAGIC_symtab ||
        (SvTYPE(obj) == SVt_PVGV &&
            (GvSV(obj) == sv || GvHV(obj) == (HV*)sv || GvAV(obj) == (AV*)sv ||
@@ -4926,10 +5057,8 @@ Perl_sv_insert(pTHX_ SV *bigstr, STRLEN offset, STRLEN len, const char *little,
     else if ((i = mid - big)) {        /* faster from front */
        midend -= littlelen;
        mid = midend;
+       Move(big, midend - i, i, char);
        sv_chop(bigstr,midend-i);
-       big += i;
-       while (i--)
-           *--midend = *--big;
        if (littlelen)
            Move(little, mid, littlelen,char);
     }
@@ -4988,13 +5117,9 @@ Perl_sv_replace(pTHX_ register SV *sv, register SV *nsv)
 #else
     StructCopy(nsv,sv,SV);
 #endif
-    /* Currently could join these into one piece of pointer arithmetic, but
-       it would be unclear.  */
-    if(SvTYPE(sv) == SVt_IV)
+    if(SvTYPE(sv) == SVt_IV) {
        SvANY(sv)
            = (XPVIV*)((char*)&(sv->sv_u.svu_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
-    else if (SvTYPE(sv) == SVt_RV) {
-       SvANY(sv) = &sv->sv_u.svu_rv;
     }
        
 
@@ -5051,16 +5176,28 @@ Perl_sv_clear(pTHX_ register SV *sv)
 
     assert(sv);
     assert(SvREFCNT(sv) == 0);
+    assert(SvTYPE(sv) != SVTYPEMASK);
 
     if (type <= SVt_IV) {
        /* See the comment in sv.h about the collusion between this early
           return and the overloading of the NULL and IV slots in the size
           table.  */
+       if (SvROK(sv)) {
+           SV * const target = SvRV(sv);
+           if (SvWEAKREF(sv))
+               sv_del_backref(target, sv);
+           else
+               SvREFCNT_dec(target);
+       }
+       SvFLAGS(sv) &= SVf_BREAK;
+       SvFLAGS(sv) |= SVTYPEMASK;
        return;
     }
 
     if (SvOBJECT(sv)) {
-       if (PL_defstash) {              /* Still have a symbol table? */
+       if (PL_defstash &&      /* Still have a symbol table? */
+           SvDESTROYABLE(sv))
+       {
            dSP;
            HV* stash;
            do {        
@@ -5134,6 +5271,10 @@ Perl_sv_clear(pTHX_ register SV *sv)
        Safefree(IoFMT_NAME(sv));
        Safefree(IoBOTTOM_NAME(sv));
        goto freescalar;
+    case SVt_REGEXP:
+       /* FIXME for plugins */
+       pregfree2((REGEXP*) sv);
+       goto freescalar;
     case SVt_PVCV:
     case SVt_PVFM:
        cv_undef((CV*)sv);
@@ -5177,14 +5318,15 @@ Perl_sv_clear(pTHX_ register SV *sv)
     case SVt_PVMG:
     case SVt_PVNV:
     case SVt_PVIV:
+    case SVt_PV:
       freescalar:
        /* Don't bother with SvOOK_off(sv); as we're only going to free it.  */
        if (SvOOK(sv)) {
-           SvPV_set(sv, SvPVX_mutable(sv) - SvIVX(sv));
+           STRLEN offset;
+           SvOOK_offset(sv, offset);
+           SvPV_set(sv, SvPVX_mutable(sv) - offset);
            /* Don't even bother with turning off the OOK flag.  */
        }
-    case SVt_PV:
-    case SVt_RV:
        if (SvROK(sv)) {
            SV * const target = SvRV(sv);
            if (SvWEAKREF(sv))
@@ -5286,17 +5428,28 @@ Perl_sv_free(pTHX_ SV *sv)
            return;
        }
        if (ckWARN_d(WARN_INTERNAL)) {
-           Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
-                        "Attempt to free unreferenced scalar: SV 0x%"UVxf
-                        pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE);
 #ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
            Perl_dump_sv_child(aTHX_ sv);
 #else
   #ifdef DEBUG_LEAKING_SCALARS
-       sv_dump(sv);
+           sv_dump(sv);
   #endif
+#ifdef DEBUG_LEAKING_SCALARS_ABORT
+           if (PL_warnhook == PERL_WARNHOOK_FATAL
+               || ckDEAD(packWARN(WARN_INTERNAL))) {
+               /* Don't let Perl_warner cause us to escape our fate:  */
+               abort();
+           }
+#endif
+           /* This may not return:  */
+           Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
+                        "Attempt to free unreferenced scalar: SV 0x%"UVxf
+                        pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE);
 #endif
        }
+#ifdef DEBUG_LEAKING_SCALARS_ABORT
+       abort();
+#endif
        return;
     }
     if (--(SvREFCNT(sv)) > 0)
@@ -5384,7 +5537,7 @@ Perl_sv_len_utf8(pTHX_ register SV *sv)
 
        if (PL_utf8cache) {
            STRLEN ulen;
-           MAGIC *mg = SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_utf8) : 0;
+           MAGIC *mg = SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_utf8) : NULL;
 
            if (mg && mg->mg_len != -1) {
                ulen = mg->mg_len;
@@ -5942,8 +6095,7 @@ Perl_sv_eq(pTHX_ register SV *sv1, register SV *sv2)
         * invalidate pv1, so we may need to make a copy */
        if (sv1 == sv2 && (SvTHINKFIRST(sv1) || SvGMAGICAL(sv1))) {
            pv1 = SvPV_const(sv1, cur1);
-           sv1 = sv_2mortal(newSVpvn(pv1, cur1));
-           if (SvUTF8(sv2)) SvUTF8_on(sv1);
+           sv1 = newSVpvn_flags(pv1, cur1, SVs_TEMP | SvUTF8(sv2));
        }
        pv1 = SvPV_const(sv1, cur1);
     }
@@ -6100,7 +6252,7 @@ Perl_sv_cmp(pTHX_ register SV *sv1, register SV *sv2)
 
 Compares the strings in two SVs in a locale-aware manner. Is UTF-8 and
 'use bytes' aware, handles get magic, and will coerce its args to strings
-if necessary.  See also C<sv_cmp_locale>.  See also C<sv_cmp>.
+if necessary.  See also C<sv_cmp>.
 
 =cut
 */
@@ -6899,6 +7051,40 @@ Perl_sv_newmortal(pTHX)
     return sv;
 }
 
+
+/*
+=for apidoc newSVpvn_flags
+
+Creates a new SV and copies a string into it.  The reference count for the
+SV is set to 1.  Note that if C<len> is zero, Perl will create a zero length
+string.  You are responsible for ensuring that the source string is at least
+C<len> bytes long.  If the C<s> argument is NULL the new SV will be undefined.
+Currently the only flag bits accepted are C<SVf_UTF8> and C<SVs_TEMP>.
+If C<SVs_TEMP> is set, then C<sv2mortal()> is called on the result before
+returning. If C<SVf_UTF8> is set, then it will be set on the new SV.
+C<newSVpvn_utf8()> is a convenience wrapper for this function, defined as
+
+    #define newSVpvn_utf8(s, len, u)                   \
+       newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0)
+
+=cut
+*/
+
+SV *
+Perl_newSVpvn_flags(pTHX_ const char *s, STRLEN len, U32 flags)
+{
+    dVAR;
+    register SV *sv;
+
+    /* All the flags we don't support must be zero.
+       And we're new code so I'm going to assert this from the start.  */
+    assert(!(flags & ~(SVf_UTF8|SVs_TEMP)));
+    new_SV(sv);
+    sv_setpvn(sv,s,len);
+    SvFLAGS(sv) |= (flags & SVf_UTF8);
+    return (flags & SVs_TEMP) ? sv_2mortal(sv) : sv;
+}
+
 /*
 =for apidoc sv_2mortal
 
@@ -6968,7 +7154,6 @@ Perl_newSVpvn(pTHX_ const char *s, STRLEN len)
     return sv;
 }
 
-
 /*
 =for apidoc newSVhek
 
@@ -7046,11 +7231,11 @@ Perl_newSVhek(pTHX_ const HEK *hek)
 
 Creates a new SV with its SvPVX_const pointing to a shared string in the string
 table. If the string does not already exist in the table, it is created
-first.  Turns on READONLY and FAKE.  The string's hash is stored in the UV
-slot of the SV; if the C<hash> parameter is non-zero, that value is used;
-otherwise the hash is computed.  The idea here is that as the string table
-is used for shared hash keys these strings will have SvPVX_const == HeKEY and
-hash lookup will avoid string compare.
+first.  Turns on READONLY and FAKE. If the C<hash> parameter is non-zero, that
+value is used; otherwise the hash is computed. The string's hash can be later
+be retrieved from the SV with the C<SvSHARED_HASH()> macro. The idea here is
+that as the string table is used for shared hash keys these strings will have
+SvPVX_const == HeKEY and hash lookup will avoid string compare.
 
 =cut
 */
@@ -7203,7 +7388,7 @@ Perl_newSVuv(pTHX_ UV u)
 /*
 =for apidoc newSV_type
 
-Creates a new SV, of the type specificied.  The reference count for the new SV
+Creates a new SV, of the type specified.  The reference count for the new SV
 is set to 1.
 
 =cut
@@ -7232,7 +7417,7 @@ SV *
 Perl_newRV_noinc(pTHX_ SV *tmpRef)
 {
     dVAR;
-    register SV *sv = newSV_type(SVt_RV);
+    register SV *sv = newSV_type(SVt_IV);
     SvTEMP_off(tmpRef);
     SvRV_set(sv, tmpRef);
     SvROK_on(sv);
@@ -7594,7 +7779,8 @@ Perl_sv_pvn_force_flags(pTHX_ SV *sv, STRLEN *lp, I32 flags)
            else
                Perl_croak(aTHX_ "Can't coerce readonly %s to string", ref);
        }
-       if (SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM)
+       if ((SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM)
+           || isGV_with_GP(sv))
            Perl_croak(aTHX_ "Can't coerce %s to string in %s", sv_reftype(sv,0),
                OP_NAME(PL_op));
        s = sv_2pv_flags(sv, &len, flags);
@@ -7608,7 +7794,7 @@ Perl_sv_pvn_force_flags(pTHX_ SV *sv, STRLEN *lp, I32 flags)
            SvGROW(sv, len + 1);
            Move(s,SvPVX(sv),len,char);
            SvCUR_set(sv, len);
-           *SvEND(sv) = '\0';
+           SvPVX(sv)[len] = '\0';
        }
        if (!SvPOK(sv)) {
            SvPOK_on(sv);               /* validate pointer */
@@ -7676,7 +7862,6 @@ Perl_sv_reftype(pTHX_ const SV *sv, int ob)
        case SVt_NULL:
        case SVt_IV:
        case SVt_NV:
-       case SVt_RV:
        case SVt_PV:
        case SVt_PVIV:
        case SVt_PVNV:
@@ -7700,6 +7885,7 @@ Perl_sv_reftype(pTHX_ const SV *sv, int ob)
        case SVt_PVFM:          return "FORMAT";
        case SVt_PVIO:          return "IO";
        case SVt_BIND:          return "BIND";
+       case SVt_REGEXP:        return "REGEXP"; 
        default:                return "UNKNOWN";
        }
     }
@@ -7787,15 +7973,11 @@ Perl_newSVrv(pTHX_ SV *rv, const char *classname)
        SvFLAGS(rv) = 0;
        SvREFCNT(rv) = refcnt;
 
-       sv_upgrade(rv, SVt_RV);
+       sv_upgrade(rv, SVt_IV);
     } else if (SvROK(rv)) {
        SvREFCNT_dec(SvRV(rv));
-    } else if (SvTYPE(rv) < SVt_RV)
-       sv_upgrade(rv, SVt_RV);
-    else if (SvTYPE(rv) > SVt_RV) {
-       SvPV_free(rv);
-       SvCUR_set(rv, 0);
-       SvLEN_set(rv, 0);
+    } else {
+       prepare_SV_for_RV(rv);
     }
 
     SvOK_off(rv);
@@ -7938,6 +8120,8 @@ Perl_sv_bless(pTHX_ SV *sv, HV *stash)
         Perl_croak(aTHX_ "Can't bless non-reference value");
     tmpRef = SvRV(sv);
     if (SvFLAGS(tmpRef) & (SVs_OBJECT|SVf_READONLY)) {
+       if (SvIsCOW(tmpRef))
+           sv_force_normal_flags(tmpRef, 0);
        if (SvREADONLY(tmpRef))
            Perl_croak(aTHX_ PL_no_modify);
        if (SvOBJECT(tmpRef)) {
@@ -8588,10 +8772,11 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                %p              include pointer address (standard)      
                %-p     (SVf)   include an SV (previously %_)
                %-<num>p        include an SV with precision <num>      
-               %1p     (VDf)   include a v-string (as %vd)
                %<num>p         reserved for future extensions
 
        Robin Barker 2005-07-14
+
+               %1p     (VDf)   removed.  RMB 2007-10-19
 */
            char* r = q; 
            bool sv = FALSE;    
@@ -8611,13 +8796,6 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                        is_utf8 = TRUE;
                    goto string;
                }
-#if vdNUMBER
-               else if (n == vdNUMBER) {       /* VDf */
-                   vectorize = TRUE;
-                   VECTORIZE_ARGS
-                   goto format_vd;
-               }
-#endif
                else if (n) {
                    if (ckWARN_d(WARN_INTERNAL))
                        Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
@@ -9181,7 +9359,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                : SvNV(argsv);
 
            need = 0;
-           if (c != 'e' && c != 'E') {
+           /* nv * 0 will be NaN for NaN, +Inf and -Inf, and 0 for anything
+              else. frexp() has some unspecified behaviour for those three */
+           if (c != 'e' && c != 'E' && (nv * 0) == 0) {
                i = PERL_INT_MIN;
                /* FIXME: if HAS_LONG_DOUBLE but not USE_LONG_DOUBLE this
                   will cast our (long double) to (double) */
@@ -9404,7 +9584,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            }
            else {
                const STRLEN old_elen = elen;
-               SV * const nsv = sv_2mortal(newSVpvn(eptr, elen));
+               SV * const nsv = newSVpvn_flags(eptr, elen, SVs_TEMP);
                sv_utf8_upgrade(nsv);
                eptr = SvPVX_const(nsv);
                elen = SvCUR(nsv);
@@ -9482,7 +9662,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 All the macros and functions in this section are for the private use of
 the main function, perl_clone().
 
-The foo_dup() functions make an exact copy of an existing foo thinngy.
+The foo_dup() functions make an exact copy of an existing foo thingy.
 During the course of a cloning, a hash table is used to map old addresses
 to new addresses. The table is created and manipulated with the
 ptr_table_* functions.
@@ -9568,6 +9748,7 @@ Perl_parser_dup(pTHX_ const yy_parser *proto, CLONE_PARAMS* param)
     parser->multi_close        = proto->multi_close;
     parser->multi_open = proto->multi_open;
     parser->multi_start        = proto->multi_start;
+    parser->multi_end  = proto->multi_end;
     parser->pending_ident = proto->pending_ident;
     parser->preambled  = proto->preambled;
     parser->sublex_info        = proto->sublex_info; /* XXX not quite right */
@@ -9575,12 +9756,20 @@ Perl_parser_dup(pTHX_ const yy_parser *proto, CLONE_PARAMS* param)
     parser->expect     = proto->expect;
     parser->copline    = proto->copline;
     parser->last_lop_op        = proto->last_lop_op;
+    parser->lex_state  = proto->lex_state;
+    parser->rsfp       = fp_dup(proto->rsfp, '<', param);
+    /* rsfp_filters entries have fake IoDIRP() */
+    parser->rsfp_filters= av_dup_inc(proto->rsfp_filters, param);
+    parser->in_my      = proto->in_my;
+    parser->in_my_stash        = hv_dup(proto->in_my_stash, param);
+    parser->error_count        = proto->error_count;
+
 
     parser->linestr    = sv_dup_inc(proto->linestr, param);
 
     {
-       char *ols = SvPVX(proto->linestr);
-       char *ls  = SvPVX(parser->linestr);
+       char * const ols = SvPVX(proto->linestr);
+       char * const ls  = SvPVX(parser->linestr);
 
        parser->bufptr      = ls + (proto->bufptr >= ols ?
                                    proto->bufptr -  ols : 0);
@@ -9598,6 +9787,9 @@ Perl_parser_dup(pTHX_ const yy_parser *proto, CLONE_PARAMS* param)
        parser->bufend      = ls + SvCUR(parser->linestr);
     }
 
+    Copy(proto->tokenbuf, parser->tokenbuf, 256, char);
+
+
 #ifdef PERL_MAD
     parser->endwhite   = proto->endwhite;
     parser->faketokens = proto->faketokens;
@@ -9716,10 +9908,13 @@ Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS* param)
        nmg->mg_private = mg->mg_private;
        nmg->mg_type    = mg->mg_type;
        nmg->mg_flags   = mg->mg_flags;
+       /* FIXME for plugins
        if (mg->mg_type == PERL_MAGIC_qr) {
            nmg->mg_obj = (SV*)CALLREGDUPE((REGEXP*)mg->mg_obj, param);
        }
-       else if(mg->mg_type == PERL_MAGIC_backref) {
+       else
+       */
+       if(mg->mg_type == PERL_MAGIC_backref) {
            /* The backref AV has its reference count deliberately bumped by
               1.  */
            nmg->mg_obj = SvREFCNT_inc(av_dup_inc((AV*) mg->mg_obj, param));
@@ -9943,10 +10138,7 @@ Perl_rvpv_dup(pTHX_ SV *dstr, const SV *sstr, CLONE_PARAMS* param)
     }
     else {
        /* Copy the NULL */
-       if (SvTYPE(dstr) == SVt_RV)
-           SvRV_set(dstr, NULL);
-       else
-           SvPV_set(dstr, NULL);
+       SvPV_set(dstr, NULL);
     }
 }
 
@@ -9958,8 +10150,14 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
     dVAR;
     SV *dstr;
 
-    if (!sstr || SvTYPE(sstr) == SVTYPEMASK)
+    if (!sstr)
+       return NULL;
+    if (SvTYPE(sstr) == SVTYPEMASK) {
+#ifdef DEBUG_LEAKING_SCALARS_ABORT
+       abort();
+#endif
        return NULL;
+    }
     /* look for it in the table first */
     dstr = (SV*)ptr_table_fetch(PL_ptr_table, sstr);
     if (dstr)
@@ -9969,10 +10167,10 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
         /** We are joining here so we don't want do clone
            something that is bad **/
        if (SvTYPE(sstr) == SVt_PVHV) {
-           const char * const hvname = HvNAME_get(sstr);
+           const HEK * const hvname = HvNAME_HEK(sstr);
            if (hvname)
                /** don't clone stashes if they already exist **/
-               return (SV*)gv_stashpv(hvname,0);
+               return (SV*)gv_stashpvn(HEK_KEY(hvname), HEK_LEN(hvname), 0);
         }
     }
 
@@ -10002,8 +10200,7 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
 
     /* don't clone objects whose class has asked us not to */
     if (SvOBJECT(sstr) && ! (SvFLAGS(SvSTASH(sstr)) & SVphv_CLONEABLE)) {
-       SvFLAGS(dstr) &= ~SVTYPEMASK;
-       SvOBJECT_off(dstr);
+       SvFLAGS(dstr) = 0;
        return dstr;
     }
 
@@ -10013,16 +10210,16 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
        break;
     case SVt_IV:
        SvANY(dstr)     = (XPVIV*)((char*)&(dstr->sv_u.svu_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
-       SvIV_set(dstr, SvIVX(sstr));
+       if(SvROK(sstr)) {
+           Perl_rvpv_dup(aTHX_ dstr, sstr, param);
+       } else {
+           SvIV_set(dstr, SvIVX(sstr));
+       }
        break;
     case SVt_NV:
        SvANY(dstr)     = new_XNV();
        SvNV_set(dstr, SvNVX(sstr));
        break;
-    case SVt_RV:
-       SvANY(dstr)     = &(dstr->sv_u.svu_rv);
-       Perl_rvpv_dup(aTHX_ dstr, sstr, param);
-       break;
        /* case SVt_BIND: */
     default:
        {
@@ -10047,6 +10244,7 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
            case SVt_PVAV:
            case SVt_PVCV:
            case SVt_PVLV:
+           case SVt_REGEXP:
            case SVt_PVMG:
            case SVt_PVNV:
            case SVt_PVIV:
@@ -10101,6 +10299,10 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                break;
            case SVt_PVMG:
                break;
+           case SVt_REGEXP:
+               /* FIXME for plugins */
+               re_dup_guts((REGEXP*) sstr, (REGEXP*) dstr, param);
+               break;
            case SVt_PVLV:
                /* XXX LvTARGOFF sometimes holds PMOP* when DEBUGGING */
                if (LvTYPE(dstr) == 't') /* for tie: unrefcnted fake (SV**) */
@@ -10130,7 +10332,7 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                    IoOFP(dstr) = IoIFP(dstr);
                else
                    IoOFP(dstr) = fp_dup(IoOFP(dstr), IoTYPE(dstr), param);
-               /* PL_rsfp_filters entries have fake IoDIRP() */
+               /* PL_parser->rsfp_filters entries have fake IoDIRP() */
                if(IoFLAGS(dstr) & IOf_FAKE_DIRP) {
                    /* I have no idea why fake dirp (rsfps)
                       should be treated differently but otherwise
@@ -10443,9 +10645,9 @@ ANY *
 Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
 {
     dVAR;
-    ANY * const ss     = proto_perl->Tsavestack;
-    const I32 max      = proto_perl->Tsavestack_max;
-    I32 ix             = proto_perl->Tsavestack_ix;
+    ANY * const ss     = proto_perl->Isavestack;
+    const I32 max      = proto_perl->Isavestack_max;
+    I32 ix             = proto_perl->Isavestack_ix;
     ANY *nss;
     SV *sv;
     GV *gv;
@@ -10769,7 +10971,7 @@ do_mark_cloneable_stash(pTHX_ SV *sv)
            ENTER;
            SAVETMPS;
            PUSHMARK(SP);
-           XPUSHs(sv_2mortal(newSVhek(hvname)));
+           mXPUSHs(newSVhek(hvname));
            PUTBACK;
            call_sv((SV*)GvCV(cloner), G_SCALAR);
            SPAGAIN;
@@ -10881,6 +11083,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_savestack_ix = 0;
     PL_savestack_max = -1;
     PL_sig_pending = 0;
+    PL_parser = NULL;
     Zero(&PL_debug_pad, 1, struct perl_debug_pad);
 #  else        /* !DEBUGGING */
     Zero(my_perl, 1, PerlInterpreter);
@@ -10915,6 +11118,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_savestack_ix = 0;
     PL_savestack_max = -1;
     PL_sig_pending = 0;
+    PL_parser = NULL;
     Zero(&PL_debug_pad, 1, struct perl_debug_pad);
 #    else      /* !DEBUGGING */
     Zero(my_perl, 1, PerlInterpreter);
@@ -11001,7 +11205,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        PL_compiling.cop_hints_hash->refcounted_he_refcnt++;
        HINTS_REFCNT_UNLOCK;
     }
-    PL_curcop          = (COP*)any_dup(proto_perl->Tcurcop, proto_perl);
+    PL_curcop          = (COP*)any_dup(proto_perl->Icurcop, proto_perl);
 #ifdef PERL_DEBUG_READONLY_OPS
     PL_slabs = NULL;
     PL_slab_count = 0;
@@ -11034,7 +11238,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_patchlevel      = sv_dup_inc(proto_perl->Ipatchlevel, param);
     PL_localpatches    = proto_perl->Ilocalpatches;
     PL_splitstr                = proto_perl->Isplitstr;
-    PL_preprocess      = proto_perl->Ipreprocess;
     PL_minus_n         = proto_perl->Iminus_n;
     PL_minus_p         = proto_perl->Iminus_p;
     PL_minus_l         = proto_perl->Iminus_l;
@@ -11077,26 +11280,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_regmatch_slab   = NULL;
     
     /* Clone the regex array */
-    PL_regex_padav = newAV();
-    {
-       const I32 len = av_len((AV*)proto_perl->Iregex_padav);
-       SV* const * const regexen = AvARRAY((AV*)proto_perl->Iregex_padav);
-       IV i;
-       av_push(PL_regex_padav, sv_dup_inc_NN(regexen[0],param));
-       for(i = 1; i <= len; i++) {
-           const SV * const regex = regexen[i];
-           SV * const sv =
-               SvREPADTMP(regex)
-                   ? sv_dup_inc(regex, param)
-                   : SvREFCNT_inc(
-                       newSViv(PTR2IV(CALLREGDUPE(
-                               INT2PTR(REGEXP *, SvIVX(regex)), param))))
-               ;
-           if (SvFLAGS(regex) & SVf_BREAK)
-               SvFLAGS(sv) |= SVf_BREAK; /* unrefcnted PL_curpm */
-           av_push(PL_regex_padav, sv);
-       }
-    }
+    /* 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 */
@@ -11120,13 +11308,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_DBsingle                = sv_dup(proto_perl->IDBsingle, param);
     PL_DBtrace         = sv_dup(proto_perl->IDBtrace, param);
     PL_DBsignal                = sv_dup(proto_perl->IDBsignal, param);
-    PL_DBassertion      = sv_dup(proto_perl->IDBassertion, param);
-    PL_lineary         = av_dup(proto_perl->Ilineary, param);
     PL_dbargs          = av_dup(proto_perl->Idbargs, param);
 
     /* symbol tables */
-    PL_defstash                = hv_dup_inc(proto_perl->Tdefstash, param);
-    PL_curstash                = hv_dup(proto_perl->Tcurstash, param);
+    PL_defstash                = hv_dup_inc(proto_perl->Idefstash, param);
+    PL_curstash                = hv_dup(proto_perl->Icurstash, param);
     PL_debstash                = hv_dup(proto_perl->Idebstash, param);
     PL_globalstash     = hv_dup(proto_perl->Iglobalstash, param);
     PL_curstname       = sv_dup_inc(proto_perl->Icurstname, param);
@@ -11142,7 +11328,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_sub_generation  = proto_perl->Isub_generation;
     PL_isarev          = hv_dup_inc(proto_perl->Iisarev, param);
-    PL_delayedisa      = hv_dup_inc(proto_perl->Tdelayedisa, param);
 
     /* funky return mechanisms */
     PL_forkprocess     = proto_perl->Iforkprocess;
@@ -11212,9 +11397,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_custom_op_descs  = hv_dup_inc(proto_perl->Icustom_op_descs,param);
 
     PL_profiledata     = NULL;
-    PL_rsfp            = fp_dup(proto_perl->Irsfp, '<', param);
-    /* PL_rsfp_filters entries have fake IoDIRP() */
-    PL_rsfp_filters    = av_dup_inc(proto_perl->Irsfp_filters, param);
 
     PL_compcv                  = cv_dup(proto_perl->Icompcv, param);
 
@@ -11248,25 +11430,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_runops          = proto_perl->Irunops;
 
-    Copy(proto_perl->Itokenbuf, PL_tokenbuf, 256, char);
-
-#ifdef CSH
-    PL_cshlen          = proto_perl->Icshlen;
-    PL_cshname         = proto_perl->Icshname; /* XXX never deallocated */
-#endif
-
     PL_parser          = parser_dup(proto_perl->Iparser, param);
 
-    PL_lex_state       = proto_perl->Ilex_state;
-
-    PL_multi_end       = proto_perl->Imulti_end;
-
-    PL_error_count     = proto_perl->Ierror_count;
     PL_subline         = proto_perl->Isubline;
     PL_subname         = sv_dup_inc(proto_perl->Isubname, param);
 
-    PL_in_my           = proto_perl->Iin_my;
-    PL_in_my_stash     = hv_dup(proto_perl->Iin_my_stash, param);
 #ifdef FCRYPT
     PL_cryptseen       = proto_perl->Icryptseen;
 #endif
@@ -11338,9 +11506,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_lockhook                = proto_perl->Ilockhook;
     PL_unlockhook      = proto_perl->Iunlockhook;
     PL_threadhook      = proto_perl->Ithreadhook;
-
-    PL_runops_std      = proto_perl->Irunops_std;
-    PL_runops_dbg      = proto_perl->Irunops_dbg;
+    PL_destroyhook     = proto_perl->Idestroyhook;
 
 #ifdef THREADS_HAVE_PIDS
     PL_ppid            = proto_perl->Ippid;
@@ -11377,54 +11543,54 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        PL_psig_name    = (SV**)NULL;
     }
 
-    /* thrdvar.h stuff */
+    /* intrpvar.h stuff */
 
     if (flags & CLONEf_COPY_STACKS) {
        /* next allocation will be PL_tmps_stack[PL_tmps_ix+1] */
-       PL_tmps_ix              = proto_perl->Ttmps_ix;
-       PL_tmps_max             = proto_perl->Ttmps_max;
-       PL_tmps_floor           = proto_perl->Ttmps_floor;
+       PL_tmps_ix              = proto_perl->Itmps_ix;
+       PL_tmps_max             = proto_perl->Itmps_max;
+       PL_tmps_floor           = proto_perl->Itmps_floor;
        Newxz(PL_tmps_stack, PL_tmps_max, SV*);
        i = 0;
        while (i <= PL_tmps_ix) {
-           PL_tmps_stack[i]    = sv_dup_inc(proto_perl->Ttmps_stack[i], param);
+           PL_tmps_stack[i]    = sv_dup_inc(proto_perl->Itmps_stack[i], param);
            ++i;
        }
 
        /* next PUSHMARK() sets *(PL_markstack_ptr+1) */
-       i = proto_perl->Tmarkstack_max - proto_perl->Tmarkstack;
+       i = proto_perl->Imarkstack_max - proto_perl->Imarkstack;
        Newxz(PL_markstack, i, I32);
-       PL_markstack_max        = PL_markstack + (proto_perl->Tmarkstack_max
-                                                 - proto_perl->Tmarkstack);
-       PL_markstack_ptr        = PL_markstack + (proto_perl->Tmarkstack_ptr
-                                                 - proto_perl->Tmarkstack);
-       Copy(proto_perl->Tmarkstack, PL_markstack,
+       PL_markstack_max        = PL_markstack + (proto_perl->Imarkstack_max
+                                                 - proto_perl->Imarkstack);
+       PL_markstack_ptr        = PL_markstack + (proto_perl->Imarkstack_ptr
+                                                 - proto_perl->Imarkstack);
+       Copy(proto_perl->Imarkstack, PL_markstack,
             PL_markstack_ptr - PL_markstack + 1, I32);
 
        /* next push_scope()/ENTER sets PL_scopestack[PL_scopestack_ix]
         * NOTE: unlike the others! */
-       PL_scopestack_ix        = proto_perl->Tscopestack_ix;
-       PL_scopestack_max       = proto_perl->Tscopestack_max;
+       PL_scopestack_ix        = proto_perl->Iscopestack_ix;
+       PL_scopestack_max       = proto_perl->Iscopestack_max;
        Newxz(PL_scopestack, PL_scopestack_max, I32);
-       Copy(proto_perl->Tscopestack, PL_scopestack, PL_scopestack_ix, I32);
+       Copy(proto_perl->Iscopestack, PL_scopestack, PL_scopestack_ix, I32);
 
        /* NOTE: si_dup() looks at PL_markstack */
-       PL_curstackinfo         = si_dup(proto_perl->Tcurstackinfo, param);
+       PL_curstackinfo         = si_dup(proto_perl->Icurstackinfo, param);
 
        /* PL_curstack          = PL_curstackinfo->si_stack; */
-       PL_curstack             = av_dup(proto_perl->Tcurstack, param);
-       PL_mainstack            = av_dup(proto_perl->Tmainstack, param);
+       PL_curstack             = av_dup(proto_perl->Icurstack, param);
+       PL_mainstack            = av_dup(proto_perl->Imainstack, param);
 
        /* next PUSHs() etc. set *(PL_stack_sp+1) */
        PL_stack_base           = AvARRAY(PL_curstack);
-       PL_stack_sp             = PL_stack_base + (proto_perl->Tstack_sp
-                                                  - proto_perl->Tstack_base);
+       PL_stack_sp             = PL_stack_base + (proto_perl->Istack_sp
+                                                  - 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->Tsavestack_ix;
-       PL_savestack_max        = proto_perl->Tsavestack_max;
+       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);
     }
@@ -11437,9 +11603,9 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
         * non-refcount means (eg a temp in @_); otherwise they will be
         * orphaned
         */
-       for (i = 0; i<= proto_perl->Ttmps_ix; i++) {
+       for (i = 0; i<= proto_perl->Itmps_ix; i++) {
            SV * const nsv = (SV*)ptr_table_fetch(PL_ptr_table,
-                   proto_perl->Ttmps_stack[i]);
+                   proto_perl->Itmps_stack[i]);
            if (nsv && !SvREFCNT(nsv)) {
                EXTEND_MORTAL(1);
                PL_tmps_stack[++PL_tmps_ix] = SvREFCNT_inc_simple(nsv);
@@ -11447,50 +11613,50 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        }
     }
 
-    PL_start_env       = proto_perl->Tstart_env;       /* XXXXXX */
+    PL_start_env       = proto_perl->Istart_env;       /* XXXXXX */
     PL_top_env         = &PL_start_env;
 
-    PL_op              = proto_perl->Top;
+    PL_op              = proto_perl->Iop;
 
     PL_Sv              = NULL;
     PL_Xpv             = (XPV*)NULL;
-    PL_na              = proto_perl->Tna;
+    my_perl->Ina       = proto_perl->Ina;
 
-    PL_statbuf         = proto_perl->Tstatbuf;
-    PL_statcache       = proto_perl->Tstatcache;
-    PL_statgv          = gv_dup(proto_perl->Tstatgv, param);
-    PL_statname                = sv_dup_inc(proto_perl->Tstatname, param);
+    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->Ttimesbuf;
+    PL_timesbuf                = proto_perl->Itimesbuf;
 #endif
 
-    PL_tainted         = proto_perl->Ttainted;
-    PL_curpm           = proto_perl->Tcurpm;   /* XXX No PMOP ref count */
-    PL_rs              = sv_dup_inc(proto_perl->Trs, param);
-    PL_last_in_gv      = gv_dup(proto_perl->Tlast_in_gv, param);
-    PL_ofs_sv          = sv_dup_inc(proto_perl->Tofs_sv, param);
-    PL_defoutgv                = gv_dup_inc(proto_perl->Tdefoutgv, param);
-    PL_chopset         = proto_perl->Tchopset; /* XXX never deallocated */
-    PL_toptarget       = sv_dup_inc(proto_perl->Ttoptarget, param);
-    PL_bodytarget      = sv_dup_inc(proto_perl->Tbodytarget, param);
-    PL_formtarget      = sv_dup(proto_perl->Tformtarget, param);
-
-    PL_restartop       = proto_perl->Trestartop;
-    PL_in_eval         = proto_perl->Tin_eval;
-    PL_delaymagic      = proto_perl->Tdelaymagic;
-    PL_dirty           = proto_perl->Tdirty;
-    PL_localizing      = proto_perl->Tlocalizing;
-
-    PL_errors          = sv_dup_inc(proto_perl->Terrors, param);
+    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_ofs_sv          = sv_dup_inc(proto_perl->Iofs_sv, 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_restartop       = proto_perl->Irestartop;
+    PL_in_eval         = proto_perl->Iin_eval;
+    PL_delaymagic      = proto_perl->Idelaymagic;
+    PL_dirty           = proto_perl->Idirty;
+    PL_localizing      = proto_perl->Ilocalizing;
+
+    PL_errors          = sv_dup_inc(proto_perl->Ierrors, param);
     PL_hv_fetch_ent_mh = NULL;
-    PL_modcount                = proto_perl->Tmodcount;
+    PL_modcount                = proto_perl->Imodcount;
     PL_lastgotoprobe   = NULL;
-    PL_dumpindent      = proto_perl->Tdumpindent;
+    PL_dumpindent      = proto_perl->Idumpindent;
 
-    PL_sortcop         = (OP*)any_dup(proto_perl->Tsortcop, proto_perl);
-    PL_sortstash       = hv_dup(proto_perl->Tsortstash, param);
-    PL_firstgv         = gv_dup(proto_perl->Tfirstgv, param);
-    PL_secondgv                = gv_dup(proto_perl->Tsecondgv, param);
+    PL_sortcop         = (OP*)any_dup(proto_perl->Isortcop, proto_perl);
+    PL_sortstash       = hv_dup(proto_perl->Isortstash, param);
+    PL_firstgv         = gv_dup(proto_perl->Ifirstgv, param);
+    PL_secondgv                = gv_dup(proto_perl->Isecondgv, param);
     PL_efloatbuf       = NULL;         /* reinits on demand */
     PL_efloatsize      = 0;                    /* reinits on demand */
 
@@ -11502,24 +11668,24 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_lastscream      = NULL;
 
 
-    PL_regdummy                = proto_perl->Tregdummy;
+    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->Tpeepp;
+    PL_peepp           = proto_perl->Ipeepp;
 
     PL_stashcache       = newHV();
 
     PL_watchaddr       = (char **) ptr_table_fetch(PL_ptr_table,
-                                           proto_perl->Twatchaddr);
+                                           proto_perl->Iwatchaddr);
     PL_watchok         = PL_watchaddr ? * PL_watchaddr : NULL;
     if (PL_debug && PL_watchaddr) {
        PerlIO_printf(Perl_debug_log,
          "WATCHING: %"UVxf" cloned as %"UVxf" with value %"UVxf"\n",
-         PTR2UV(proto_perl->Twatchaddr), PTR2UV(PL_watchaddr),
+         PTR2UV(proto_perl->Iwatchaddr), PTR2UV(PL_watchaddr),
          PTR2UV(PL_watchok));
     }
 
@@ -11539,7 +11705,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
            ENTER;
            SAVETMPS;
            PUSHMARK(SP);
-           XPUSHs(sv_2mortal(newSVhek(HvNAME_HEK(stash))));
+           mXPUSHs(newSVhek(HvNAME_HEK(stash)));
            PUTBACK;
            call_sv((SV*)GvCV(cloner), G_DISCARD);
            FREETMPS;
@@ -11655,8 +11821,9 @@ Perl_sv_cat_decode(pTHX_ SV *dsv, SV *encoding,
        XPUSHs(encoding);
        XPUSHs(dsv);
        XPUSHs(ssv);
-       XPUSHs(offsv = sv_2mortal(newSViv(*offset)));
-       XPUSHs(sv_2mortal(newSVpvn(tstr, tlen)));
+       offsv = newSViv(*offset);
+       mXPUSHs(offsv);
+       mXPUSHp(tstr, tlen);
        PUTBACK;
        call_method("cat_decode", G_SCALAR);
        SPAGAIN;
@@ -11710,7 +11877,7 @@ S_find_hash_subscript(pTHX_ HV *hv, SV* val)
                return NULL;
            if (HeKLEN(entry) == HEf_SVKEY)
                return sv_mortalcopy(HeKEY_sv(entry));
-           return sv_2mortal(newSVpvn(HeKEY(entry), HeKLEN(entry)));
+           return sv_2mortal(newSVhek(HeKEY_hek(entry)));
        }
     }
     return NULL;
@@ -11774,8 +11941,7 @@ S_varname(pTHX_ GV *gv, const char gvtype, PADOFFSET targ,
        }
     }
     else {
-       U32 unused;
-       CV * const cv = find_runcv(&unused);
+       CV * const cv = find_runcv(NULL);
        SV *sv;
        AV *av;
 
@@ -12065,14 +12231,27 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
 
     case OP_RV2SV:
     case OP_CUSTOM:
-    case OP_ENTERSUB:
        match = 1; /* XS or custom code could trigger random warnings */
        goto do_op;
 
+    case OP_ENTERSUB:
+    case OP_GOTO:
+       /* XXX tmp hack: these two may call an XS sub, and currently
+         XS subs don't have a SUB entry on the context stack, so CV and
+         pad determination goes wrong, and BAD things happen. So, just
+         don't try to determine the value under those circumstances.
+         Need a better fix at dome point. DAPM 11/2007 */
+       break;
+
+    case OP_POS:
+       /* def-ness of rval pos() is independent of the def-ness of its arg */
+       if ( !(obase->op_flags & OPf_MOD))
+           break;
+
     case OP_SCHOMP:
     case OP_CHOMP:
        if (SvROK(PL_rs) && uninit_sv == SvRV(PL_rs))
-           return sv_2mortal(newSVpvs("${$/}"));
+           return newSVpvs_flags("${$/}", SVs_TEMP);
        /*FALLTHROUGH*/
 
     default: