This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Oops. Fix threaded builds.
[perl5.git] / pp.c
diff --git a/pp.c b/pp.c
index d090069..58169cb 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -54,7 +54,6 @@ static const STRLEN capital_iota_len = sizeof(GREEK_CAPITAL_LETTER_IOTA_UTF8) -
 
 PP(pp_stub)
 {
-    dVAR;
     dSP;
     if (GIMME_V == G_SCALAR)
        XPUSHs(&PL_sv_undef);
@@ -65,7 +64,7 @@ PP(pp_stub)
 
 PP(pp_padav)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     I32 gimme;
     assert(SvTYPE(TARG) == SVt_PVAV);
     if (UNLIKELY( PL_op->op_private & OPpLVAL_INTRO ))
@@ -117,7 +116,7 @@ PP(pp_padav)
 
 PP(pp_padhv)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     I32 gimme;
 
     assert(SvTYPE(TARG) == SVt_PVHV);
@@ -154,7 +153,7 @@ PP(pp_padhv)
 
 PP(pp_padcv)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     assert(SvTYPE(TARG) == SVt_PVCV);
     XPUSHs(TARG);
     RETURN;
@@ -162,14 +161,14 @@ PP(pp_padcv)
 
 PP(pp_introcv)
 {
-    dVAR; dTARGET;
+    dTARGET;
     SvPADSTALE_off(TARG);
     return NORMAL;
 }
 
 PP(pp_clonecv)
 {
-    dVAR; dTARGET;
+    dTARGET;
     MAGIC * const mg =
        mg_find(PadlistNAMESARRAY(CvPADLIST(find_runcv(NULL)))[ARGTARG],
                PERL_MAGIC_proto);
@@ -211,7 +210,6 @@ static SV *
 S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict,
               const bool noinit)
 {
-    dVAR;
     if (!isGV(sv) || SvFAKE(sv)) SvGETMAGIC(sv);
     if (SvROK(sv)) {
        if (SvAMAGIC(sv)) {
@@ -226,8 +224,9 @@ S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict,
            SvREFCNT_inc_void_NN(sv);
            sv = MUTABLE_SV(gv);
        }
-       else if (!isGV_with_GP(sv))
-           return (SV *)Perl_die(aTHX_ "Not a GLOB reference");
+       else if (!isGV_with_GP(sv)) {
+           Perl_die(aTHX_ "Not a GLOB reference");
+        }
     }
     else {
        if (!isGV_with_GP(sv)) {
@@ -250,6 +249,7 @@ S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict,
                        const char * const name = CopSTASHPV(PL_curcop);
                        gv = newGVgen_flags(name,
                                 HvNAMEUTF8(CopSTASH(PL_curcop)) ? SVf_UTF8 : 0 );
+                       SvREFCNT_inc_simple_void_NN(gv);
                    }
                    prepare_SV_for_RV(sv);
                    SvRV_set(sv, MUTABLE_SV(gv));
@@ -257,8 +257,9 @@ S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict,
                    SvSETMAGIC(sv);
                    goto wasref;
                }
-               if (PL_op->op_flags & OPf_REF || strict)
-                   return (SV *)Perl_die(aTHX_ PL_no_usym, "a symbol");
+               if (PL_op->op_flags & OPf_REF || strict) {
+                   Perl_die(aTHX_ PL_no_usym, "a symbol");
+                }
                if (ckWARN(WARN_UNINITIALIZED))
                    report_uninit(sv);
                return &PL_sv_undef;
@@ -271,14 +272,14 @@ S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict,
                    return &PL_sv_undef;
            }
            else {
-               if (strict)
-                   return
-                    (SV *)Perl_die(aTHX_
-                           S_no_symref_sv,
-                           sv,
-                           (SvPOKp(sv) && SvCUR(sv)>32 ? "..." : ""),
-                           "a symbol"
-                          );
+               if (strict) {
+                    Perl_die(aTHX_
+                             S_no_symref_sv,
+                             sv,
+                             (SvPOKp(sv) && SvCUR(sv)>32 ? "..." : ""),
+                             "a symbol"
+                             );
+                }
                if ((PL_op->op_private & (OPpLVAL_INTRO|OPpDONT_INIT_GV))
                    == OPpDONT_INIT_GV) {
                    /* We are the target of a coderef assignment.  Return
@@ -303,7 +304,7 @@ S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict,
 
 PP(pp_rv2gv)
 {
-    dVAR; dSP; dTOPss;
+    dSP; dTOPss;
 
     sv = S_rv2gv(aTHX_
           sv, PL_op->op_private & OPpDEREF,
@@ -322,7 +323,6 @@ GV *
 Perl_softref2xv(pTHX_ SV *const sv, const char *const what,
                const svtype type, SV ***spp)
 {
-    dVAR;
     GV *gv;
 
     PERL_ARGS_ASSERT_SOFTREF2XV;
@@ -365,7 +365,7 @@ Perl_softref2xv(pTHX_ SV *const sv, const char *const what,
 
 PP(pp_rv2sv)
 {
-    dVAR; dSP; dTOPss;
+    dSP; dTOPss;
     GV *gv = NULL;
 
     SvGETMAGIC(sv);
@@ -413,7 +413,7 @@ PP(pp_rv2sv)
 
 PP(pp_av2arylen)
 {
-    dVAR; dSP;
+    dSP;
     AV * const av = MUTABLE_AV(TOPs);
     const I32 lvalue = PL_op->op_flags & OPf_MOD || LVRET;
     if (lvalue) {
@@ -431,7 +431,7 @@ PP(pp_av2arylen)
 
 PP(pp_pos)
 {
-    dVAR; dSP; dPOPss;
+    dSP; dPOPss;
 
     if (PL_op->op_flags & OPf_MOD || LVRET) {
        SV * const ret = sv_2mortal(newSV_type(SVt_PVLV));/* Not TARG RT#67838 */
@@ -457,7 +457,7 @@ PP(pp_pos)
 
 PP(pp_rv2cv)
 {
-    dVAR; dSP;
+    dSP;
     GV *gv;
     HV *stash_unused;
     const I32 flags = (PL_op->op_flags & OPf_SPECIAL)
@@ -472,7 +472,9 @@ PP(pp_rv2cv)
     CV *cv = sv_2cv(TOPs, &stash_unused, &gv, flags);
     if (cv) NOOP;
     else if ((flags == (GV_ADD|GV_NOEXPAND)) && gv && SvROK(gv)) {
-       cv = MUTABLE_CV(gv);
+       cv = SvTYPE(SvRV(gv)) == SVt_PVCV
+           ? MUTABLE_CV(SvRV(gv))
+           : MUTABLE_CV(gv);
     }    
     else
        cv = MUTABLE_CV(&PL_sv_undef);
@@ -482,7 +484,7 @@ PP(pp_rv2cv)
 
 PP(pp_prototype)
 {
-    dVAR; dSP;
+    dSP;
     CV *cv;
     HV *stash;
     GV *gv;
@@ -493,7 +495,7 @@ PP(pp_prototype)
        const char * s = SvPVX_const(TOPs);
        if (strnEQ(s, "CORE::", 6)) {
            const int code = keyword(s + 6, SvCUR(TOPs) - 6, 1);
-           if (!code || code == -KEY_CORE)
+           if (!code)
                DIE(aTHX_ "Can't find an opnumber for \"%"UTF8f"\"",
                   UTF8fARG(SvFLAGS(TOPs) & SVf_UTF8, SvCUR(TOPs)-6, s+6));
            {
@@ -515,7 +517,7 @@ PP(pp_prototype)
 
 PP(pp_anoncode)
 {
-    dVAR; dSP;
+    dSP;
     CV *cv = MUTABLE_CV(PAD_SV(PL_op->op_targ));
     if (CvCLONE(cv))
        cv = MUTABLE_CV(sv_2mortal(MUTABLE_SV(cv_clone(cv))));
@@ -526,14 +528,14 @@ PP(pp_anoncode)
 
 PP(pp_srefgen)
 {
-    dVAR; dSP;
+    dSP;
     *SP = refto(*SP);
     RETURN;
 }
 
 PP(pp_refgen)
 {
-    dVAR; dSP; dMARK;
+    dSP; dMARK;
     if (GIMME != G_ARRAY) {
        if (++MARK <= SP)
            *MARK = *SP;
@@ -552,7 +554,6 @@ PP(pp_refgen)
 STATIC SV*
 S_refto(pTHX_ SV *sv)
 {
-    dVAR;
     SV* rv;
 
     PERL_ARGS_ASSERT_REFTO;
@@ -571,8 +572,9 @@ S_refto(pTHX_ SV *sv)
        SvTEMP_off(sv);
        SvREFCNT_inc_void_NN(sv);
     }
-    else if (SvPADTMP(sv) && !IS_PADGV(sv))
+    else if (SvPADTMP(sv)) {
         sv = newSVsv(sv);
+    }
     else {
        SvTEMP_off(sv);
        SvREFCNT_inc_void_NN(sv);
@@ -586,21 +588,26 @@ S_refto(pTHX_ SV *sv)
 
 PP(pp_ref)
 {
-    dVAR; dSP; dTARGET;
-    SV * const sv = POPs;
+    dSP;
+    SV * const sv = TOPs;
 
     SvGETMAGIC(sv);
     if (!SvROK(sv))
-       RETPUSHNO;
+       SETs(&PL_sv_no);
+    else {
+       dTARGET;
+       SETs(TARG);
+       /* use the return value that is in a register, its the same as TARG */
+       TARG = sv_ref(TARG,SvRV(sv),TRUE);
+       SvSETMAGIC(TARG);
+    }
 
-    (void)sv_ref(TARG,SvRV(sv),TRUE);
-    PUSHTARG;
-    RETURN;
+    return NORMAL;
 }
 
 PP(pp_bless)
 {
-    dVAR; dSP;
+    dSP;
     HV *stash;
 
     if (MAXARG == 1)
@@ -641,7 +648,7 @@ PP(pp_bless)
 
 PP(pp_gelem)
 {
-    dVAR; dSP;
+    dSP;
 
     SV *sv = POPs;
     STRLEN len;
@@ -720,7 +727,7 @@ PP(pp_gelem)
 
 PP(pp_study)
 {
-    dVAR; dSP; dPOPss;
+    dSP; dPOPss;
     STRLEN len;
 
     (void)SvPV(sv, len);
@@ -734,9 +741,12 @@ PP(pp_study)
     RETPUSHYES;
 }
 
+
+/* also used for: pp_transr() */
+
 PP(pp_trans)
 {
-    dVAR; dSP; dTARG;
+    dSP; dTARG;
     SV *sv;
 
     if (PL_op->op_flags & OPf_STACKED)
@@ -766,7 +776,6 @@ PP(pp_trans)
 static void
 S_do_chomp(pTHX_ SV *retval, SV *sv, bool chomping)
 {
-    dVAR;
     STRLEN len;
     char *s;
 
@@ -928,9 +937,12 @@ S_do_chomp(pTHX_ SV *retval, SV *sv, bool chomping)
     }
 }
 
+
+/* also used for: pp_schomp() */
+
 PP(pp_schop)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     const bool chomping = PL_op->op_type == OP_SCHOMP;
 
     if (chomping)
@@ -940,9 +952,12 @@ PP(pp_schop)
     RETURN;
 }
 
+
+/* also used for: pp_chomp() */
+
 PP(pp_chop)
 {
-    dVAR; dSP; dMARK; dTARGET; dORIGMARK;
+    dSP; dMARK; dTARGET; dORIGMARK;
     const bool chomping = PL_op->op_type == OP_CHOMP;
 
     if (chomping)
@@ -956,7 +971,7 @@ PP(pp_chop)
 
 PP(pp_undef)
 {
-    dVAR; dSP;
+    dSP;
     SV *sv;
 
     if (!PL_op->op_private) {
@@ -968,7 +983,8 @@ PP(pp_undef)
     if (!sv)
        RETPUSHUNDEF;
 
-    SV_CHECK_THINKFIRST_COW_DROP(sv);
+    if (SvTHINKFIRST(sv))
+       sv_force_normal_flags(sv, SV_COW_DROP_PV|SV_IMMEDIATE_UNREF);
 
     switch (SvTYPE(sv)) {
     case SVt_NULL:
@@ -993,18 +1009,8 @@ PP(pp_undef)
                            ));
        /* FALLTHROUGH */
     case SVt_PVFM:
-       {
            /* let user-undef'd sub keep its identity */
-           GV* const gv = CvGV((const CV *)sv);
-           HEK * const hek = CvNAME_HEK((CV *)sv);
-           if (hek) share_hek_hek(hek);
-           cv_undef(MUTABLE_CV(sv));
-           if (gv) CvGV_set(MUTABLE_CV(sv), gv);
-           else if (hek) {
-               SvANY((CV *)sv)->xcv_gv_u.xcv_hek = hek;
-               CvNAMED_on(sv);
-           }
-       }
+       cv_undef_flags(MUTABLE_CV(sv), CV_UNDEF_KEEP_NAME);
        break;
     case SVt_PVGV:
        assert(isGV_with_GP(sv));
@@ -1024,6 +1030,7 @@ PP(pp_undef)
                 else stash = NULL;
             }
 
+           SvREFCNT_inc_simple_void_NN(sv_2mortal(sv));
            gp_free(MUTABLE_GV(sv));
            Newxz(gp, 1, GP);
            GvGP_set(sv, gp_ref(gp));
@@ -1062,9 +1069,12 @@ PP(pp_undef)
     RETPUSHUNDEF;
 }
 
+
+/* also used for: pp_i_postdec() pp_i_postinc() pp_postdec() */
+
 PP(pp_postinc)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     const bool inc =
        PL_op->op_type == OP_POSTINC || PL_op->op_type == OP_I_POSTINC;
     if (SvTYPE(TOPs) >= SVt_PVAV || (isGV_with_GP(TOPs) && !SvFAKE(TOPs)))
@@ -1093,7 +1103,7 @@ PP(pp_postinc)
 
 PP(pp_pow)
 {
-    dVAR; dSP; dATARGET; SV *svl, *svr;
+    dSP; dATARGET; SV *svl, *svr;
 #ifdef PERL_PRESERVE_IVUV
     bool is_int = 0;
 #endif
@@ -1260,7 +1270,7 @@ PP(pp_pow)
 
 PP(pp_multiply)
 {
-    dVAR; dSP; dATARGET; SV *svl, *svr;
+    dSP; dATARGET; SV *svl, *svr;
     tryAMAGICbin_MG(mult_amg, AMGf_assign|AMGf_numeric);
     svr = TOPs;
     svl = TOPm1s;
@@ -1382,7 +1392,7 @@ PP(pp_multiply)
 
 PP(pp_divide)
 {
-    dVAR; dSP; dATARGET; SV *svl, *svr;
+    dSP; dATARGET; SV *svl, *svr;
     tryAMAGICbin_MG(div_amg, AMGf_assign|AMGf_numeric);
     svr = TOPs;
     svl = TOPm1s;
@@ -1502,7 +1512,7 @@ PP(pp_divide)
 
 PP(pp_modulo)
 {
-    dVAR; dSP; dATARGET;
+    dSP; dATARGET;
     tryAMAGICbin_MG(modulo_amg, AMGf_assign|AMGf_numeric);
     {
        UV left  = 0;
@@ -1629,7 +1639,7 @@ PP(pp_modulo)
 
 PP(pp_repeat)
 {
-    dVAR; dSP; dATARGET;
+    dSP; dATARGET;
     IV count;
     SV *sv;
 
@@ -1651,23 +1661,25 @@ PP(pp_repeat)
              else
                   count = uv;
         } else {
-             const IV iv = SvIV_nomg(sv);
-             if (iv < 0)
-                  count = 0;
-             else
-                  count = iv;
+             count = SvIV_nomg(sv);
         }
     }
     else if (SvNOKp(sv)) {
         const NV nv = SvNV_nomg(sv);
         if (nv < 0.0)
-             count = 0;
+              count = -1;   /* An arbitrary negative integer */
         else
              count = (IV)nv;
     }
     else
         count = SvIV_nomg(sv);
 
+    if (count < 0) {
+        count = 0;
+        Perl_ck_warner(aTHX_ packWARN(WARN_NUMERIC),
+                                         "Negative repeat count does nothing");
+    }
+
     if (GIMME == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) {
        dMARK;
        static const char* const oom_list_extend = "Out of memory during list extend";
@@ -1706,10 +1718,10 @@ PP(pp_repeat)
                    SvREADONLY_on(*SP);
                }
 #else
-               if (*SP)
-                {
-                   if (mod && SvPADTMP(*SP) && !IS_PADGV(*SP))
+                if (*SP) {
+                   if (mod && SvPADTMP(*SP)) {
                        *SP = sv_mortalcopy(*SP);
+                   }
                   SvTEMP_off((*SP));
                }
 #endif
@@ -1769,7 +1781,7 @@ PP(pp_repeat)
 
 PP(pp_subtract)
 {
-    dVAR; dSP; dATARGET; bool useleft; SV *svl, *svr;
+    dSP; dATARGET; bool useleft; SV *svl, *svr;
     tryAMAGICbin_MG(subtr_amg, AMGf_assign|AMGf_numeric);
     svr = TOPs;
     svl = TOPm1s;
@@ -1888,7 +1900,7 @@ PP(pp_subtract)
 
 PP(pp_left_shift)
 {
-    dVAR; dSP; dATARGET; SV *svl, *svr;
+    dSP; dATARGET; SV *svl, *svr;
     tryAMAGICbin_MG(lshift_amg, AMGf_assign|AMGf_numeric);
     svr = POPs;
     svl = TOPs;
@@ -1908,7 +1920,7 @@ PP(pp_left_shift)
 
 PP(pp_right_shift)
 {
-    dVAR; dSP; dATARGET; SV *svl, *svr;
+    dSP; dATARGET; SV *svl, *svr;
     tryAMAGICbin_MG(rshift_amg, AMGf_assign|AMGf_numeric);
     svr = POPs;
     svl = TOPs;
@@ -1928,7 +1940,7 @@ PP(pp_right_shift)
 
 PP(pp_lt)
 {
-    dVAR; dSP;
+    dSP;
     SV *left, *right;
 
     tryAMAGICbin_MG(lt_amg, AMGf_set|AMGf_numeric);
@@ -1944,7 +1956,7 @@ PP(pp_lt)
 
 PP(pp_gt)
 {
-    dVAR; dSP;
+    dSP;
     SV *left, *right;
 
     tryAMAGICbin_MG(gt_amg, AMGf_set|AMGf_numeric);
@@ -1960,7 +1972,7 @@ PP(pp_gt)
 
 PP(pp_le)
 {
-    dVAR; dSP;
+    dSP;
     SV *left, *right;
 
     tryAMAGICbin_MG(le_amg, AMGf_set|AMGf_numeric);
@@ -1976,7 +1988,7 @@ PP(pp_le)
 
 PP(pp_ge)
 {
-    dVAR; dSP;
+    dSP;
     SV *left, *right;
 
     tryAMAGICbin_MG(ge_amg, AMGf_set|AMGf_numeric);
@@ -1992,7 +2004,7 @@ PP(pp_ge)
 
 PP(pp_ne)
 {
-    dVAR; dSP;
+    dSP;
     SV *left, *right;
 
     tryAMAGICbin_MG(ne_amg, AMGf_set|AMGf_numeric);
@@ -2015,8 +2027,6 @@ PP(pp_ne)
 I32
 Perl_do_ncmp(pTHX_ SV* const left, SV * const right)
 {
-    dVAR;
-
     PERL_ARGS_ASSERT_DO_NCMP;
 #ifdef PERL_PRESERVE_IVUV
     /* Fortunately it seems NaN isn't IOK */
@@ -2082,7 +2092,7 @@ Perl_do_ncmp(pTHX_ SV* const left, SV * const right)
 
 PP(pp_ncmp)
 {
-    dVAR; dSP;
+    dSP;
     SV *left, *right;
     I32 value;
     tryAMAGICbin_MG(ncmp_amg, AMGf_numeric);
@@ -2099,9 +2109,12 @@ PP(pp_ncmp)
     RETURN;
 }
 
+
+/* also used for: pp_sge() pp_sgt() pp_slt() */
+
 PP(pp_sle)
 {
-    dVAR; dSP;
+    dSP;
 
     int amg_type = sle_amg;
     int multiplier = 1;
@@ -2129,9 +2142,13 @@ PP(pp_sle)
     tryAMAGICbin_MG(amg_type, AMGf_set);
     {
       dPOPTOPssrl;
-      const int cmp = (IN_LOCALE_RUNTIME
-                ? sv_cmp_locale_flags(left, right, 0)
-                : sv_cmp_flags(left, right, 0));
+      const int cmp =
+#ifdef USE_LOCALE_COLLATE
+                      (IN_LC_RUNTIME(LC_COLLATE))
+                     ? sv_cmp_locale_flags(left, right, 0)
+                      :
+#endif
+                       sv_cmp_flags(left, right, 0);
       SETs(boolSV(cmp * multiplier < rhs));
       RETURN;
     }
@@ -2139,7 +2156,7 @@ PP(pp_sle)
 
 PP(pp_seq)
 {
-    dVAR; dSP;
+    dSP;
     tryAMAGICbin_MG(seq_amg, AMGf_set);
     {
       dPOPTOPssrl;
@@ -2150,7 +2167,7 @@ PP(pp_seq)
 
 PP(pp_sne)
 {
-    dVAR; dSP;
+    dSP;
     tryAMAGICbin_MG(sne_amg, AMGf_set);
     {
       dPOPTOPssrl;
@@ -2161,13 +2178,17 @@ PP(pp_sne)
 
 PP(pp_scmp)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     tryAMAGICbin_MG(scmp_amg, 0);
     {
       dPOPTOPssrl;
-      const int cmp = (IN_LOCALE_RUNTIME
-                ? sv_cmp_locale_flags(left, right, 0)
-                : sv_cmp_flags(left, right, 0));
+      const int cmp =
+#ifdef USE_LOCALE_COLLATE
+                      (IN_LC_RUNTIME(LC_COLLATE))
+                     ? sv_cmp_locale_flags(left, right, 0)
+                     :
+#endif
+                        sv_cmp_flags(left, right, 0);
       SETi( cmp );
       RETURN;
     }
@@ -2175,7 +2196,7 @@ PP(pp_scmp)
 
 PP(pp_bit_and)
 {
-    dVAR; dSP; dATARGET;
+    dSP; dATARGET;
     tryAMAGICbin_MG(band_amg, AMGf_assign);
     {
       dPOPTOPssrl;
@@ -2201,9 +2222,12 @@ PP(pp_bit_and)
     }
 }
 
+
+/* also used for: pp_bit_xor() */
+
 PP(pp_bit_or)
 {
-    dVAR; dSP; dATARGET;
+    dSP; dATARGET;
     const int op_type = PL_op->op_type;
 
     tryAMAGICbin_MG((op_type == OP_BIT_OR ? bor_amg : bxor_amg), AMGf_assign);
@@ -2260,7 +2284,7 @@ S_negate_string(pTHX)
 
 PP(pp_negate)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     tryAMAGICun_MG(neg_amg, AMGf_numeric);
     if (S_negate_string(aTHX)) return NORMAL;
     {
@@ -2304,7 +2328,7 @@ PP(pp_negate)
 
 PP(pp_not)
 {
-    dVAR; dSP;
+    dSP;
     tryAMAGICun_MG(not_amg, AMGf_set);
     *PL_stack_sp = boolSV(!SvTRUE_nomg(*PL_stack_sp));
     return NORMAL;
@@ -2312,7 +2336,7 @@ PP(pp_not)
 
 PP(pp_complement)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     tryAMAGICun_MG(compl_amg, AMGf_numeric);
     {
       dTOPss;
@@ -2413,7 +2437,7 @@ PP(pp_complement)
 
 PP(pp_i_multiply)
 {
-    dVAR; dSP; dATARGET;
+    dSP; dATARGET;
     tryAMAGICbin_MG(mult_amg, AMGf_assign);
     {
       dPOPTOPiirl_nomg;
@@ -2425,7 +2449,7 @@ PP(pp_i_multiply)
 PP(pp_i_divide)
 {
     IV num;
-    dVAR; dSP; dATARGET;
+    dSP; dATARGET;
     tryAMAGICbin_MG(div_amg, AMGf_assign);
     {
       dPOPTOPssrl;
@@ -2452,7 +2476,7 @@ PP(pp_i_modulo)
 #endif
 {
      /* This is the vanilla old i_modulo. */
-     dVAR; dSP; dATARGET;
+     dSP; dATARGET;
      tryAMAGICbin_MG(modulo_amg, AMGf_assign);
      {
          dPOPTOPiirl_nomg;
@@ -2475,7 +2499,7 @@ PP(pp_i_modulo_1)
      /* This is the i_modulo with the workaround for the _moddi3 bug
       * in (at least) glibc 2.2.5 (the PERL_ABS() the workaround).
       * See below for pp_i_modulo. */
-     dVAR; dSP; dATARGET;
+     dSP; dATARGET;
      tryAMAGICbin_MG(modulo_amg, AMGf_assign);
      {
          dPOPTOPiirl_nomg;
@@ -2536,7 +2560,7 @@ PP(pp_i_modulo)
 
 PP(pp_i_add)
 {
-    dVAR; dSP; dATARGET;
+    dSP; dATARGET;
     tryAMAGICbin_MG(add_amg, AMGf_assign);
     {
       dPOPTOPiirl_ul_nomg;
@@ -2547,7 +2571,7 @@ PP(pp_i_add)
 
 PP(pp_i_subtract)
 {
-    dVAR; dSP; dATARGET;
+    dSP; dATARGET;
     tryAMAGICbin_MG(subtr_amg, AMGf_assign);
     {
       dPOPTOPiirl_ul_nomg;
@@ -2558,7 +2582,7 @@ PP(pp_i_subtract)
 
 PP(pp_i_lt)
 {
-    dVAR; dSP;
+    dSP;
     tryAMAGICbin_MG(lt_amg, AMGf_set);
     {
       dPOPTOPiirl_nomg;
@@ -2569,7 +2593,7 @@ PP(pp_i_lt)
 
 PP(pp_i_gt)
 {
-    dVAR; dSP;
+    dSP;
     tryAMAGICbin_MG(gt_amg, AMGf_set);
     {
       dPOPTOPiirl_nomg;
@@ -2580,7 +2604,7 @@ PP(pp_i_gt)
 
 PP(pp_i_le)
 {
-    dVAR; dSP;
+    dSP;
     tryAMAGICbin_MG(le_amg, AMGf_set);
     {
       dPOPTOPiirl_nomg;
@@ -2591,7 +2615,7 @@ PP(pp_i_le)
 
 PP(pp_i_ge)
 {
-    dVAR; dSP;
+    dSP;
     tryAMAGICbin_MG(ge_amg, AMGf_set);
     {
       dPOPTOPiirl_nomg;
@@ -2602,7 +2626,7 @@ PP(pp_i_ge)
 
 PP(pp_i_eq)
 {
-    dVAR; dSP;
+    dSP;
     tryAMAGICbin_MG(eq_amg, AMGf_set);
     {
       dPOPTOPiirl_nomg;
@@ -2613,7 +2637,7 @@ PP(pp_i_eq)
 
 PP(pp_i_ne)
 {
-    dVAR; dSP;
+    dSP;
     tryAMAGICbin_MG(ne_amg, AMGf_set);
     {
       dPOPTOPiirl_nomg;
@@ -2624,7 +2648,7 @@ PP(pp_i_ne)
 
 PP(pp_i_ncmp)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     tryAMAGICbin_MG(ncmp_amg, 0);
     {
       dPOPTOPiirl_nomg;
@@ -2643,7 +2667,7 @@ PP(pp_i_ncmp)
 
 PP(pp_i_negate)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     tryAMAGICun_MG(neg_amg, 0);
     if (S_negate_string(aTHX)) return NORMAL;
     {
@@ -2658,7 +2682,7 @@ PP(pp_i_negate)
 
 PP(pp_atan2)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     tryAMAGICbin_MG(atan2_amg, 0);
     {
       dPOPTOPnnrl_nomg;
@@ -2667,48 +2691,47 @@ PP(pp_atan2)
     }
 }
 
+
+/* also used for: pp_cos() pp_exp() pp_log() pp_sqrt() */
+
 PP(pp_sin)
 {
-    dVAR; dSP; dTARGET;
-    int amg_type = sin_amg;
+    dSP; dTARGET;
+    int amg_type = fallback_amg;
     const char *neg_report = NULL;
-    NV (*func)(NV) = Perl_sin;
     const int op_type = PL_op->op_type;
 
     switch (op_type) {
-    case OP_COS:
-       amg_type = cos_amg;
-       func = Perl_cos;
-       break;
-    case OP_EXP:
-       amg_type = exp_amg;
-       func = Perl_exp;
-       break;
-    case OP_LOG:
-       amg_type = log_amg;
-       func = Perl_log;
-       neg_report = "log";
-       break;
-    case OP_SQRT:
-       amg_type = sqrt_amg;
-       func = Perl_sqrt;
-       neg_report = "sqrt";
-       break;
+    case OP_SIN:  amg_type = sin_amg; break;
+    case OP_COS:  amg_type = cos_amg; break;
+    case OP_EXP:  amg_type = exp_amg; break;
+    case OP_LOG:  amg_type = log_amg;  neg_report = "log";  break;
+    case OP_SQRT: amg_type = sqrt_amg; neg_report = "sqrt"; break;
     }
 
+    assert(amg_type != fallback_amg);
 
     tryAMAGICun_MG(amg_type, 0);
     {
       SV * const arg = POPs;
       const NV value = SvNV_nomg(arg);
-      if (neg_report) {
+      NV result = NV_NAN;
+      if (neg_report) { /* log or sqrt */
          if (op_type == OP_LOG ? (value <= 0.0) : (value < 0.0)) {
              SET_NUMERIC_STANDARD();
              /* diag_listed_as: Can't take log of %g */
              DIE(aTHX_ "Can't take %s of %"NVgf, neg_report, value);
          }
       }
-      XPUSHn(func(value));
+      switch (op_type) {
+      default:
+      case OP_SIN:  result = Perl_sin(value);  break;
+      case OP_COS:  result = Perl_cos(value);  break;
+      case OP_EXP:  result = Perl_exp(value);  break;
+      case OP_LOG:  result = Perl_log(value);  break;
+      case OP_SQRT: result = Perl_sqrt(value); break;
+      }
+      XPUSHn(result);
       RETURN;
     }
 }
@@ -2726,7 +2749,6 @@ PP(pp_sin)
 
 PP(pp_rand)
 {
-    dVAR;
     if (!PL_srand_called) {
        (void)seedDrand01((Rand_seed_t)seed());
        PL_srand_called = TRUE;
@@ -2761,7 +2783,7 @@ PP(pp_rand)
 
 PP(pp_srand)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     UV anum;
 
     if (MAXARG >= 1 && (TOPs || POPs)) {
@@ -2799,7 +2821,7 @@ PP(pp_srand)
 
 PP(pp_int)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     tryAMAGICun_MG(int_amg, AMGf_numeric);
     {
       SV * const sv = TOPs;
@@ -2820,7 +2842,9 @@ PP(pp_int)
       }
       else {
          const NV value = SvNV_nomg(sv);
-         if (value >= 0.0) {
+          if (SvNOK(sv) && UNLIKELY(Perl_isinfnan(SvNV(sv))))
+              SETn(SvNV(sv));
+         else if (value >= 0.0) {
              if (value < (NV)UV_MAX + 0.5) {
                  SETu(U_V(value));
              } else {
@@ -2841,7 +2865,7 @@ PP(pp_int)
 
 PP(pp_abs)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     tryAMAGICun_MG(abs_amg, AMGf_numeric);
     {
       SV * const sv = TOPs;
@@ -2879,9 +2903,12 @@ PP(pp_abs)
     RETURN;
 }
 
+
+/* also used for: pp_hex() */
+
 PP(pp_oct)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     const char *tmps;
     I32 flags = PERL_SCAN_ALLOW_UNDERSCORES;
     STRLEN len;
@@ -2906,11 +2933,11 @@ PP(pp_oct)
         tmps++, len--;
     if (*tmps == '0')
         tmps++, len--;
-    if (*tmps == 'x' || *tmps == 'X') {
+    if (isALPHA_FOLD_EQ(*tmps, 'x')) {
     hex:
         result_uv = grok_hex (tmps, &len, &flags, &result_nv);
     }
-    else if (*tmps == 'b' || *tmps == 'B')
+    else if (isALPHA_FOLD_EQ(*tmps, 'b'))
         result_uv = grok_bin (tmps, &len, &flags, &result_nv);
     else
         result_uv = grok_oct (tmps, &len, &flags, &result_nv);
@@ -2928,27 +2955,48 @@ PP(pp_oct)
 
 PP(pp_length)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     SV * const sv = TOPs;
 
-    SvGETMAGIC(sv);
+    U32 in_bytes = IN_BYTES;
+    /* simplest case shortcut */
+    /* turn off SVf_UTF8 in tmp flags if HINT_BYTES on*/
+    U32 svflags = (SvFLAGS(sv) ^ (in_bytes << 26)) & (SVf_POK|SVs_GMG|SVf_UTF8);
+    assert(HINT_BYTES == 0x00000008 && SVf_UTF8 == 0x20000000 && (SVf_UTF8 == HINT_BYTES << 26));
+    SETs(TARG);
+
+    if(LIKELY(svflags == SVf_POK))
+        goto simple_pv;
+    if(svflags & SVs_GMG)
+        mg_get(sv);
     if (SvOK(sv)) {
-       if (!IN_BYTES)
-           SETi(sv_len_utf8_nomg(sv));
+       if (!IN_BYTES) /* reread to avoid using an C auto/register */
+           sv_setiv(TARG, (IV)sv_len_utf8_nomg(sv));
        else
        {
            STRLEN len;
-           (void)SvPV_nomg_const(sv,len);
-           SETi(len);
+            /* unrolled SvPV_nomg_const(sv,len) */
+            if(SvPOK_nog(sv)){
+                simple_pv:
+                len = SvCUR(sv);
+            } else  {
+                (void)sv_2pv_flags(sv, &len, 0|SV_CONST_RETURN);
+            }
+           sv_setiv(TARG, (IV)(len));
        }
     } else {
        if (!SvPADTMP(TARG)) {
            sv_setsv_nomg(TARG, &PL_sv_undef);
-           SETTARG;
-       }
-       SETs(&PL_sv_undef);
+       } else { /* TARG is on stack at this point and is overwriten by SETs.
+                   This branch is the odd one out, so put TARG by default on
+                   stack earlier to let local SP go out of liveness sooner */
+            SETs(&PL_sv_undef);
+            goto no_set_magic;
+        }
     }
-    RETURN;
+    SvSETMAGIC(TARG);
+    no_set_magic:
+    return NORMAL; /* no putback, SP didn't move in this opcode */
 }
 
 /* Returns false if substring is completely outside original string.
@@ -2956,10 +3004,10 @@ PP(pp_length)
    always be true for an explicit 0.
 */
 bool
-Perl_translate_substr_offsets(pTHX_ STRLEN curlen, IV pos1_iv,
-                                   bool pos1_is_uv, IV len_iv,
-                                   bool len_is_uv, STRLEN *posp,
-                                   STRLEN *lenp)
+Perl_translate_substr_offsets( STRLEN curlen, IV pos1_iv,
+                               bool pos1_is_uv, IV len_iv,
+                               bool len_is_uv, STRLEN *posp,
+                               STRLEN *lenp)
 {
     IV pos2_iv;
     int    pos2_is_uv;
@@ -3020,7 +3068,7 @@ Perl_translate_substr_offsets(pTHX_ STRLEN curlen, IV pos1_iv,
 
 PP(pp_substr)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     SV *sv;
     STRLEN curlen;
     STRLEN utf8_curlen;
@@ -3159,7 +3207,7 @@ bound_fail:
 
 PP(pp_vec)
 {
-    dVAR; dSP;
+    dSP;
     const IV size   = POPi;
     const IV offset = POPi;
     SV * const src = POPs;
@@ -3185,16 +3233,19 @@ PP(pp_vec)
     RETURN;
 }
 
+
+/* also used for: pp_rindex() */
+
 PP(pp_index)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     SV *big;
     SV *little;
     SV *temp = NULL;
     STRLEN biglen;
     STRLEN llen = 0;
-    I32 offset;
-    I32 retval;
+    SSize_t offset = 0;
+    SSize_t retval;
     const char *big_p;
     const char *little_p;
     bool big_utf8;
@@ -3277,13 +3328,13 @@ PP(pp_index)
        offset = is_index ? 0 : biglen;
     else {
        if (big_utf8 && offset > 0)
-           sv_pos_u2b(big, &offset, 0);
+           offset = sv_pos_u2b_flags(big, offset, 0, SV_CONST_RETURN);
        if (!is_index)
            offset += llen;
     }
     if (offset < 0)
        offset = 0;
-    else if (offset > (I32)biglen)
+    else if (offset > (SSize_t)biglen)
        offset = biglen;
     if (!(little_p = is_index
          ? fbm_instr((unsigned char*)big_p + offset,
@@ -3294,7 +3345,7 @@ PP(pp_index)
     else {
        retval = little_p - big_p;
        if (retval > 0 && big_utf8)
-           sv_pos_b2u(big, &retval);
+           retval = sv_pos_b2u_flags(big, retval, SV_CONST_RETURN);
     }
     SvREFCNT_dec(temp);
  fail:
@@ -3304,7 +3355,7 @@ PP(pp_index)
 
 PP(pp_sprintf)
 {
-    dVAR; dSP; dMARK; dORIGMARK; dTARGET;
+    dSP; dMARK; dORIGMARK; dTARGET;
     SvTAINTED_off(TARG);
     do_sprintf(TARG, SP-MARK, MARK+1);
     TAINT_IF(SvTAINTED(TARG));
@@ -3315,7 +3366,7 @@ PP(pp_sprintf)
 
 PP(pp_ord)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
 
     SV *argsv = POPs;
     STRLEN len;
@@ -3324,41 +3375,46 @@ PP(pp_ord)
     if (PL_encoding && SvPOK(argsv) && !DO_UTF8(argsv)) {
         SV * const tmpsv = sv_2mortal(newSVsv(argsv));
         s = (U8*)sv_recode_to_utf8(tmpsv, PL_encoding);
+        len = UTF8SKIP(s);  /* Should be well-formed; so this is its length */
         argsv = tmpsv;
     }
 
     XPUSHu(DO_UTF8(argsv)
-           ? utf8n_to_uvchr(s, UTF8_MAXBYTES, 0, UTF8_ALLOW_ANYUV)
-           : (UV)(*s & 0xff));
+           ? utf8n_to_uvchr(s, len, 0, UTF8_ALLOW_ANYUV)
+           : (UV)(*s));
 
     RETURN;
 }
 
 PP(pp_chr)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     char *tmps;
     UV value;
     SV *top = POPs;
 
     SvGETMAGIC(top);
-    if (!IN_BYTES /* under bytes, chr(-1) eq chr(0xff), etc. */
-     && ((SvIOKp(top) && !SvIsUV(top) && SvIV_nomg(top) < 0)
-        ||
-        ((SvNOKp(top) || (SvOK(top) && !SvIsUV(top)))
-         && SvNV_nomg(top) < 0.0))) {
+    if (UNLIKELY(isinfnansv(top)))
+        Perl_croak(aTHX_ "Cannot chr %"NVgf, SvNV(top));
+    else {
+        if (!IN_BYTES /* under bytes, chr(-1) eq chr(0xff), etc. */
+            && ((SvIOKp(top) && !SvIsUV(top) && SvIV_nomg(top) < 0)
+                ||
+                ((SvNOKp(top) || (SvOK(top) && !SvIsUV(top)))
+                 && SvNV_nomg(top) < 0.0))) {
            if (ckWARN(WARN_UTF8)) {
                if (SvGMAGICAL(top)) {
                    SV *top2 = sv_newmortal();
                    sv_setsv_nomg(top2, top);
                    top = top2;
                }
-               Perl_warner(aTHX_ packWARN(WARN_UTF8),
-                          "Invalid negative number (%"SVf") in chr", top);
-           }
-           value = UNICODE_REPLACEMENT;
-    } else {
-       value = SvUV_nomg(top);
+                Perl_warner(aTHX_ packWARN(WARN_UTF8),
+                            "Invalid negative number (%"SVf") in chr", SVfARG(top));
+            }
+            value = UNICODE_REPLACEMENT;
+        } else {
+            value = SvUV_nomg(top);
+        }
     }
 
     SvUPGRADE(TARG,SVt_PV);
@@ -3404,7 +3460,7 @@ PP(pp_chr)
 PP(pp_crypt)
 {
 #ifdef HAS_CRYPT
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     dPOPTOPssrl;
     STRLEN len;
     const char *tmps = SvPV_const(left, len);
@@ -3453,6 +3509,9 @@ PP(pp_crypt)
 /* Generally UTF-8 and UTF-EBCDIC are indistinguishable at this level.  So 
  * most comments below say UTF-8, when in fact they mean UTF-EBCDIC as well */
 
+
+/* also used for: pp_lcfirst() */
+
 PP(pp_ucfirst)
 {
     /* Actually is both lcfirst() and ucfirst().  Only the first character
@@ -3460,7 +3519,6 @@ PP(pp_ucfirst)
      * take the source and change that one character and store it back, but not
      * if read-only etc, or if the length changes */
 
-    dVAR;
     dSP;
     SV *source = TOPs;
     STRLEN slen; /* slen is the byte length of the whole SV. */
@@ -3478,22 +3536,16 @@ PP(pp_ucfirst)
     STRLEN tculen;  /* tculen is the byte length of the freshly titlecased (or
                     * lowercased) character stored in tmpbuf.  May be either
                     * UTF-8 or not, but in either case is the number of bytes */
-    bool tainted = FALSE;
 
-    SvGETMAGIC(source);
-    if (SvOK(source)) {
-       s = (const U8*)SvPV_nomg_const(source, slen);
-    } else {
-       if (ckWARN(WARN_UNINITIALIZED))
-           report_uninit(source);
-       s = (const U8*)"";
-       slen = 0;
-    }
+    s = (const U8*)SvPV_const(source, slen);
 
     /* We may be able to get away with changing only the first character, in
      * place, but not if read-only, etc.  Later we may discover more reasons to
      * not convert in-place. */
-    inplace = SvPADTMP(source) && !SvREADONLY(source) && SvTEMP(source);
+    inplace = !SvREADONLY(source)
+          && (  SvPADTMP(source)
+             || (  SvTEMP(source) && !SvSMAGICAL(source)
+                && SvREFCNT(source) == 1));
 
     /* First calculate what the changed first character should be.  This affects
      * whether we can just swap it out, leaving the rest of the string unchanged,
@@ -3507,12 +3559,18 @@ PP(pp_ucfirst)
        doing_utf8 = TRUE;
         ulen = UTF8SKIP(s);
         if (op_type == OP_UCFIRST) {
-           _to_utf8_title_flags(s, tmpbuf, &tculen,
-                                cBOOL(IN_LOCALE_RUNTIME), &tainted);
+#ifdef USE_LOCALE_CTYPE
+           _to_utf8_title_flags(s, tmpbuf, &tculen, IN_LC_RUNTIME(LC_CTYPE));
+#else
+           _to_utf8_title_flags(s, tmpbuf, &tculen, 0);
+#endif
        }
         else {
-           _to_utf8_lower_flags(s, tmpbuf, &tculen,
-                                cBOOL(IN_LOCALE_RUNTIME), &tainted);
+#ifdef USE_LOCALE_CTYPE
+           _to_utf8_lower_flags(s, tmpbuf, &tculen, IN_LC_RUNTIME(LC_CTYPE));
+#else
+           _to_utf8_lower_flags(s, tmpbuf, &tculen, 0);
+#endif
        }
 
         /* we can't do in-place if the length changes.  */
@@ -3530,22 +3588,42 @@ PP(pp_ucfirst)
        if (op_type == OP_LCFIRST) {
 
            /* lower case the first letter: no trickiness for any character */
-           *tmpbuf = (IN_LOCALE_RUNTIME) ? toLOWER_LC(*s) :
-                       ((IN_UNI_8_BIT) ? toLOWER_LATIN1(*s) : toLOWER(*s));
+            *tmpbuf =
+#ifdef USE_LOCALE_CTYPE
+                      (IN_LC_RUNTIME(LC_CTYPE))
+                      ? toLOWER_LC(*s)
+                      :
+#endif
+                         (IN_UNI_8_BIT)
+                         ? toLOWER_LATIN1(*s)
+                         : toLOWER(*s);
        }
        /* is ucfirst() */
-       else if (IN_LOCALE_RUNTIME) {
-           *tmpbuf = toUPPER_LC(*s);   /* This would be a bug if any locales
-                                        * have upper and title case different
-                                        */
+#ifdef USE_LOCALE_CTYPE
+       else if (IN_LC_RUNTIME(LC_CTYPE)) {
+            if (IN_UTF8_CTYPE_LOCALE) {
+                goto do_uni_rules;
+            }
+
+            *tmpbuf = (U8) toUPPER_LC(*s); /* This would be a bug if any
+                                              locales have upper and title case
+                                              different */
        }
+#endif
        else if (! IN_UNI_8_BIT) {
            *tmpbuf = toUPPER(*s);      /* Returns caseless for non-ascii, or
                                         * on EBCDIC machines whatever the
                                         * native function does */
        }
-       else { /* is ucfirst non-UTF-8, not in locale, and cased latin1 */
-           UV title_ord = _to_upper_title_latin1(*s, tmpbuf, &tculen, 's');
+        else {
+            /* Here, is ucfirst non-UTF-8, not in locale (unless that locale is
+             * UTF-8, which we treat as not in locale), and cased latin1 */
+           UV title_ord;
+#ifdef USE_LOCALE_CTYPE
+      do_uni_rules:
+#endif
+
+           title_ord = _to_upper_title_latin1(*s, tmpbuf, &tculen, 's');
            if (tculen > 1) {
                assert(tculen == 2);
 
@@ -3646,17 +3724,9 @@ PP(pp_ucfirst)
            SvCUR_set(dest, need - 1);
        }
 
-       if (tainted) {
-           TAINT;
-           SvTAINTED_on(dest);
-       }
     }
     else {  /* Neither source nor dest are in or need to be UTF-8 */
        if (slen) {
-           if (IN_LOCALE_RUNTIME) {
-               TAINT;
-               SvTAINTED_on(dest);
-           }
            if (inplace) {  /* in-place, only need to change the 1st char */
                *d = *tmpbuf;
            }
@@ -3684,6 +3754,12 @@ PP(pp_ucfirst)
            SvCUR_set(dest, need - 1);
        }
     }
+#ifdef USE_LOCALE_CTYPE
+    if (IN_LC_RUNTIME(LC_CTYPE)) {
+        TAINT;
+        SvTAINTED_on(dest);
+    }
+#endif
     if (dest != source && SvTAINTED(source))
        SvTAINT(dest);
     SvSETMAGIC(dest);
@@ -3695,7 +3771,6 @@ PP(pp_ucfirst)
    of the three tight loops.  There is less and less commonality though */
 PP(pp_uc)
 {
-    dVAR;
     dSP;
     SV *source = TOPs;
     STRLEN len;
@@ -3706,17 +3781,29 @@ PP(pp_uc)
 
     SvGETMAGIC(source);
 
-    if (SvPADTMP(source) && !SvREADONLY(source) && !SvAMAGIC(source)
-       && SvTEMP(source) && !DO_UTF8(source)
-       && (IN_LOCALE_RUNTIME || ! IN_UNI_8_BIT)) {
-
-       /* We can convert in place.  The reason we can't if in UNI_8_BIT is to
-        * make the loop tight, so we overwrite the source with the dest before
-        * looking at it, and we need to look at the original source
-        * afterwards.  There would also need to be code added to handle
-        * switching to not in-place in midstream if we run into characters
-        * that change the length.
-        */
+    if ((SvPADTMP(source)
+        ||
+       (SvTEMP(source) && !SvSMAGICAL(source) && SvREFCNT(source) == 1))
+       && !SvREADONLY(source) && SvPOK(source)
+       && !DO_UTF8(source)
+       && (
+#ifdef USE_LOCALE_CTYPE
+            (IN_LC_RUNTIME(LC_CTYPE))
+            ? ! IN_UTF8_CTYPE_LOCALE
+            :
+#endif
+              ! IN_UNI_8_BIT))
+    {
+
+        /* We can convert in place.  The reason we can't if in UNI_8_BIT is to
+         * make the loop tight, so we overwrite the source with the dest before
+         * looking at it, and we need to look at the original source
+         * afterwards.  There would also need to be code added to handle
+         * switching to not in-place in midstream if we run into characters
+         * that change the length.  Since being in locale overrides UNI_8_BIT,
+         * that latter becomes irrelevant in the above test; instead for
+         * locale, the size can't normally change, except if the locale is a
+         * UTF-8 one */
        dest = source;
        s = d = (U8*)SvPV_force_nomg(source, len);
        min = len + 1;
@@ -3725,21 +3812,7 @@ PP(pp_uc)
 
        dest = TARG;
 
-       /* The old implementation would copy source into TARG at this point.
-          This had the side effect that if source was undef, TARG was now
-          an undefined SV with PADTMP set, and they don't warn inside
-          sv_2pv_flags(). However, we're now getting the PV direct from
-          source, which doesn't have PADTMP set, so it would warn. Hence the
-          little games.  */
-
-       if (SvOK(source)) {
-           s = (const U8*)SvPV_nomg_const(source, len);
-       } else {
-           if (ckWARN(WARN_UNINITIALIZED))
-               report_uninit(source);
-           s = (const U8*)"";
-           len = 0;
-       }
+       s = (const U8*)SvPV_nomg_const(source, len);
        min = len + 1;
 
        SvUPGRADE(dest, SVt_PV);
@@ -3755,7 +3828,6 @@ PP(pp_uc)
     if (DO_UTF8(source)) {
        const U8 *const send = s + len;
        U8 tmpbuf[UTF8_MAXBYTES_CASE+1];
-       bool tainted = FALSE;
 
        /* All occurrences of these are to be moved to follow any other marks.
         * This is context-dependent.  We may not be passed enough context to
@@ -3785,8 +3857,11 @@ PP(pp_uc)
              * and copy it to the output buffer */
 
             u = UTF8SKIP(s);
-            uv = _to_utf8_upper_flags(s, tmpbuf, &ulen,
-                                     cBOOL(IN_LOCALE_RUNTIME), &tainted);
+#ifdef USE_LOCALE_CTYPE
+            uv = _to_utf8_upper_flags(s, tmpbuf, &ulen, IN_LC_RUNTIME(LC_CTYPE));
+#else
+            uv = _to_utf8_upper_flags(s, tmpbuf, &ulen, 0);
+#endif
 #define GREEK_CAPITAL_LETTER_IOTA 0x0399
 #define COMBINING_GREEK_YPOGEGRAMMENI 0x0345
             if (uv == GREEK_CAPITAL_LETTER_IOTA
@@ -3821,10 +3896,6 @@ PP(pp_uc)
        *d = '\0';
 
        SvCUR_set(dest, d - (U8*)SvPVX_const(dest));
-       if (tainted) {
-           TAINT;
-           SvTAINTED_on(dest);
-       }
     }
     else {     /* Not UTF-8 */
        if (len) {
@@ -3833,18 +3904,25 @@ PP(pp_uc)
            /* Use locale casing if in locale; regular style if not treating
             * latin1 as having case; otherwise the latin1 casing.  Do the
             * whole thing in a tight loop, for speed, */
-           if (IN_LOCALE_RUNTIME) {
-               TAINT;
-               SvTAINTED_on(dest);
+#ifdef USE_LOCALE_CTYPE
+           if (IN_LC_RUNTIME(LC_CTYPE)) {
+                if (IN_UTF8_CTYPE_LOCALE) {
+                    goto do_uni_rules;
+                }
                for (; s < send; d++, s++)
-                   *d = toUPPER_LC(*s);
+                    *d = (U8) toUPPER_LC(*s);
            }
-           else if (! IN_UNI_8_BIT) {
+           else
+#endif
+                 if (! IN_UNI_8_BIT) {
                for (; s < send; d++, s++) {
                    *d = toUPPER(*s);
                }
            }
            else {
+#ifdef USE_LOCALE_CTYPE
+          do_uni_rules:
+#endif
                for (; s < send; d++, s++) {
                    *d = toUPPER_LATIN1_MOD(*s);
                    if (LIKELY(*d != LATIN_SMALL_LETTER_Y_WITH_DIAERESIS)) {
@@ -3933,6 +4011,12 @@ PP(pp_uc)
            SvCUR_set(dest, d - (U8*)SvPVX_const(dest));
        }
     } /* End of isn't utf8 */
+#ifdef USE_LOCALE_CTYPE
+    if (IN_LC_RUNTIME(LC_CTYPE)) {
+        TAINT;
+        SvTAINTED_on(dest);
+    }
+#endif
     if (dest != source && SvTAINTED(source))
        SvTAINT(dest);
     SvSETMAGIC(dest);
@@ -3941,7 +4025,6 @@ PP(pp_uc)
 
 PP(pp_lc)
 {
-    dVAR;
     dSP;
     SV *source = TOPs;
     STRLEN len;
@@ -3952,8 +4035,12 @@ PP(pp_lc)
 
     SvGETMAGIC(source);
 
-    if (SvPADTMP(source) && !SvREADONLY(source) && !SvAMAGIC(source)
-       && SvTEMP(source) && !DO_UTF8(source)) {
+    if (   (  SvPADTMP(source)
+          || (  SvTEMP(source) && !SvSMAGICAL(source)
+             && SvREFCNT(source) == 1  )
+          )
+       && !SvREADONLY(source) && SvPOK(source)
+       && !DO_UTF8(source)) {
 
        /* We can convert in place, as lowercasing anything in the latin1 range
         * (or else DO_UTF8 would have been on) doesn't lengthen it */
@@ -3965,21 +4052,7 @@ PP(pp_lc)
 
        dest = TARG;
 
-       /* The old implementation would copy source into TARG at this point.
-          This had the side effect that if source was undef, TARG was now
-          an undefined SV with PADTMP set, and they don't warn inside
-          sv_2pv_flags(). However, we're now getting the PV direct from
-          source, which doesn't have PADTMP set, so it would warn. Hence the
-          little games.  */
-
-       if (SvOK(source)) {
-           s = (const U8*)SvPV_nomg_const(source, len);
-       } else {
-           if (ckWARN(WARN_UNINITIALIZED))
-               report_uninit(source);
-           s = (const U8*)"";
-           len = 0;
-       }
+       s = (const U8*)SvPV_nomg_const(source, len);
        min = len + 1;
 
        SvUPGRADE(dest, SVt_PV);
@@ -3995,17 +4068,19 @@ PP(pp_lc)
     if (DO_UTF8(source)) {
        const U8 *const send = s + len;
        U8 tmpbuf[UTF8_MAXBYTES_CASE+1];
-       bool tainted = FALSE;
 
        while (s < send) {
            const STRLEN u = UTF8SKIP(s);
            STRLEN ulen;
 
-           _to_utf8_lower_flags(s, tmpbuf, &ulen,
-                                cBOOL(IN_LOCALE_RUNTIME), &tainted);
+#ifdef USE_LOCALE_CTYPE
+           _to_utf8_lower_flags(s, tmpbuf, &ulen, IN_LC_RUNTIME(LC_CTYPE));
+#else
+           _to_utf8_lower_flags(s, tmpbuf, &ulen, 0);
+#endif
 
            /* Here is where we would do context-sensitive actions.  See the
-            * commit message for this comment for why there isn't any */
+            * commit message for 86510fb15 for why there isn't any */
 
            if (ulen > u && (SvLEN(dest) < (min += ulen - u))) {
 
@@ -4032,10 +4107,6 @@ PP(pp_lc)
        SvUTF8_on(dest);
        *d = '\0';
        SvCUR_set(dest, d - (U8*)SvPVX_const(dest));
-       if (tainted) {
-           TAINT;
-           SvTAINTED_on(dest);
-       }
     } else {   /* Not utf8 */
        if (len) {
            const U8 *const send = s + len;
@@ -4043,13 +4114,14 @@ PP(pp_lc)
            /* Use locale casing if in locale; regular style if not treating
             * latin1 as having case; otherwise the latin1 casing.  Do the
             * whole thing in a tight loop, for speed, */
-           if (IN_LOCALE_RUNTIME) {
-               TAINT;
-               SvTAINTED_on(dest);
+#ifdef USE_LOCALE_CTYPE
+            if (IN_LC_RUNTIME(LC_CTYPE)) {
                for (; s < send; d++, s++)
                    *d = toLOWER_LC(*s);
-           }
-           else if (! IN_UNI_8_BIT) {
+            }
+           else
+#endif
+            if (! IN_UNI_8_BIT) {
                for (; s < send; d++, s++) {
                    *d = toLOWER(*s);
                }
@@ -4065,6 +4137,12 @@ PP(pp_lc)
            SvCUR_set(dest, d - (U8*)SvPVX_const(dest));
        }
     }
+#ifdef USE_LOCALE_CTYPE
+    if (IN_LC_RUNTIME(LC_CTYPE)) {
+        TAINT;
+        SvTAINTED_on(dest);
+    }
+#endif
     if (dest != source && SvTAINTED(source))
        SvTAINT(dest);
     SvSETMAGIC(dest);
@@ -4073,7 +4151,7 @@ PP(pp_lc)
 
 PP(pp_quotemeta)
 {
-    dVAR; dSP; dTARGET;
+    dSP; dTARGET;
     SV * const sv = TOPs;
     STRLEN len;
     const char *s = SvPV_const(sv,len);
@@ -4095,11 +4173,15 @@ PP(pp_quotemeta)
                    }
                }
                else if (UTF8_IS_DOWNGRADEABLE_START(*s)) {
-
+                   if (
+#ifdef USE_LOCALE_CTYPE
                    /* In locale, we quote all non-ASCII Latin1 chars.
                     * Otherwise use the quoting rules */
-                   if (IN_LOCALE_RUNTIME
-                       || _isQUOTEMETA(TWO_BYTE_UTF8_TO_NATIVE(*s, *(s + 1))))
+                   
+                   IN_LC_RUNTIME(LC_CTYPE)
+                       ||
+#endif
+                       _isQUOTEMETA(TWO_BYTE_UTF8_TO_NATIVE(*s, *(s + 1))))
                    {
                        to_quote = TRUE;
                    }
@@ -4147,7 +4229,6 @@ PP(pp_quotemeta)
 
 PP(pp_fc)
 {
-    dVAR;
     dTARGET;
     dSP;
     SV *source = TOPs;
@@ -4158,9 +4239,13 @@ PP(pp_fc)
     const U8 *send;
     U8 *d;
     U8 tmpbuf[UTF8_MAXBYTES_CASE + 1];
-    const bool full_folding = TRUE;
+    const bool full_folding = TRUE; /* This variable is here so we can easily
+                                       move to more generality later */
     const U8 flags = ( full_folding      ? FOLD_FLAGS_FULL   : 0 )
-                   | ( IN_LOCALE_RUNTIME ? FOLD_FLAGS_LOCALE : 0 );
+#ifdef USE_LOCALE_CTYPE
+                   | ( IN_LC_RUNTIME(LC_CTYPE) ? FOLD_FLAGS_LOCALE : 0 )
+#endif
+    ;
 
     /* This is a facsimile of pp_lc, but with a thousand bugs thanks to me.
      * You are welcome(?) -Hugmeir
@@ -4189,12 +4274,11 @@ PP(pp_fc)
 
     send = s + len;
     if (DO_UTF8(source)) { /* UTF-8 flagged string. */
-        bool tainted = FALSE;
         while (s < send) {
             const STRLEN u = UTF8SKIP(s);
             STRLEN ulen;
 
-            _to_utf8_fold_flags(s, tmpbuf, &ulen, flags, &tainted);
+            _to_utf8_fold_flags(s, tmpbuf, &ulen, flags);
 
             if (ulen > u && (SvLEN(dest) < (min += ulen - u))) {
                 const UV o = d - (U8*)SvPVX_const(dest);
@@ -4207,23 +4291,26 @@ PP(pp_fc)
             s += u;
         }
         SvUTF8_on(dest);
-       if (tainted) {
-           TAINT;
-           SvTAINTED_on(dest);
-       }
     } /* Unflagged string */
     else if (len) {
-        if ( IN_LOCALE_RUNTIME ) { /* Under locale */
-            TAINT;
-            SvTAINTED_on(dest);
+#ifdef USE_LOCALE_CTYPE
+        if ( IN_LC_RUNTIME(LC_CTYPE) ) { /* Under locale */
+            if (IN_UTF8_CTYPE_LOCALE) {
+                goto do_uni_folding;
+            }
             for (; s < send; d++, s++)
-                *d = toFOLD_LC(*s);
+                *d = (U8) toFOLD_LC(*s);
         }
-        else if ( !IN_UNI_8_BIT ) { /* Under nothing, or bytes */
+        else
+#endif
+        if ( !IN_UNI_8_BIT ) { /* Under nothing, or bytes */
             for (; s < send; d++, s++)
                 *d = toFOLD(*s);
         }
         else {
+#ifdef USE_LOCALE_CTYPE
+      do_uni_folding:
+#endif
             /* For ASCII and the Latin-1 range, there's only two troublesome
              * folds, \x{DF} (\N{LATIN SMALL LETTER SHARP S}), which under full
              * casefolding becomes 'ss'; and \x{B5} (\N{MICRO SIGN}), which
@@ -4290,6 +4377,12 @@ PP(pp_fc)
     *d = '\0';
     SvCUR_set(dest, d - (U8*)SvPVX_const(dest));
 
+#ifdef USE_LOCALE_CTYPE
+    if (IN_LC_RUNTIME(LC_CTYPE)) {
+        TAINT;
+        SvTAINTED_on(dest);
+    }
+#endif
     if (SvTAINTED(source))
        SvTAINT(dest);
     SvSETMAGIC(dest);
@@ -4300,7 +4393,7 @@ PP(pp_fc)
 
 PP(pp_aslice)
 {
-    dVAR; dSP; dMARK; dORIGMARK;
+    dSP; dMARK; dORIGMARK;
     AV *const av = MUTABLE_AV(POPs);
     const I32 lval = (PL_op->op_flags & OPf_MOD || LVRET);
 
@@ -4364,7 +4457,7 @@ PP(pp_aslice)
 
 PP(pp_kvaslice)
 {
-    dVAR; dSP; dMARK;
+    dSP; dMARK;
     AV *const av = MUTABLE_AV(POPs);
     I32 lval = (PL_op->op_flags & OPf_MOD);
     SSize_t items = SP - MARK;
@@ -4407,10 +4500,13 @@ PP(pp_kvaslice)
     RETURN;
 }
 
+
 /* Smart dereferencing for keys, values and each */
+
+/* also used for: pp_reach() pp_rvalues() */
+
 PP(pp_rkeys)
 {
-    dVAR;
     dSP;
     dPOPss;
 
@@ -4448,14 +4544,13 @@ PP(pp_rkeys)
 
 PP(pp_aeach)
 {
-    dVAR;
     dSP;
     AV *array = MUTABLE_AV(POPs);
     const I32 gimme = GIMME_V;
     IV *iterp = Perl_av_iter_p(aTHX_ array);
     const IV current = (*iterp)++;
 
-    if (current > av_len(array)) {
+    if (current > av_tindex(array)) {
        *iterp = 0;
        if (gimme == G_SCALAR)
            RETPUSHUNDEF;
@@ -4472,9 +4567,9 @@ PP(pp_aeach)
     RETURN;
 }
 
+/* also used for: pp_avalues()*/
 PP(pp_akeys)
 {
-    dVAR;
     dSP;
     AV *array = MUTABLE_AV(POPs);
     const I32 gimme = GIMME_V;
@@ -4483,7 +4578,7 @@ PP(pp_akeys)
 
     if (gimme == G_SCALAR) {
        dTARGET;
-       PUSHi(av_len(array) + 1);
+       PUSHi(av_tindex(array) + 1);
     }
     else if (gimme == G_ARRAY) {
         IV n = Perl_av_len(aTHX_ array);
@@ -4510,7 +4605,6 @@ PP(pp_akeys)
 
 PP(pp_each)
 {
-    dVAR;
     dSP;
     HV * hash = MUTABLE_HV(POPs);
     HE *entry;
@@ -4543,21 +4637,20 @@ PP(pp_each)
 STATIC OP *
 S_do_delete_local(pTHX)
 {
-    dVAR;
     dSP;
     const I32 gimme = GIMME_V;
     const MAGIC *mg;
     HV *stash;
     const bool sliced = !!(PL_op->op_private & OPpSLICE);
-    SV *unsliced_keysv = sliced ? NULL : POPs;
+    SV **unsliced_keysv = sliced ? NULL : sp--;
     SV * const osv = POPs;
-    SV **mark = sliced ? PL_stack_base + POPMARK : &unsliced_keysv-1;
+    SV **mark = sliced ? PL_stack_base + POPMARK : unsliced_keysv-1;
     dORIGMARK;
     const bool tied = SvRMAGICAL(osv)
                            && mg_find((const SV *)osv, PERL_MAGIC_tied);
     const bool can_preserve = SvCANEXISTDELETE(osv);
     const U32 type = SvTYPE(osv);
-    SV ** const end = sliced ? SP : &unsliced_keysv;
+    SV ** const end = sliced ? SP : unsliced_keysv;
 
     if (type == SVt_PVHV) {                    /* hash element */
            HV * const hv = MUTABLE_HV(osv);
@@ -4647,14 +4740,13 @@ S_do_delete_local(pTHX)
        }
     }
     else if (gimme != G_VOID)
-       PUSHs(unsliced_keysv);
+       PUSHs(*unsliced_keysv);
 
     RETURN;
 }
 
 PP(pp_delete)
 {
-    dVAR;
     dSP;
     I32 gimme;
     I32 discard;
@@ -4720,7 +4812,6 @@ PP(pp_delete)
 
 PP(pp_exists)
 {
-    dVAR;
     dSP;
     SV *tmpsv;
     HV *hv;
@@ -4755,7 +4846,7 @@ PP(pp_exists)
 
 PP(pp_hslice)
 {
-    dVAR; dSP; dMARK; dORIGMARK;
+    dSP; dMARK; dORIGMARK;
     HV * const hv = MUTABLE_HV(POPs);
     const I32 lval = (PL_op->op_flags & OPf_MOD || LVRET);
     const bool localizing = PL_op->op_private & OPpLVAL_INTRO;
@@ -4812,7 +4903,7 @@ PP(pp_hslice)
 
 PP(pp_kvhslice)
 {
-    dVAR; dSP; dMARK;
+    dSP; dMARK;
     HV * const hv = MUTABLE_HV(POPs);
     I32 lval = (PL_op->op_flags & OPf_MOD);
     SSize_t items = SP - MARK;
@@ -4863,20 +4954,22 @@ PP(pp_kvhslice)
 
 PP(pp_list)
 {
-    dVAR; dSP; dMARK;
+    I32 markidx = POPMARK;
     if (GIMME != G_ARRAY) {
+       SV **mark = PL_stack_base + markidx;
+       dSP;
        if (++MARK <= SP)
            *MARK = *SP;                /* unwanted list, return last item */
        else
            *MARK = &PL_sv_undef;
        SP = MARK;
+       PUTBACK;
     }
-    RETURN;
+    return NORMAL;
 }
 
 PP(pp_lslice)
 {
-    dVAR;
     dSP;
     SV ** const lastrelem = PL_stack_sp;
     SV ** const lastlelem = PL_stack_base + POPMARK;
@@ -4915,8 +5008,9 @@ PP(pp_lslice)
            is_something_there = TRUE;
            if (!(*lelem = firstrelem[ix]))
                *lelem = &PL_sv_undef;
-           else if (mod && SvPADTMP(*lelem) && !IS_PADGV(*lelem))
+           else if (mod && SvPADTMP(*lelem)) {
                *lelem = firstrelem[ix] = sv_mortalcopy(*lelem);
+            }
        }
     }
     if (is_something_there)
@@ -4928,7 +5022,7 @@ PP(pp_lslice)
 
 PP(pp_anonlist)
 {
-    dVAR; dSP; dMARK;
+    dSP; dMARK;
     const I32 items = SP - MARK;
     SV * const av = MUTABLE_SV(av_make(items, MARK+1));
     SP = MARK;
@@ -4939,7 +5033,7 @@ PP(pp_anonlist)
 
 PP(pp_anonhash)
 {
-    dVAR; dSP; dMARK; dORIGMARK;
+    dSP; dMARK; dORIGMARK;
     HV* const hv = newHV();
     SV* const retval = sv_2mortal( PL_op->op_flags & OPf_SPECIAL
                                     ? newRV_noinc(MUTABLE_SV(hv))
@@ -5000,7 +5094,7 @@ S_deref_plain_array(pTHX_ AV *ary)
 
 PP(pp_splice)
 {
-    dVAR; dSP; dMARK; dORIGMARK;
+    dSP; dMARK; dORIGMARK;
     int num_args = (SP - MARK);
     AV *ary = DEREF_PLAIN_ARRAY(MUTABLE_AV(*++MARK));
     SV **src;
@@ -5210,7 +5304,7 @@ PP(pp_splice)
 
 PP(pp_push)
 {
-    dVAR; dSP; dMARK; dORIGMARK; dTARGET;
+    dSP; dMARK; dORIGMARK; dTARGET;
     AV * const ary = DEREF_PLAIN_ARRAY(MUTABLE_AV(*++MARK));
     const MAGIC * const mg = SvTIED_mg((const SV *)ary, PERL_MAGIC_tied);
 
@@ -5246,9 +5340,9 @@ PP(pp_push)
     RETURN;
 }
 
+/* also used for: pp_pop()*/
 PP(pp_shift)
 {
-    dVAR;
     dSP;
     AV * const av = PL_op->op_flags & OPf_SPECIAL
        ? MUTABLE_AV(GvAV(PL_defgv)) : DEREF_PLAIN_ARRAY(MUTABLE_AV(POPs));
@@ -5263,7 +5357,7 @@ PP(pp_shift)
 
 PP(pp_unshift)
 {
-    dVAR; dSP; dMARK; dORIGMARK; dTARGET;
+    dSP; dMARK; dORIGMARK; dTARGET;
     AV *ary = DEREF_PLAIN_ARRAY(MUTABLE_AV(*++MARK));
     const MAGIC * const mg = SvTIED_mg((const SV *)ary, PERL_MAGIC_tied);
 
@@ -5293,7 +5387,7 @@ PP(pp_unshift)
 
 PP(pp_reverse)
 {
-    dVAR; dSP; dMARK;
+    dSP; dMARK;
 
     if (GIMME == G_ARRAY) {
        if (PL_op->op_private & OPpREVERSE_INPLACE) {
@@ -5315,7 +5409,7 @@ PP(pp_reverse)
                const MAGIC *mg;
                bool can_preserve = SvCANEXISTDELETE(av);
 
-               for (i = 0, j = av_len(av); i < j; ++i, --j) {
+               for (i = 0, j = av_tindex(av); i < j; ++i, --j) {
                    SV *begin, *end;
 
                    if (can_preserve) {
@@ -5424,7 +5518,7 @@ PP(pp_reverse)
 
 PP(pp_split)
 {
-    dVAR; dSP; dTARG;
+    dSP; dTARG;
     AV *ary;
     IV limit = POPi;                   /* note, negative is forever */
     SV * const sv = POPs;
@@ -5664,7 +5758,7 @@ PP(pp_split)
     else if (do_utf8 == (RX_UTF8(rx) != 0) &&
             (RX_EXTFLAGS(rx) & RXf_USE_INTUIT) && !RX_NPARENS(rx)
             && (RX_EXTFLAGS(rx) & RXf_CHECK_ALL)
-            && !(RX_EXTFLAGS(rx) & RXf_ANCH)) {
+             && !(RX_EXTFLAGS(rx) & RXf_IS_ANCHORED)) {
        const int tail = (RX_EXTFLAGS(rx) & RXf_INTUIT_TAIL);
        SV * const csv = CALLREG_INTUIT_STRING(rx);
 
@@ -5868,7 +5962,6 @@ PP(pp_once)
 
 PP(pp_lock)
 {
-    dVAR;
     dSP;
     dTOPss;
     SV *retsv = sv;
@@ -5882,9 +5975,11 @@ PP(pp_lock)
 }
 
 
+/* used for: pp_padany(), pp_mapstart(), pp_custom(); plus any system ops
+ * that aren't implemented on a particular platform */
+
 PP(unimplemented_op)
 {
-    dVAR;
     const Optype op_type = PL_op->op_type;
     /* Using OP_NAME() isn't going to be helpful here. Firstly, it doesn't cope
        with out of range op numbers - it only "special" cases op_custom.
@@ -6016,7 +6111,6 @@ PP(pp_coreargs)
                )
               )
                DIE(aTHX_
-               /* diag_listed_as: Type of arg %d to &CORE::%s must be %s*/
                 "Type of arg %d to &CORE::%s must be %s",
                  whicharg, PL_op_name[opnum],
                  wantscalar