This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Abstract all the accesses to cop_arybase (apart from ByteLoader)
[perl5.git] / pp_hot.c
index 7d6fdc5..8cb2364 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1,7 +1,7 @@
 /*    pp_hot.c
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -37,6 +37,7 @@
 
 PP(pp_const)
 {
+    dVAR;
     dSP;
     XPUSHs(cSVOP_sv);
     RETURN;
@@ -44,6 +45,7 @@ PP(pp_const)
 
 PP(pp_nextstate)
 {
+    dVAR;
     PL_curcop = (COP*)PL_op;
     TAINT_NOT;         /* Each statement is presumed innocent */
     PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;
@@ -53,35 +55,39 @@ PP(pp_nextstate)
 
 PP(pp_gvsv)
 {
+    dVAR;
     dSP;
     EXTEND(SP,1);
     if (PL_op->op_private & OPpLVAL_INTRO)
        PUSHs(save_scalar(cGVOP_gv));
     else
-       PUSHs(GvSV(cGVOP_gv));
+       PUSHs(GvSVn(cGVOP_gv));
     RETURN;
 }
 
 PP(pp_null)
 {
+    dVAR;
     return NORMAL;
 }
 
 PP(pp_setstate)
 {
+    dVAR;
     PL_curcop = (COP*)PL_op;
     return NORMAL;
 }
 
 PP(pp_pushmark)
 {
+    dVAR;
     PUSHMARK(PL_stack_sp);
     return NORMAL;
 }
 
 PP(pp_stringify)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     sv_copypv(TARG,TOPs);
     SETTARG;
     RETURN;
@@ -89,32 +95,86 @@ PP(pp_stringify)
 
 PP(pp_gv)
 {
-    dSP;
+    dVAR; dSP;
     XPUSHs((SV*)cGVOP_gv);
     RETURN;
 }
 
 PP(pp_and)
 {
-    dSP;
+    dVAR; dSP;
     if (!SvTRUE(TOPs))
        RETURN;
     else {
-       --SP;
+        if (PL_op->op_type == OP_AND)
+           --SP;
        RETURNOP(cLOGOP->op_other);
     }
 }
 
 PP(pp_sassign)
 {
-    dSP; dPOPTOPssrl;
+    dVAR; dSP; dPOPTOPssrl;
 
     if (PL_op->op_private & OPpASSIGN_BACKWARDS) {
-       SV *temp;
-       temp = left; left = right; right = temp;
+       SV * const temp = left;
+       left = right; right = temp;
     }
     if (PL_tainting && PL_tainted && !SvTAINTED(left))
        TAINT_NOT;
+    if (PL_op->op_private & OPpASSIGN_CV_TO_GV) {
+       SV * const cv = SvRV(left);
+       const U32 cv_type = SvTYPE(cv);
+       const U32 gv_type = SvTYPE(right);
+       const bool got_coderef = cv_type == SVt_PVCV || cv_type == SVt_PVFM;
+
+       if (!got_coderef) {
+           assert(SvROK(cv));
+       }
+
+       /* Can do the optimisation if right (LVAUE) is not a typeglob,
+          left (RVALUE) is a reference to something, and we're in void
+          context. */
+       if (!got_coderef && gv_type != SVt_PVGV && GIMME_V == G_VOID) {
+           /* Is the target symbol table currently empty?  */
+           GV * const gv = gv_fetchsv(right, GV_NOINIT, SVt_PVGV);
+           if (SvTYPE(gv) != SVt_PVGV && !SvOK(gv)) {
+               /* Good. Create a new proxy constant subroutine in the target.
+                  The gv becomes a(nother) reference to the constant.  */
+               SV *const value = SvRV(cv);
+
+               SvUPGRADE((SV *)gv, SVt_RV);
+               SvROK_on(gv);
+               SvRV_set(gv, value);
+               SvREFCNT_inc_simple_void(value);
+               SETs(right);
+               RETURN;
+           }
+       }
+
+       /* Need to fix things up.  */
+       if (gv_type != SVt_PVGV) {
+           /* Need to fix GV.  */
+           right = (SV*)gv_fetchsv(right, GV_ADD, SVt_PVGV);
+       }
+
+       if (!got_coderef) {
+           /* We've been returned a constant rather than a full subroutine,
+              but they expect a subroutine reference to apply.  */
+           ENTER;
+           SvREFCNT_inc_void(SvRV(cv));
+           /* newCONSTSUB takes a reference count on the passed in SV
+              from us.  We set the name to NULL, otherwise we get into
+              all sorts of fun as the reference to our new sub is
+              donated to the GV that we're about to assign to.
+           */
+           SvRV_set(left, (SV *)newCONSTSUB(GvSTASH(right), NULL,
+                                                SvRV(cv)));
+           SvREFCNT_dec(cv);
+           LEAVE;
+       }
+
+    }
     SvSetMagicSV(right, left);
     SETs(right);
     RETURN;
@@ -122,7 +182,7 @@ PP(pp_sassign)
 
 PP(pp_cond_expr)
 {
-    dSP;
+    dVAR; dSP;
     if (SvTRUEx(POPs))
        RETURNOP(cLOGOP->op_other);
     else
@@ -131,6 +191,7 @@ PP(pp_cond_expr)
 
 PP(pp_unstack)
 {
+    dVAR;
     I32 oldsave;
     TAINT_NOT;         /* Each statement is presumed innocent */
     PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;
@@ -142,24 +203,27 @@ PP(pp_unstack)
 
 PP(pp_concat)
 {
-  dSP; dATARGET; tryAMAGICbin(concat,opASSIGN);
+  dVAR; dSP; dATARGET; tryAMAGICbin(concat,opASSIGN);
   {
     dPOPTOPssrl;
     bool lbyte;
     STRLEN rlen;
-    const char *rpv = SvPV(right, rlen);       /* mg_get(right) happens here */
-    const bool rbyte = !DO_UTF8(right);
+    const char *rpv = NULL;
+    bool rbyte = FALSE;
     bool rcopied = FALSE;
 
     if (TARG == right && right != left) {
+       /* mg_get(right) may happen here ... */
+       rpv = SvPV_const(right, rlen);
+       rbyte = !DO_UTF8(right);
        right = sv_2mortal(newSVpvn(rpv, rlen));
-       rpv = SvPV(right, rlen);        /* no point setting UTF-8 here */
+       rpv = SvPV_const(right, rlen);  /* no point setting UTF-8 here */
        rcopied = TRUE;
     }
 
     if (TARG != left) {
         STRLEN llen;
-        const char* const lpv = SvPV(left, llen);      /* mg_get(left) may happen here */
+        const char* const lpv = SvPV_const(left, llen);        /* mg_get(left) may happen here */
        lbyte = !DO_UTF8(left);
        sv_setpvn(TARG, lpv, llen);
        if (!lbyte)
@@ -169,16 +233,23 @@ PP(pp_concat)
     }
     else { /* TARG == left */
         STRLEN llen;
-       if (SvGMAGICAL(left))
-           mg_get(left);               /* or mg_get(left) may happen here */
-       if (!SvOK(TARG))
+       SvGETMAGIC(left);               /* or mg_get(left) may happen here */
+       if (!SvOK(TARG)) {
+           if (left == right && ckWARN(WARN_UNINITIALIZED))
+               report_uninit(right);
            sv_setpvn(left, "", 0);
-       (void)SvPV_nomg(left, llen);    /* Needed to set UTF8 flag */
+       }
+       (void)SvPV_nomg_const(left, llen);    /* Needed to set UTF8 flag */
        lbyte = !DO_UTF8(left);
        if (IN_BYTES)
            SvUTF8_off(TARG);
     }
 
+    /* or mg_get(right) may happen here */
+    if (!rcopied) {
+       rpv = SvPV_const(right, rlen);
+       rbyte = !DO_UTF8(right);
+    }
     if (lbyte != rbyte) {
        if (lbyte)
            sv_utf8_upgrade_nomg(TARG);
@@ -186,7 +257,7 @@ PP(pp_concat)
            if (!rcopied)
                right = sv_2mortal(newSVpvn(rpv, rlen));
            sv_utf8_upgrade_nomg(right);
-           rpv = SvPV(right, rlen);
+           rpv = SvPV_const(right, rlen);
        }
     }
     sv_catpvn_nomg(TARG, rpv, rlen);
@@ -198,7 +269,7 @@ PP(pp_concat)
 
 PP(pp_padsv)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     XPUSHs(TARG);
     if (PL_op->op_flags & OPf_MOD) {
        if (PL_op->op_private & OPpLVAL_INTRO)
@@ -214,6 +285,7 @@ PP(pp_padsv)
 
 PP(pp_readline)
 {
+    dVAR;
     tryAMAGICunTARGET(iter, 0);
     PL_last_in_gv = (GV*)(*PL_stack_sp--);
     if (SvTYPE(PL_last_in_gv) != SVt_PVGV) {
@@ -232,7 +304,7 @@ PP(pp_readline)
 
 PP(pp_eq)
 {
-    dSP; tryAMAGICbinSET(eq,0);
+    dVAR; dSP; tryAMAGICbinSET(eq,0);
 #ifndef NV_PRESERVES_UV
     if (SvROK(TOPs) && !SvAMAGIC(TOPs) && SvROK(TOPm1s) && !SvAMAGIC(TOPm1s)) {
         SP--;
@@ -248,8 +320,8 @@ PP(pp_eq)
           right argument if we know the left is integer.  */
       SvIV_please(TOPm1s);
        if (SvIOK(TOPm1s)) {
-           bool auvok = SvUOK(TOPm1s);
-           bool buvok = SvUOK(TOPs);
+           const bool auvok = SvUOK(TOPm1s);
+           const bool buvok = SvUOK(TOPs);
        
            if (auvok == buvok) { /* ## IV == IV or UV == UV ## */
                 /* Casting IV to UV before comparison isn't going to matter
@@ -258,8 +330,8 @@ PP(pp_eq)
                    differ from normal zero. As I understand it. (Need to
                    check - is negative zero implementation defined behaviour
                    anyway?). NWC  */
-               UV buv = SvUVX(POPs);
-               UV auv = SvUVX(TOPs);
+               const UV buv = SvUVX(POPs);
+               const UV auv = SvUVX(TOPs);
                
                SETs(boolSV(auv == buv));
                RETURN;
@@ -278,28 +350,34 @@ PP(pp_eq)
                     ivp = *--SP;
                 }
                 iv = SvIVX(ivp);
-                if (iv < 0) {
+               if (iv < 0)
                     /* As uv is a UV, it's >0, so it cannot be == */
                     SETs(&PL_sv_no);
-                    RETURN;
-                }
-               /* we know iv is >= 0 */
-               SETs(boolSV((UV)iv == SvUVX(uvp)));
+               else
+                   /* we know iv is >= 0 */
+                   SETs(boolSV((UV)iv == SvUVX(uvp)));
                RETURN;
            }
        }
     }
 #endif
     {
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+      dPOPTOPnnrl;
+      if (Perl_isnan(left) || Perl_isnan(right))
+         RETSETNO;
+      SETs(boolSV(left == right));
+#else
       dPOPnv;
       SETs(boolSV(TOPn == value));
+#endif
       RETURN;
     }
 }
 
 PP(pp_preinc)
 {
-    dSP;
+    dVAR; dSP;
     if (SvTYPE(TOPs) >= SVt_PVGV && SvTYPE(TOPs) != SVt_PVLV)
        DIE(aTHX_ PL_no_modify);
     if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)
@@ -316,53 +394,75 @@ PP(pp_preinc)
 
 PP(pp_or)
 {
-    dSP;
+    dVAR; dSP;
     if (SvTRUE(TOPs))
        RETURN;
     else {
-       --SP;
+       if (PL_op->op_type == OP_OR)
+            --SP;
        RETURNOP(cLOGOP->op_other);
     }
 }
 
-PP(pp_dor)
+PP(pp_defined)
 {
-    /* Most of this is lifted straight from pp_defined */
-    dSP;
-    register SV* const sv = TOPs;
-
-    if (!sv || !SvANY(sv)) {
-       --SP;
-       RETURNOP(cLOGOP->op_other);
-    }
-    
+    dVAR; dSP;
+    register SV* sv;
+    bool defined;
+    const int op_type = PL_op->op_type;
+    const int is_dor = (op_type == OP_DOR || op_type == OP_DORASSIGN);
+
+    if (is_dor) {
+        sv = TOPs;
+        if (!sv || !SvANY(sv)) {
+           if (op_type == OP_DOR)
+               --SP;
+            RETURNOP(cLOGOP->op_other);
+        }
+    } else if (op_type == OP_DEFINED) {
+        sv = POPs;
+        if (!sv || !SvANY(sv))
+            RETPUSHNO;
+    } else
+        DIE(aTHX_ "panic:  Invalid op (%s) in pp_defined()", OP_NAME(PL_op));
+
+    defined = FALSE;
     switch (SvTYPE(sv)) {
     case SVt_PVAV:
        if (AvMAX(sv) >= 0 || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
-           RETURN;
+           defined = TRUE;
        break;
     case SVt_PVHV:
        if (HvARRAY(sv) || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
-           RETURN;
+           defined = TRUE;
        break;
     case SVt_PVCV:
        if (CvROOT(sv) || CvXSUB(sv))
-           RETURN;
+           defined = TRUE;
        break;
     default:
-       if (SvGMAGICAL(sv))
-           mg_get(sv);
+       SvGETMAGIC(sv);
        if (SvOK(sv))
-           RETURN;
+           defined = TRUE;
+       break;
     }
-    
-    --SP;
-    RETURNOP(cLOGOP->op_other);
+
+    if (is_dor) {
+        if(defined) 
+            RETURN; 
+        if(op_type == OP_DOR)
+            --SP;
+        RETURNOP(cLOGOP->op_other);
+    }
+    /* assuming OP_DEFINED */
+    if(defined) 
+        RETPUSHYES;
+    RETPUSHNO;
 }
 
 PP(pp_add)
 {
-    dSP; dATARGET; bool useleft; tryAMAGICbin(add,opASSIGN);
+    dVAR; dSP; dATARGET; bool useleft; tryAMAGICbin(add,opASSIGN);
     useleft = USE_LEFT(TOPm1s);
 #ifdef PERL_PRESERVE_IVUV
     /* We must see if we can perform the addition with integers if possible,
@@ -524,11 +624,11 @@ PP(pp_add)
 
 PP(pp_aelemfast)
 {
-    dSP;
-    AV *av = PL_op->op_flags & OPf_SPECIAL ?
+    dVAR; dSP;
+    AV * const av = PL_op->op_flags & OPf_SPECIAL ?
                (AV*)PAD_SV(PL_op->op_targ) : GvAV(cGVOP_gv);
     const U32 lval = PL_op->op_flags & OPf_MOD;
-    SV** svp = av_fetch(av, PL_op->op_private, lval);
+    SV** const svp = av_fetch(av, PL_op->op_private, lval);
     SV *sv = (svp ? *svp : &PL_sv_undef);
     EXTEND(SP, 1);
     if (!lval && SvGMAGICAL(sv))       /* see note in pp_helem() */
@@ -539,7 +639,7 @@ PP(pp_aelemfast)
 
 PP(pp_join)
 {
-    dSP; dMARK; dTARGET;
+    dVAR; dSP; dMARK; dTARGET;
     MARK++;
     do_join(TARG, *MARK, MARK, SP);
     SP = MARK;
@@ -549,13 +649,13 @@ PP(pp_join)
 
 PP(pp_pushre)
 {
-    dSP;
+    dVAR; dSP;
 #ifdef DEBUGGING
     /*
      * We ass_u_me that LvTARGOFF() comes first, and that two STRLENs
      * will be enough to hold an OP*.
      */
-    SV* sv = sv_newmortal();
+    SV* const sv = sv_newmortal();
     sv_upgrade(sv, SVt_PVLV);
     LvTYPE(sv) = '/';
     Copy(&PL_op, &LvTARGOFF(sv), 1, OP*);
@@ -571,15 +671,10 @@ PP(pp_pushre)
 PP(pp_print)
 {
     dVAR; dSP; dMARK; dORIGMARK;
-    GV *gv;
     IO *io;
     register PerlIO *fp;
     MAGIC *mg;
-
-    if (PL_op->op_flags & OPf_STACKED)
-       gv = (GV*)*++MARK;
-    else
-       gv = PL_defoutgv;
+    GV * const gv = (PL_op->op_flags & OPf_STACKED) ? (GV*)*++MARK : PL_defoutgv;
 
     if (gv && (io = GvIO(gv))
        && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
@@ -660,18 +755,18 @@ PP(pp_print)
        }
     }
     SP = ORIGMARK;
-    PUSHs(&PL_sv_yes);
+    XPUSHs(&PL_sv_yes);
     RETURN;
 
   just_say_no:
     SP = ORIGMARK;
-    PUSHs(&PL_sv_undef);
+    XPUSHs(&PL_sv_undef);
     RETURN;
 }
 
 PP(pp_rv2av)
 {
-    dSP; dTOPss;
+    dVAR; dSP; dTOPss;
     AV *av;
 
     if (SvROK(sv)) {
@@ -734,10 +829,10 @@ PP(pp_rv2av)
                if ((PL_op->op_flags & OPf_SPECIAL) &&
                    !(PL_op->op_flags & OPf_MOD))
                {
-                   gv = (GV*)gv_fetchsv(sv, FALSE, SVt_PVAV);
+                   gv = (GV*)gv_fetchsv(sv, 0, SVt_PVAV);
                    if (!gv
                        && (!is_gv_magical_sv(sv,0)
-                           || !(gv = (GV*)gv_fetchsv(sv, TRUE, SVt_PVAV))))
+                           || !(gv = (GV*)gv_fetchsv(sv, GV_ADD, SVt_PVAV))))
                    {
                        RETSETUNDEF;
                    }
@@ -745,7 +840,7 @@ PP(pp_rv2av)
                else {
                    if (PL_op->op_private & HINT_STRICT_REFS)
                        DIE(aTHX_ PL_no_symref_sv, sv, "an ARRAY");
-                   gv = (GV*)gv_fetchsv(sv, TRUE, SVt_PVAV);
+                   gv = (GV*)gv_fetchsv(sv, GV_ADD, SVt_PVAV);
                }
            }
            else {
@@ -775,7 +870,7 @@ PP(pp_rv2av)
        if (SvRMAGICAL(av)) {
            U32 i;
            for (i=0; i < (U32)maxarg; i++) {
-               SV **svp = av_fetch(av, i, FALSE);
+               SV ** const svp = av_fetch(av, i, FALSE);
                /* See note in pp_helem, and bug id #27839 */
                SP[i+1] = svp
                    ? SvGMAGICAL(*svp) ? sv_mortalcopy(*svp) : *svp
@@ -797,7 +892,7 @@ PP(pp_rv2av)
 
 PP(pp_rv2hv)
 {
-    dSP; dTOPss;
+    dVAR; dSP; dTOPss;
     HV *hv;
     const I32 gimme = GIMME_V;
     static const char return_hash_to_lvalue_scalar[] = "Can't return hash to lvalue scalar context";
@@ -861,10 +956,10 @@ PP(pp_rv2hv)
                if ((PL_op->op_flags & OPf_SPECIAL) &&
                    !(PL_op->op_flags & OPf_MOD))
                {
-                   gv = (GV*)gv_fetchsv(sv, FALSE, SVt_PVHV);
+                   gv = (GV*)gv_fetchsv(sv, 0, SVt_PVHV);
                    if (!gv
                        && (!is_gv_magical_sv(sv,0)
-                           || !(gv = (GV*)gv_fetchsv(sv, TRUE, SVt_PVHV))))
+                           || !(gv = (GV*)gv_fetchsv(sv, GV_ADD, SVt_PVHV))))
                    {
                        RETSETUNDEF;
                    }
@@ -872,7 +967,7 @@ PP(pp_rv2hv)
                else {
                    if (PL_op->op_private & HINT_STRICT_REFS)
                        DIE(aTHX_ PL_no_symref_sv, sv, "a HASH");
-                   gv = (GV*)gv_fetchsv(sv, TRUE, SVt_PVHV);
+                   gv = (GV*)gv_fetchsv(sv, GV_ADD, SVt_PVHV);
                }
            }
            else {
@@ -909,6 +1004,7 @@ PP(pp_rv2hv)
 STATIC void
 S_do_oddball(pTHX_ HV *hash, SV **relem, SV **firstrelem)
 {
+    dVAR;
     if (*relem) {
        SV *tmpstr;
         const HE *didstore;
@@ -927,7 +1023,7 @@ S_do_oddball(pTHX_ HV *hash, SV **relem, SV **firstrelem)
            Perl_warner(aTHX_ packWARN(WARN_MISC), err);
        }
 
-        tmpstr = NEWSV(29,0);
+        tmpstr = newSV(0);
         didstore = hv_store_ent(hash,*relem,tmpstr,0);
         if (SvMAGICAL(hash)) {
             if (SvSMAGICAL(tmpstr))
@@ -958,7 +1054,7 @@ PP(pp_aassign)
     I32 i;
     int magic;
     int duplicates = 0;
-    SV **firsthashrelem = 0;   /* "= 0" keeps gcc 2.95 quiet  */
+    SV **firsthashrelem = NULL;        /* "= 0" keeps gcc 2.95 quiet  */
 
 
     PL_delaymagic = DM_DELAY;          /* catch simultaneous items */
@@ -971,7 +1067,6 @@ PP(pp_aassign)
     if (PL_op->op_private & (OPpASSIGN_COMMON)) {
        EXTEND_MORTAL(lastrelem - firstrelem + 1);
        for (relem = firstrelem; relem <= lastrelem; relem++) {
-           /*SUPPRESS 560*/
            if ((sv = *relem)) {
                TAINT_NOT;      /* Each item is independent */
                *relem = sv_mortalcopy(sv);
@@ -981,8 +1076,8 @@ PP(pp_aassign)
 
     relem = firstrelem;
     lelem = firstlelem;
-    ary = Null(AV*);
-    hash = Null(HV*);
+    ary = NULL;
+    hash = NULL;
 
     while (lelem <= lastlelem) {
        TAINT_NOT;              /* Each item stands on its own, taintwise. */
@@ -1019,11 +1114,9 @@ PP(pp_aassign)
 
                while (relem < lastrelem) {     /* gobble up all the rest */
                    HE *didstore;
-                   if (*relem)
-                       sv = *(relem++);
-                   else
-                       sv = &PL_sv_no, relem++;
-                   tmpstr = NEWSV(29,0);
+                   sv = *relem ? *relem : &PL_sv_no;
+                   relem++;
+                   tmpstr = newSV(0);
                    if (*relem)
                        sv_setsv(tmpstr,*relem);        /* value */
                    *(relem++) = tmpstr;
@@ -1161,10 +1254,10 @@ PP(pp_aassign)
 
 PP(pp_qr)
 {
-    dSP;
-    register PMOP *pm = cPMOP;
-    SV *rv = sv_newmortal();
-    SV *sv = newSVrv(rv, "Regexp");
+    dVAR; dSP;
+    register PMOP * const pm = cPMOP;
+    SV * const rv = sv_newmortal();
+    SV * const sv = newSVrv(rv, "Regexp");
     if (pm->op_pmdynflags & PMdf_TAINTED)
         SvTAINTED_on(rv);
     sv_magic(sv,(SV*)ReREFCNT_inc(PM_GETRE(pm)), PERL_MAGIC_qr,0,0);
@@ -1173,15 +1266,15 @@ PP(pp_qr)
 
 PP(pp_match)
 {
-    dSP; dTARG;
+    dVAR; dSP; dTARG;
     register PMOP *pm = cPMOP;
     PMOP *dynpm = pm;
-    register char *t;
-    register char *s;
-    char *strend;
+    register const char *t;
+    register const char *s;
+    const char *strend;
     I32 global;
     I32 r_flags = REXEC_CHECKED;
-    char *truebase;                    /* Start of string  */
+    const char *truebase;                      /* Start of string  */
     register REGEXP *rx = PM_GETRE(pm);
     bool rxtainted;
     const I32 gimme = GIMME;
@@ -1201,10 +1294,10 @@ PP(pp_match)
     }
 
     PUTBACK;                           /* EVAL blocks need stack_sp. */
-    s = SvPV(TARG, len);
-    strend = s + len;
+    s = SvPV_const(TARG, len);
     if (!s)
        DIE(aTHX_ "panic: pp_match");
+    strend = s + len;
     rxtainted = ((pm->op_pmdynflags & PMdf_TAINTED) ||
                 (PL_tainted && (pm->op_pmflags & PMf_RETAINT)));
     TAINT_NOT;
@@ -1234,7 +1327,7 @@ PP(pp_match)
     if ((global = dynpm->op_pmflags & PMf_GLOBAL)) {
        rx->startp[0] = -1;
        if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) {
-           MAGIC* mg = mg_find(TARG, PERL_MAGIC_regex_global);
+           MAGIC* const mg = mg_find(TARG, PERL_MAGIC_regex_global);
            if (mg && mg->mg_len >= 0) {
                if (!(rx->reganch & ROPT_GPOS_SEEN))
                    rx->endp[0] = rx->startp[0] = mg->mg_len;
@@ -1248,7 +1341,7 @@ PP(pp_match)
        }
     }
     if ((!global && rx->nparens)
-           || SvTEMP(TARG) || PL_sawampersand)
+           || SvTEMP(TARG) || PL_sawampersand || (pm->op_pmflags & PMf_EVAL))
        r_flags |= REXEC_COPY_STR;
     if (SvSCREAM(TARG))
        r_flags |= REXEC_SCREAM;
@@ -1263,8 +1356,9 @@ play_it_again:
     }
     if (rx->reganch & RE_USE_INTUIT &&
        DO_UTF8(TARG) == ((rx->reganch & ROPT_UTF8) != 0)) {
-       PL_bostr = truebase;
-       s = CALLREG_INTUIT_START(aTHX_ rx, TARG, s, strend, r_flags, NULL);
+       /* FIXME - can PL_bostr be made const char *?  */
+       PL_bostr = (char *)truebase;
+       s = CALLREG_INTUIT_START(aTHX_ rx, TARG, (char *)s, (char *)strend, r_flags, NULL);
 
        if (!s)
            goto nope;
@@ -1276,7 +1370,7 @@ play_it_again:
             && !SvROK(TARG))   /* Cannot trust since INTUIT cannot guess ^ */
            goto yup;
     }
-    if (CALLREGEXEC(aTHX_ rx, s, strend, truebase, minmatch, TARG, NULL, r_flags))
+    if (CALLREGEXEC(aTHX_ rx, (char*)s, (char *)strend, (char*)truebase, minmatch, TARG, NULL, r_flags))
     {
        PL_curpm = pm;
        if (dynpm->op_pmflags & PMf_ONCE)
@@ -1300,7 +1394,6 @@ play_it_again:
        EXTEND_MORTAL(nparens + i);
        for (i = !i; i <= nparens; i++) {
            PUSHs(sv_newmortal());
-           /*SUPPRESS 560*/
            if ((rx->startp[i] != -1) && rx->endp[i] != -1 ) {
                const I32 len = rx->endp[i] - rx->startp[i];
                s = rx->startp[i] + truebase;
@@ -1314,12 +1407,16 @@ play_it_again:
        }
        if (global) {
            if (dynpm->op_pmflags & PMf_CONTINUE) {
-               MAGIC* mg = 0;
+               MAGIC* mg = NULL;
                if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG))
                    mg = mg_find(TARG, PERL_MAGIC_regex_global);
                if (!mg) {
-                   sv_magic(TARG, (SV*)0, PERL_MAGIC_regex_global, Nullch, 0);
-                   mg = mg_find(TARG, PERL_MAGIC_regex_global);
+#ifdef PERL_OLD_COPY_ON_WRITE
+                   if (SvIsCOW(TARG))
+                       sv_force_normal_flags(TARG, 0);
+#endif
+                   mg = sv_magicext(TARG, NULL, PERL_MAGIC_regex_global,
+                                    &PL_vtbl_mglob, NULL, 0);
                }
                if (rx->startp[0] != -1) {
                    mg->mg_len = rx->endp[0];
@@ -1342,12 +1439,18 @@ play_it_again:
     }
     else {
        if (global) {
-           MAGIC* mg = 0;
+           MAGIC* mg;
            if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG))
                mg = mg_find(TARG, PERL_MAGIC_regex_global);
+           else
+               mg = NULL;
            if (!mg) {
-               sv_magic(TARG, (SV*)0, PERL_MAGIC_regex_global, Nullch, 0);
-               mg = mg_find(TARG, PERL_MAGIC_regex_global);
+#ifdef PERL_OLD_COPY_ON_WRITE
+               if (SvIsCOW(TARG))
+                   sv_force_normal_flags(TARG, 0);
+#endif
+               mg = sv_magicext(TARG, NULL, PERL_MAGIC_regex_global,
+                                &PL_vtbl_mglob, NULL, 0);
            }
            if (rx->startp[0] != -1) {
                mg->mg_len = rx->endp[0];
@@ -1371,12 +1474,13 @@ yup:                                    /* Confirmed by INTUIT */
     if (RX_MATCH_COPIED(rx))
        Safefree(rx->subbeg);
     RX_MATCH_COPIED_off(rx);
-    rx->subbeg = Nullch;
+    rx->subbeg = NULL;
     if (global) {
-       rx->subbeg = truebase;
+       /* FIXME - should rx->subbeg be const char *?  */
+       rx->subbeg = (char *) truebase;
        rx->startp[0] = s - truebase;
        if (RX_MATCH_UTF8(rx)) {
-           char *t = (char*)utf8_hop((U8*)s, rx->minlen);
+           char * const t = (char*)utf8_hop((U8*)s, rx->minlen);
            rx->endp[0] = t - truebase;
        }
        else {
@@ -1387,7 +1491,7 @@ yup:                                      /* Confirmed by INTUIT */
     }
     if (PL_sawampersand) {
        I32 off;
-#ifdef PERL_COPY_ON_WRITE
+#ifdef PERL_OLD_COPY_ON_WRITE
        if (SvIsCOW(TARG) || (SvFLAGS(TARG) & CAN_COW_MASK) == CAN_COW_FLAGS) {
            if (DEBUG_C_TEST) {
                PerlIO_printf(Perl_debug_log,
@@ -1396,15 +1500,15 @@ yup:                                    /* Confirmed by INTUIT */
                              (int)(t-truebase));
            }
            rx->saved_copy = sv_setsv_cow(rx->saved_copy, TARG);
-           rx->subbeg = SvPVX_const(rx->saved_copy) + (t - truebase);
+           rx->subbeg = (char *) SvPVX_const(rx->saved_copy) + (t - truebase);
            assert (SvPOKp(rx->saved_copy));
        } else
 #endif
        {
 
            rx->subbeg = savepvn(t, strend - t);
-#ifdef PERL_COPY_ON_WRITE
-           rx->saved_copy = Nullsv;
+#ifdef PERL_OLD_COPY_ON_WRITE
+           rx->saved_copy = NULL;
 #endif
        }
        rx->sublen = strend - t;
@@ -1424,7 +1528,7 @@ nope:
 ret_no:
     if (global && !(dynpm->op_pmflags & PMf_CONTINUE)) {
        if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) {
-           MAGIC* mg = mg_find(TARG, PERL_MAGIC_regex_global);
+           MAGIC* const mg = mg_find(TARG, PERL_MAGIC_regex_global);
            if (mg)
                mg->mg_len = -1;
        }
@@ -1446,24 +1550,26 @@ Perl_do_readline(pTHX)
     register IO * const io = GvIO(PL_last_in_gv);
     register const I32 type = PL_op->op_type;
     const I32 gimme = GIMME_V;
-    MAGIC *mg;
 
-    if (io && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) {
-       PUSHMARK(SP);
-       XPUSHs(SvTIED_obj((SV*)io, mg));
-       PUTBACK;
-       ENTER;
-       call_method("READLINE", gimme);
-       LEAVE;
-       SPAGAIN;
-       if (gimme == G_SCALAR) {
-           SV* result = POPs;
-           SvSetSV_nosteal(TARG, result);
-           PUSHTARG;
+    if (io) {
+       MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+       if (mg) {
+           PUSHMARK(SP);
+           XPUSHs(SvTIED_obj((SV*)io, mg));
+           PUTBACK;
+           ENTER;
+           call_method("READLINE", gimme);
+           LEAVE;
+           SPAGAIN;
+           if (gimme == G_SCALAR) {
+               SV* const result = POPs;
+               SvSetSV_nosteal(TARG, result);
+               PUSHTARG;
+           }
+           RETURN;
        }
-       RETURN;
     }
-    fp = Nullfp;
+    fp = NULL;
     if (io) {
        fp = IoIFP(io);
        if (!fp) {
@@ -1472,8 +1578,8 @@ Perl_do_readline(pTHX)
                    IoLINES(io) = 0;
                    if (av_len(GvAVn(PL_last_in_gv)) < 0) {
                        IoFLAGS(io) &= ~IOf_START;
-                       do_open(PL_last_in_gv,"-",1,FALSE,O_RDONLY,0,Nullfp);
-                       sv_setpvn(GvSV(PL_last_in_gv), "-", 1);
+                       do_open(PL_last_in_gv,"-",1,FALSE,O_RDONLY,0,NULL);
+                       sv_setpvn(GvSVn(PL_last_in_gv), "-", 1);
                        SvSETMAGIC(GvSV(PL_last_in_gv));
                        fp = IoIFP(io);
                        goto have_fp;
@@ -1494,8 +1600,9 @@ Perl_do_readline(pTHX)
        }
     }
     if (!fp) {
-       if (ckWARN2(WARN_GLOB, WARN_CLOSED)
-               && (!io || !(IoFLAGS(io) & IOf_START))) {
+       if ((!io || !(IoFLAGS(io) & IOf_START))
+           && ckWARN2(WARN_GLOB, WARN_CLOSED))
+       {
            if (type == OP_GLOB)
                Perl_warner(aTHX_ packWARN(WARN_GLOB),
                            "glob failed (can't start child: %s)",
@@ -1518,6 +1625,9 @@ Perl_do_readline(pTHX)
        sv = TARG;
        if (SvROK(sv))
            sv_unref(sv);
+       else if (isGV_with_GP(sv)) {
+           SvPV_force_nolen(sv);
+       }
        SvUPGRADE(sv, SVt_PV);
        tmplen = SvLEN(sv);     /* remember if already alloced */
        if (!tmplen && !SvREADONLY(sv))
@@ -1525,14 +1635,13 @@ Perl_do_readline(pTHX)
        offset = 0;
        if (type == OP_RCATLINE && SvOK(sv)) {
            if (!SvPOK(sv)) {
-               STRLEN n_a;
-               (void)SvPV_force(sv, n_a);
+               SvPV_force_nolen(sv);
            }
            offset = SvCUR(sv);
        }
     }
     else {
-       sv = sv_2mortal(NEWSV(57, 80));
+       sv = sv_2mortal(newSV(80));
        offset = 0;
     }
 
@@ -1588,40 +1697,41 @@ Perl_do_readline(pTHX)
        SPAGAIN;
        XPUSHs(sv);
        if (type == OP_GLOB) {
-           char *tmps;
+           const char *t1;
 
            if (SvCUR(sv) > 0 && SvCUR(PL_rs) > 0) {
-               tmps = SvEND(sv) - 1;
+               char * const tmps = SvEND(sv) - 1;
                if (*tmps == *SvPVX_const(PL_rs)) {
                    *tmps = '\0';
                    SvCUR_set(sv, SvCUR(sv) - 1);
                }
            }
-           for (tmps = SvPVX(sv); *tmps; tmps++)
-               if (!isALPHA(*tmps) && !isDIGIT(*tmps) &&
-                   strchr("$&*(){}[]'\";\\|?<>~`", *tmps))
+           for (t1 = SvPVX_const(sv); *t1; t1++)
+               if (!isALPHA(*t1) && !isDIGIT(*t1) &&
+                   strchr("$&*(){}[]'\";\\|?<>~`", *t1))
                        break;
-           if (*tmps && PerlLIO_lstat(SvPVX_const(sv), &PL_statbuf) < 0) {
+           if (*t1 && PerlLIO_lstat(SvPVX_const(sv), &PL_statbuf) < 0) {
                (void)POPs;             /* Unmatched wildcard?  Chuck it... */
                continue;
            }
        } else if (SvUTF8(sv)) { /* OP_READLINE, OP_RCATLINE */
-            const U8 *s = (U8*)SvPVX(sv) + offset;
-            const STRLEN len = SvCUR(sv) - offset;
-            const U8 *f;
-            
-            if (ckWARN(WARN_UTF8) &&
-                !Perl_is_utf8_string_loc(aTHX_ s, len, &f))
-                 /* Emulate :encoding(utf8) warning in the same case. */
-                 Perl_warner(aTHX_ packWARN(WARN_UTF8),
-                             "utf8 \"\\x%02X\" does not map to Unicode",
-                             f < (U8*)SvEND(sv) ? *f : 0);
+            if (ckWARN(WARN_UTF8)) {
+               const U8 * const s = (const U8*)SvPVX_const(sv) + offset;
+               const STRLEN len = SvCUR(sv) - offset;
+               const U8 *f;
+
+               if (!is_utf8_string_loc(s, len, &f))
+                   /* Emulate :encoding(utf8) warning in the same case. */
+                   Perl_warner(aTHX_ packWARN(WARN_UTF8),
+                               "utf8 \"\\x%02X\" does not map to Unicode",
+                               f < (U8*)SvEND(sv) ? *f : 0);
+            }
        }
        if (gimme == G_ARRAY) {
            if (SvLEN(sv) - SvCUR(sv) > 20) {
                SvPV_shrink_to_cur(sv);
            }
-           sv = sv_2mortal(NEWSV(58, 80));
+           sv = sv_2mortal(newSV(80));
            continue;
        }
        else if (gimme == G_SCALAR && !tmplen && SvLEN(sv) - SvCUR(sv) > 80) {
@@ -1657,43 +1767,39 @@ PP(pp_enter)
 
 PP(pp_helem)
 {
-    dSP;
+    dVAR; dSP;
     HE* he;
     SV **svp;
-    SV *keysv = POPs;
-    HV *hv = (HV*)POPs;
+    SV * const keysv = POPs;
+    HV * const hv = (HV*)POPs;
     const U32 lval = PL_op->op_flags & OPf_MOD || LVRET;
     const U32 defer = PL_op->op_private & OPpLVAL_DEFER;
     SV *sv;
     const U32 hash = (SvIsCOW_shared_hash(keysv)) ? SvSHARED_HASH(keysv) : 0;
     I32 preeminent = 0;
 
-    if (SvTYPE(hv) == SVt_PVHV) {
-       if (PL_op->op_private & OPpLVAL_INTRO) {
-           MAGIC *mg;
-           HV *stash;
-           /* does the element we're localizing already exist? */
-           preeminent =  
-               /* can we determine whether it exists? */
-               (    !SvRMAGICAL(hv)
-                 || mg_find((SV*)hv, PERL_MAGIC_env)
-                 || (     (mg = mg_find((SV*)hv, PERL_MAGIC_tied))
-                       /* Try to preserve the existenceness of a tied hash
-                        * element by using EXISTS and DELETE if possible.
-                        * Fallback to FETCH and STORE otherwise */
-                       && (stash = SvSTASH(SvRV(SvTIED_obj((SV*)hv, mg))))
-                       && gv_fetchmethod_autoload(stash, "EXISTS", TRUE)
-                       && gv_fetchmethod_autoload(stash, "DELETE", TRUE)
-                   )
-               ) ? hv_exists_ent(hv, keysv, 0) : 1;
-
-       }
-       he = hv_fetch_ent(hv, keysv, lval && !defer, hash);
-       svp = he ? &HeVAL(he) : 0;
-    }
-    else {
+    if (SvTYPE(hv) != SVt_PVHV)
        RETPUSHUNDEF;
-    }
+
+    if (PL_op->op_private & OPpLVAL_INTRO) {
+       MAGIC *mg;
+       HV *stash;
+       /* does the element we're localizing already exist? */
+       preeminent = /* can we determine whether it exists? */
+           (    !SvRMAGICAL(hv)
+               || mg_find((SV*)hv, PERL_MAGIC_env)
+               || (     (mg = mg_find((SV*)hv, PERL_MAGIC_tied))
+                       /* Try to preserve the existenceness of a tied hash
+                       * element by using EXISTS and DELETE if possible.
+                       * Fallback to FETCH and STORE otherwise */
+                   && (stash = SvSTASH(SvRV(SvTIED_obj((SV*)hv, mg))))
+                   && gv_fetchmethod_autoload(stash, "EXISTS", TRUE)
+                   && gv_fetchmethod_autoload(stash, "DELETE", TRUE)
+               )
+           ) ? hv_exists_ent(hv, keysv, 0) : 1;
+    }
+    he = hv_fetch_ent(hv, keysv, lval && !defer, hash);
+    svp = he ? &HeVAL(he) : NULL;
     if (lval) {
        if (!svp || *svp == &PL_sv_undef) {
            SV* lv;
@@ -1704,9 +1810,9 @@ PP(pp_helem)
            lv = sv_newmortal();
            sv_upgrade(lv, SVt_PVLV);
            LvTYPE(lv) = 'y';
-           sv_magic(lv, key2 = newSVsv(keysv), PERL_MAGIC_defelem, Nullch, 0);
+           sv_magic(lv, key2 = newSVsv(keysv), PERL_MAGIC_defelem, NULL, 0);
            SvREFCNT_dec(key2); /* sv_magic() increments refcount */
-           LvTARG(lv) = SvREFCNT_inc(hv);
+           LvTARG(lv) = SvREFCNT_inc_simple(hv);
            LvTARGLEN(lv) = 1;
            PUSHs(lv);
            RETURN;
@@ -1717,8 +1823,9 @@ PP(pp_helem)
            else {
                if (!preeminent) {
                    STRLEN keylen;
-                   const char * const key = SvPV(keysv, keylen);
-                   SAVEDELETE(hv, savepvn(key,keylen), keylen);
+                   const char * const key = SvPV_const(keysv, keylen);
+                   SAVEDELETE(hv, savepvn(key,keylen),
+                              SvUTF8(keysv) ? -(I32)keylen : keylen);
                } else
                    save_helem(hv, keysv, svp);
             }
@@ -1798,7 +1905,7 @@ PP(pp_leave)
 
 PP(pp_iter)
 {
-    dSP;
+    dVAR; dSP;
     register PERL_CONTEXT *cx;
     SV *sv, *oldsv;
     AV* av;
@@ -1817,7 +1924,7 @@ PP(pp_iter)
            /* string increment */
            register SV* cur = cx->blk_loop.iterlval;
            STRLEN maxlen = 0;
-           const char *max = SvOK((SV*)av) ? SvPV((SV*)av, maxlen) : "";
+           const char *max = SvOK((SV*)av) ? SvPV_const((SV*)av, maxlen) : "";
            if (!SvNIOK(cur) && SvCUR(cur) <= maxlen) {
                if (SvREFCNT(*itersvp) == 1 && !SvMAGICAL(*itersvp)) {
                    /* safe to reuse old SV */
@@ -1868,14 +1975,11 @@ PP(pp_iter)
            RETPUSHNO;
 
        if (SvMAGICAL(av) || AvREIFY(av)) {
-           SV **svp = av_fetch(av, cx->blk_loop.iterix--, FALSE);
-           if (svp)
-               sv = *svp;
-           else
-               sv = Nullsv;
+           SV * const * const svp = av_fetch(av, --cx->blk_loop.iterix, FALSE);
+           sv = svp ? *svp : NULL;
        }
        else {
-           sv = AvARRAY(av)[cx->blk_loop.iterix--];
+           sv = AvARRAY(av)[--cx->blk_loop.iterix];
        }
     }
     else {
@@ -1884,19 +1988,16 @@ PP(pp_iter)
            RETPUSHNO;
 
        if (SvMAGICAL(av) || AvREIFY(av)) {
-           SV **svp = av_fetch(av, ++cx->blk_loop.iterix, FALSE);
-           if (svp)
-               sv = *svp;
-           else
-               sv = Nullsv;
+           SV * const * const svp = av_fetch(av, ++cx->blk_loop.iterix, FALSE);
+           sv = svp ? *svp : NULL;
        }
        else {
            sv = AvARRAY(av)[++cx->blk_loop.iterix];
        }
     }
 
-    if (sv && SvREFCNT(sv) == 0) {
-       *itersvp = Nullsv;
+    if (sv && SvIS_FREED(sv)) {
+       *itersvp = NULL;
        Perl_croak(aTHX_ "Use of freed value in iteration");
     }
 
@@ -1908,24 +2009,24 @@ PP(pp_iter)
        SV *lv = cx->blk_loop.iterlval;
        if (lv && SvREFCNT(lv) > 1) {
            SvREFCNT_dec(lv);
-           lv = Nullsv;
+           lv = NULL;
        }
        if (lv)
            SvREFCNT_dec(LvTARG(lv));
        else {
-           lv = cx->blk_loop.iterlval = NEWSV(26, 0);
+           lv = cx->blk_loop.iterlval = newSV(0);
            sv_upgrade(lv, SVt_PVLV);
            LvTYPE(lv) = 'y';
-           sv_magic(lv, Nullsv, PERL_MAGIC_defelem, Nullch, 0);
+           sv_magic(lv, NULL, PERL_MAGIC_defelem, NULL, 0);
        }
-       LvTARG(lv) = SvREFCNT_inc(av);
+       LvTARG(lv) = SvREFCNT_inc_simple(av);
        LvTARGOFF(lv) = cx->blk_loop.iterix;
        LvTARGLEN(lv) = (STRLEN)UV_MAX;
        sv = (SV*)lv;
     }
 
     oldsv = *itersvp;
-    *itersvp = SvREFCNT_inc(sv);
+    *itersvp = SvREFCNT_inc_simple_NN(sv);
     SvREFCNT_dec(oldsv);
 
     RETPUSHYES;
@@ -1933,14 +2034,13 @@ PP(pp_iter)
 
 PP(pp_subst)
 {
-    dSP; dTARG;
+    dVAR; dSP; dTARG;
     register PMOP *pm = cPMOP;
     PMOP *rpm = pm;
-    register SV *dstr;
     register char *s;
     char *strend;
     register char *m;
-    char *c;
+    const char *c;
     register char *d;
     STRLEN clen;
     I32 iters = 0;
@@ -1953,16 +2053,16 @@ PP(pp_subst)
     register REGEXP *rx = PM_GETRE(pm);
     STRLEN len;
     int force_on_match = 0;
-    I32 oldsave = PL_savestack_ix;
+    const I32 oldsave = PL_savestack_ix;
     STRLEN slen;
     bool doutf8 = FALSE;
-#ifdef PERL_COPY_ON_WRITE
+#ifdef PERL_OLD_COPY_ON_WRITE
     bool is_cow;
 #endif
-    SV *nsv = Nullsv;
+    SV *nsv = NULL;
 
     /* known replacement string? */
-    dstr = (pm->op_pmflags & PMf_CONST) ? POPs : Nullsv;
+    register SV *dstr = (pm->op_pmflags & PMf_CONST) ? POPs : NULL;
     if (PL_op->op_flags & OPf_STACKED)
        TARG = POPs;
     else if (PL_op->op_private & OPpTARGET_MY)
@@ -1972,7 +2072,7 @@ PP(pp_subst)
        EXTEND(SP,1);
     }
 
-#ifdef PERL_COPY_ON_WRITE
+#ifdef PERL_OLD_COPY_ON_WRITE
     /* Awooga. Awooga. "bool" types that are actually char are dangerous,
        because they make integers such as 256 "false".  */
     is_cow = SvIsCOW(TARG) ? TRUE : FALSE;
@@ -1981,7 +2081,7 @@ PP(pp_subst)
        sv_force_normal_flags(TARG,0);
 #endif
     if (
-#ifdef PERL_COPY_ON_WRITE
+#ifdef PERL_OLD_COPY_ON_WRITE
        !is_cow &&
 #endif
        (SvREADONLY(TARG)
@@ -1990,7 +2090,7 @@ PP(pp_subst)
        DIE(aTHX_ PL_no_modify);
     PUTBACK;
 
-    s = SvPV(TARG, len);
+    s = SvPV_mutable(TARG, len);
     if (!SvPOKp(TARG) || SvTYPE(TARG) == SVt_PVGV)
        force_on_match = 1;
     rxtainted = ((pm->op_pmdynflags & PMdf_TAINTED) ||
@@ -2015,7 +2115,8 @@ PP(pp_subst)
        pm = PL_curpm;
        rx = PM_GETRE(pm);
     }
-    r_flags = (rx->nparens || SvTEMP(TARG) || PL_sawampersand)
+    r_flags = (rx->nparens || SvTEMP(TARG) || PL_sawampersand
+           || (pm->op_pmflags & PMf_EVAL))
               ? REXEC_COPY_STR : 0;
     if (SvSCREAM(TARG))
        r_flags |= REXEC_SCREAM;
@@ -2050,22 +2151,22 @@ PP(pp_subst)
                  sv_recode_to_utf8(nsv, PL_encoding);
             else
                  sv_utf8_upgrade(nsv);
-            c = SvPV(nsv, clen);
+            c = SvPV_const(nsv, clen);
             doutf8 = TRUE;
        }
        else {
-           c = SvPV(dstr, clen);
+           c = SvPV_const(dstr, clen);
            doutf8 = DO_UTF8(dstr);
        }
     }
     else {
-        c = Nullch;
+       c = NULL;
        doutf8 = FALSE;
     }
     
     /* can do inplace substitution? */
     if (c
-#ifdef PERL_COPY_ON_WRITE
+#ifdef PERL_OLD_COPY_ON_WRITE
        && !is_cow
 #endif
        && (I32)clen <= rx->minlen && (once || !(r_flags & REXEC_COPY_STR))
@@ -2079,7 +2180,7 @@ PP(pp_subst)
            LEAVE_SCOPE(oldsave);
            RETURN;
        }
-#ifdef PERL_COPY_ON_WRITE
+#ifdef PERL_OLD_COPY_ON_WRITE
        if (SvIsCOW(TARG)) {
            assert (!force_on_match);
            goto have_a_cow;
@@ -2111,7 +2212,6 @@ PP(pp_subst)
                *m = '\0';
                SvCUR_set(TARG, m - s);
            }
-           /*SUPPRESS 560*/
            else if ((i = m - s)) {     /* faster from front */
                d -= clen;
                m = d;
@@ -2140,7 +2240,6 @@ PP(pp_subst)
                    DIE(aTHX_ "Substitution loop");
                rxtainted |= RX_MATCH_TAINTED(rx);
                m = rx->startp[0] + orig;
-               /*SUPPRESS 560*/
                if ((i = m - s)) {
                    if (s != d)
                        Move(s, d, i, char);
@@ -2186,7 +2285,7 @@ PP(pp_subst)
            s = SvPV_force(TARG, len);
            goto force_it;
        }
-#ifdef PERL_COPY_ON_WRITE
+#ifdef PERL_OLD_COPY_ON_WRITE
       have_a_cow:
 #endif
        rxtainted |= RX_MATCH_TAINTED(rx);
@@ -2197,7 +2296,7 @@ PP(pp_subst)
        if (!c) {
            register PERL_CONTEXT *cx;
            SPAGAIN;
-           ReREFCNT_inc(rx);
+           (void)ReREFCNT_inc(rx);
            PUSHSUBST(cx);
            RETURNOP(cPMOP->op_pmreplroot);
        }
@@ -2230,7 +2329,7 @@ PP(pp_subst)
        else
            sv_catpvn(dstr, s, strend - s);
 
-#ifdef PERL_COPY_ON_WRITE
+#ifdef PERL_OLD_COPY_ON_WRITE
        /* The match may make the string COW. If so, brilliant, because that's
           just saved us one malloc, copy and free - the regexp has donated
           the old buffer, and we malloc an entirely new one, rather than the
@@ -2247,7 +2346,7 @@ PP(pp_subst)
        SvCUR_set(TARG, SvCUR(dstr));
        SvLEN_set(TARG, SvLEN(dstr));
        doutf8 |= DO_UTF8(dstr);
-       SvPV_set(dstr, (char*)0);
+       SvPV_set(dstr, NULL);
        sv_free(dstr);
 
        TAINT_IF(rxtainted & 1);
@@ -2285,7 +2384,7 @@ PP(pp_grepwhile)
     /* All done yet? */
     if (PL_stack_base + *PL_markstack_ptr > SP) {
        I32 items;
-       I32 gimme = GIMME_V;
+       const I32 gimme = GIMME_V;
 
        LEAVE;                                  /* exit outer scope */
        (void)POPMARK;                          /* pop src */
@@ -2294,7 +2393,7 @@ PP(pp_grepwhile)
        SP = PL_stack_base + POPMARK;           /* pop original mark */
        if (gimme == G_SCALAR) {
            if (PL_op->op_private & OPpGREP_LEX) {
-               SV* sv = sv_newmortal();
+               SV* const sv = sv_newmortal();
                sv_setiv(sv, items);
                PUSHs(sv);
            }
@@ -2334,6 +2433,9 @@ PP(pp_leavesub)
     register PERL_CONTEXT *cx;
     SV *sv;
 
+    if (CxMULTICALL(&cxstack[cxstack_ix]))
+       return 0;
+
     POPBLOCK(cx,newpm);
     cxstack_ix++; /* temporarily protect top context */
 
@@ -2394,6 +2496,9 @@ PP(pp_leavesublv)
     register PERL_CONTEXT *cx;
     SV *sv;
 
+    if (CxMULTICALL(&cxstack[cxstack_ix]))
+       return 0;
+
     POPBLOCK(cx,newpm);
     cxstack_ix++; /* temporarily protect top context */
 
@@ -2415,13 +2520,13 @@ PP(pp_leavesublv)
            EXTEND_MORTAL(SP - newsp);
            for (mark = newsp + 1; mark <= SP; mark++) {
                if (SvTEMP(*mark))
-                   /* empty */ ;
+                   /*EMPTY*/;
                else if (SvFLAGS(*mark) & (SVs_PADTMP | SVf_READONLY))
                    *mark = sv_mortalcopy(*mark);
                else {
                    /* Can be a localized value subject to deletion. */
                    PL_tmps_stack[++PL_tmps_ix] = *mark;
-                   (void)SvREFCNT_inc(*mark);
+                   SvREFCNT_inc_void(*mark);
                }
            }
        }
@@ -2442,7 +2547,10 @@ PP(pp_leavesublv)
            MARK = newsp + 1;
            EXTEND_MORTAL(1);
            if (MARK == SP) {
-               if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)) {
+               /* Temporaries are bad unless they happen to be elements
+                * of a tied hash or array */
+               if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY) &&
+                   !(SvRMAGICAL(TOPs) && mg_find(TOPs, PERL_MAGIC_tiedelem))) {
                    LEAVE;
                    cxstack_ix--;
                    POPSUB(cx,sv);
@@ -2455,7 +2563,7 @@ PP(pp_leavesublv)
                else {                  /* Can be a localized value
                                         * subject to deletion. */
                    PL_tmps_stack[++PL_tmps_ix] = *mark;
-                   (void)SvREFCNT_inc(*mark);
+                   SvREFCNT_inc_void(*mark);
                }
            }
            else {                      /* Should not happen? */
@@ -2487,7 +2595,7 @@ PP(pp_leavesublv)
                else {
                    /* Can be a localized value subject to deletion. */
                    PL_tmps_stack[++PL_tmps_ix] = *mark;
-                   (void)SvREFCNT_inc(*mark);
+                   SvREFCNT_inc_void(*mark);
                }
            }
        }
@@ -2544,25 +2652,25 @@ PP(pp_leavesublv)
 STATIC CV *
 S_get_db_sub(pTHX_ SV **svp, CV *cv)
 {
-    SV *dbsv = GvSV(PL_DBsub);
+    dVAR;
+    SV * const dbsv = GvSVn(PL_DBsub);
 
     save_item(dbsv);
     if (!PERLDB_SUB_NN) {
-       GV *gv = CvGV(cv);
+       GV * const gv = CvGV(cv);
 
        if ( (CvFLAGS(cv) & (CVf_ANON | CVf_CLONED))
             || strEQ(GvNAME(gv), "END")
             || ((GvCV(gv) != cv) && /* Could be imported, and old sub redefined. */
-                !( (SvTYPE(*svp) == SVt_PVGV) && (GvCV((GV*)*svp) == cv)
-                   && (gv = (GV*)*svp) ))) {
+                !( (SvTYPE(*svp) == SVt_PVGV) && (GvCV((GV*)*svp) == cv) ))) {
            /* Use GV from the stack as a fallback. */
            /* GV is potentially non-unique, or contain different CV. */
-           SV *tmp = newRV((SV*)cv);
+           SV * const tmp = newRV((SV*)cv);
            sv_setsv(dbsv, tmp);
            SvREFCNT_dec(tmp);
        }
        else {
-           gv_efullname3(dbsv, gv, Nullch);
+           gv_efullname3(dbsv, gv, NULL);
        }
     }
     else {
@@ -2573,7 +2681,7 @@ S_get_db_sub(pTHX_ SV **svp, CV *cv)
        SvIV_set(dbsv, PTR2IV(cv));     /* Do it the quickest way  */
     }
 
-    if (CvXSUB(cv))
+    if (CvISXSUB(cv))
        PL_curcopdb = PL_curcop;
     cv = GvCV(PL_DBsub);
     return cv;
@@ -2583,7 +2691,6 @@ PP(pp_entersub)
 {
     dVAR; dSP; dPOPss;
     GV *gv;
-    HV *stash;
     register CV *cv;
     register PERL_CONTEXT *cx;
     I32 gimme;
@@ -2594,8 +2701,10 @@ PP(pp_entersub)
     switch (SvTYPE(sv)) {
        /* This is overwhelming the most common case:  */
     case SVt_PVGV:
-       if (!(cv = GvCVu((GV*)sv)))
-           cv = sv_2cv(sv, &stash, &gv, FALSE);
+       if (!(cv = GvCVu((GV*)sv))) {
+           HV *stash;
+           cv = sv_2cv(sv, &stash, &gv, 0);
+       }
        if (!cv) {
            ENTER;
            SAVETMPS;
@@ -2614,11 +2723,10 @@ PP(pp_entersub)
                mg_get(sv);
                if (SvROK(sv))
                    goto got_rv;
-               sym = SvPOKp(sv) ? SvPVX_const(sv) : Nullch;
+               sym = SvPOKp(sv) ? SvPVX_const(sv) : NULL;
            }
            else {
-                STRLEN n_a;
-               sym = SvPV(sv, n_a);
+               sym = SvPV_nolen_const(sv);
             }
            if (!sym)
                DIE(aTHX_ PL_no_usym, "a subroutine");
@@ -2629,7 +2737,7 @@ PP(pp_entersub)
        }
   got_rv:
        {
-           SV **sp = &sv;              /* Used in tryAMAGICunDEREF macro. */
+           SV * const * sp = &sv;              /* Used in tryAMAGICunDEREF macro. */
            tryAMAGICunDEREF(to_cv);
        }       
        cv = (CV*)SvRV(sv);
@@ -2650,7 +2758,35 @@ PP(pp_entersub)
 
   retry:
     if (!CvROOT(cv) && !CvXSUB(cv)) {
-       goto fooey;
+       GV* autogv;
+       SV* sub_name;
+
+       /* anonymous or undef'd function leaves us no recourse */
+       if (CvANON(cv) || !(gv = CvGV(cv)))
+           DIE(aTHX_ "Undefined subroutine called");
+
+       /* autoloaded stub? */
+       if (cv != GvCV(gv)) {
+           cv = GvCV(gv);
+       }
+       /* should call AUTOLOAD now? */
+       else {
+try_autoload:
+           if ((autogv = gv_autoload4(GvSTASH(gv), GvNAME(gv), GvNAMELEN(gv),
+                                  FALSE)))
+           {
+               cv = GvCV(autogv);
+           }
+           /* sorry */
+           else {
+               sub_name = sv_newmortal();
+               gv_efullname3(sub_name, gv, NULL);
+               DIE(aTHX_ "Undefined subroutine &%"SVf" called", sub_name);
+           }
+       }
+       if (!cv)
+           DIE(aTHX_ "Not a CODE reference");
+       goto retry;
     }
 
     gimme = GIMME_V;
@@ -2663,11 +2799,11 @@ PP(pp_entersub)
            DIE(aTHX_ "No DB::sub routine defined");
     }
 
-    if (!(CvXSUB(cv))) {
+    if (!(CvISXSUB(cv))) {
        /* This path taken at least 75% of the time   */
        dMARK;
        register I32 items = SP - MARK;
-       AV* padlist = CvPADLIST(cv);
+       AV* const padlist = CvPADLIST(cv);
        PUSHBLOCK(cx, CXt_SUB, MARK);
        PUSHSUB(cx);
        cx->blk_sub.retop = PL_op->op_next;
@@ -2681,15 +2817,11 @@ PP(pp_entersub)
            PERL_STACK_OVERFLOW_CHECK();
            pad_push(padlist, CvDEPTH(cv));
        }
-       PAD_SET_CUR(padlist, CvDEPTH(cv));
+       SAVECOMPPAD();
+       PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv));
        if (hasargs)
        {
-           AV* av;
-#if 0
-           DEBUG_S(PerlIO_printf(Perl_debug_log,
-                                 "%p entersub preparing @_\n", thr));
-#endif
-           av = (AV*)PAD_SVl(0);
+           AV* const av = (AV*)PAD_SVl(0);
            if (AvREAL(av)) {
                /* @_ is normally not REAL--this should only ever
                 * happen when DB::sub() calls things that modify @_ */
@@ -2698,7 +2830,7 @@ PP(pp_entersub)
                AvREIFY_on(av);
            }
            cx->blk_sub.savearray = GvAV(PL_defgv);
-           GvAV(PL_defgv) = (AV*)SvREFCNT_inc(av);
+           GvAV(PL_defgv) = (AV*)SvREFCNT_inc_simple(av);
            CX_CURPAD_SAVE(cx->blk_sub);
            cx->blk_sub.argarray = av;
            ++MARK;
@@ -2739,26 +2871,6 @@ PP(pp_entersub)
        RETURNOP(CvSTART(cv));
     }
     else {
-#ifdef PERL_XSUB_OLDSTYLE
-       if (CvOLDSTYLE(cv)) {
-           I32 (*fp3)(int,int,int);
-           dMARK;
-           register I32 items = SP - MARK;
-                                       /* We dont worry to copy from @_. */
-           while (SP > mark) {
-               SP[1] = SP[0];
-               SP--;
-           }
-           PL_stack_sp = mark + 1;
-           fp3 = (I32(*)(int,int,int))CvXSUB(cv);
-           items = (*fp3)(CvXSUBANY(cv).any_i32,
-                          MARK - PL_stack_base + 1,
-                          items);
-           PL_stack_sp = PL_stack_base + items;
-       }
-       else
-#endif /* PERL_XSUB_OLDSTYLE */
-       {
            I32 markix = TOPMARK;
 
            PUTBACK;
@@ -2795,46 +2907,9 @@ PP(pp_entersub)
                    *(PL_stack_base + markix) = *PL_stack_sp;
                PL_stack_sp = PL_stack_base + markix;
            }
-       }
        LEAVE;
        return NORMAL;
     }
-
-    assert (0); /* Cannot get here.  */
-    /* This is deliberately moved here as spaghetti code to keep it out of the
-       hot path.  */
-    {
-       GV* autogv;
-       SV* sub_name;
-
-      fooey:
-       /* anonymous or undef'd function leaves us no recourse */
-       if (CvANON(cv) || !(gv = CvGV(cv)))
-           DIE(aTHX_ "Undefined subroutine called");
-
-       /* autoloaded stub? */
-       if (cv != GvCV(gv)) {
-           cv = GvCV(gv);
-       }
-       /* should call AUTOLOAD now? */
-       else {
-try_autoload:
-           if ((autogv = gv_autoload4(GvSTASH(gv), GvNAME(gv), GvNAMELEN(gv),
-                                  FALSE)))
-           {
-               cv = GvCV(autogv);
-           }
-           /* sorry */
-           else {
-               sub_name = sv_newmortal();
-               gv_efullname3(sub_name, gv, Nullch);
-               DIE(aTHX_ "Undefined subroutine &%"SVf" called", sub_name);
-           }
-       }
-       if (!cv)
-           DIE(aTHX_ "Not a CODE reference");
-       goto retry;
-    }
 }
 
 void
@@ -2843,8 +2918,8 @@ Perl_sub_crush_depth(pTHX_ CV *cv)
     if (CvANON(cv))
        Perl_warner(aTHX_ packWARN(WARN_RECURSION), "Deep recursion on anonymous subroutine");
     else {
-       SV* tmpstr = sv_newmortal();
-       gv_efullname3(tmpstr, CvGV(cv), Nullch);
+       SV* const tmpstr = sv_newmortal();
+       gv_efullname3(tmpstr, CvGV(cv), NULL);
        Perl_warner(aTHX_ packWARN(WARN_RECURSION), "Deep recursion on subroutine \"%"SVf"\"",
                tmpstr);
     }
@@ -2852,11 +2927,11 @@ Perl_sub_crush_depth(pTHX_ CV *cv)
 
 PP(pp_aelem)
 {
-    dSP;
+    dVAR; dSP;
     SV** svp;
     SV* const elemsv = POPs;
     IV elem = SvIV(elemsv);
-    AV* av = (AV*)POPs;
+    AV* const av = (AV*)POPs;
     const U32 lval = PL_op->op_flags & OPf_MOD || LVRET;
     const U32 defer = (PL_op->op_private & OPpLVAL_DEFER) && (elem > av_len(av));
     SV *sv;
@@ -2864,7 +2939,7 @@ PP(pp_aelem)
     if (SvROK(elemsv) && !SvGAMAGIC(elemsv) && ckWARN(WARN_MISC))
        Perl_warner(aTHX_ packWARN(WARN_MISC), "Use of reference \"%"SVf"\" as array index", elemsv);
     if (elem > 0)
-       elem -= PL_curcop->cop_arybase;
+       elem -= CopARYBASE_get(PL_curcop);
     if (SvTYPE(av) != SVt_PVAV)
        RETPUSHUNDEF;
     svp = av_fetch(av, elem, lval && !defer);
@@ -2889,8 +2964,8 @@ PP(pp_aelem)
            lv = sv_newmortal();
            sv_upgrade(lv, SVt_PVLV);
            LvTYPE(lv) = 'y';
-           sv_magic(lv, Nullsv, PERL_MAGIC_defelem, Nullch, 0);
-           LvTARG(lv) = SvREFCNT_inc(av);
+           sv_magic(lv, NULL, PERL_MAGIC_defelem, NULL, 0);
+           LvTARG(lv) = SvREFCNT_inc_simple(av);
            LvTARGOFF(lv) = elem;
            LvTARGLEN(lv) = 1;
            PUSHs(lv);
@@ -2911,8 +2986,7 @@ PP(pp_aelem)
 void
 Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
 {
-    if (SvGMAGICAL(sv))
-       mg_get(sv);
+    SvGETMAGIC(sv);
     if (!SvOK(sv)) {
        if (SvREADONLY(sv))
            Perl_croak(aTHX_ PL_no_modify);
@@ -2925,7 +2999,7 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
        }
        switch (to_what) {
        case OPpDEREF_SV:
-           SvRV_set(sv, NEWSV(355,0));
+           SvRV_set(sv, newSV(0));
            break;
        case OPpDEREF_AV:
            SvRV_set(sv, (SV*)newAV());
@@ -2941,25 +3015,25 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
 
 PP(pp_method)
 {
-    dSP;
-    SV* sv = TOPs;
+    dVAR; dSP;
+    SV* const sv = TOPs;
 
     if (SvROK(sv)) {
-       SV* rsv = SvRV(sv);
+       SV* const rsv = SvRV(sv);
        if (SvTYPE(rsv) == SVt_PVCV) {
            SETs(rsv);
            RETURN;
        }
     }
 
-    SETs(method_common(sv, Null(U32*)));
+    SETs(method_common(sv, NULL));
     RETURN;
 }
 
 PP(pp_method_named)
 {
-    dSP;
-    SV* sv = cSVOP_sv;
+    dVAR; dSP;
+    SV* const sv = cSVOP_sv;
     U32 hash = SvSHARED_HASH(sv);
 
     XPUSHs(method_common(sv, &hash));
@@ -2969,32 +3043,28 @@ PP(pp_method_named)
 STATIC SV *
 S_method_common(pTHX_ SV* meth, U32* hashp)
 {
-    SV* sv;
+    dVAR;
     SV* ob;
     GV* gv;
     HV* stash;
     STRLEN namelen;
-    const char* packname = 0;
-    SV *packsv = Nullsv;
+    const char* packname = NULL;
+    SV *packsv = NULL;
     STRLEN packlen;
-    const char *name = SvPV(meth, namelen);
-
-    sv = *(PL_stack_base + TOPMARK + 1);
+    const char * const name = SvPV_const(meth, namelen);
+    SV * const sv = *(PL_stack_base + TOPMARK + 1);
 
     if (!sv)
        Perl_croak(aTHX_ "Can't call method \"%s\" on an undefined value", name);
 
-    if (SvGMAGICAL(sv))
-       mg_get(sv);
+    SvGETMAGIC(sv);
     if (SvROK(sv))
        ob = (SV*)SvRV(sv);
     else {
        GV* iogv;
 
        /* this isn't a reference */
-       packname = Nullch;
-
-        if(SvOK(sv) && (packname = SvPV(sv, packlen))) {
+        if(SvOK(sv) && (packname = SvPV_const(sv, packlen))) {
           const HE* const he = hv_fetch_ent(PL_stashcache, sv, 0, 0);
           if (he) { 
             stash = INT2PTR(HV*,SvIV(HeVAL(he)));
@@ -3004,7 +3074,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
 
        if (!SvOK(sv) ||
            !(packname) ||
-           !(iogv = gv_fetchsv(sv, FALSE, SVt_PVIO)) ||
+           !(iogv = gv_fetchsv(sv, 0, SVt_PVIO)) ||
            !(ob=(SV*)GvIO(iogv)))
        {
            /* this isn't the name of a filehandle either */
@@ -3023,7 +3093,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
            if (!stash)
                packsv = sv;
             else {
-               SV* ref = newSViv(PTR2IV(stash));
+               SV* const ref = newSViv(PTR2IV(stash));
                hv_store(PL_stashcache, packname, packlen, ref, 0);
            }
            goto fetch;
@@ -3069,7 +3139,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
           don't want that.
        */
        const char* leaf = name;
-       const char* sep = Nullch;
+       const char* sep = NULL;
        const char* p;
 
        for (p = name; *p; p++) {
@@ -3085,7 +3155,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
                packname = CopSTASHPV(PL_curcop);
            }
            else if (stash) {
-               HEK *packhek = HvNAME_HEK(stash);
+               HEK * const packhek = HvNAME_HEK(stash);
                if (packhek) {
                    packname = HEK_KEY(packhek);
                    packlen = HEK_LEN(packhek);