This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
pp_ctl.c: Add -D output for inward goto
[perl5.git] / pp_ctl.c
index 072f529..a0cb31c 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -34,7 +34,8 @@
 #define PERL_IN_PP_CTL_C
 #include "perl.h"
 
 #define PERL_IN_PP_CTL_C
 #include "perl.h"
 
-#define DOCATCH(o) ((CATCH_GET == TRUE) ? docatch(o) : (o))
+#define RUN_PP_CATCHABLY(thispp) \
+    STMT_START { if (CATCH_GET) return docatch(thispp); } STMT_END
 
 #define dopoptosub(plop)       dopoptosub_at(cxstack, (plop))
 
 
 #define dopoptosub(plop)       dopoptosub_at(cxstack, (plop))
 
@@ -162,15 +163,9 @@ PP(pp_regcomp)
     /* handle the empty pattern */
     if (!RX_PRELEN(PM_GETRE(pm)) && PL_curpm) {
         if (PL_curpm == PL_reg_curpm) {
     /* handle the empty pattern */
     if (!RX_PRELEN(PM_GETRE(pm)) && PL_curpm) {
         if (PL_curpm == PL_reg_curpm) {
-            if (PL_curpm_under) {
-                if (PL_curpm_under == PL_reg_curpm) {
-                    Perl_croak(aTHX_ "Infinite recursion via empty pattern");
-                } else {
-                    pm = PL_curpm_under;
-                }
+            if (PL_curpm_under && PL_curpm_under == PL_reg_curpm) {
+                Perl_croak(aTHX_ "Infinite recursion via empty pattern");
             }
             }
-        } else {
-            pm = PL_curpm;
         }
     }
 
         }
     }
 
@@ -218,9 +213,9 @@ PP(pp_substcont)
        SvGETMAGIC(TOPs); /* possibly clear taint on $1 etc: #67962 */
 
        /* See "how taint works" above pp_subst() */
        SvGETMAGIC(TOPs); /* possibly clear taint on $1 etc: #67962 */
 
        /* See "how taint works" above pp_subst() */
-       if (SvTAINTED(TOPs))
-           cx->sb_rxtainted |= SUBST_TAINT_REPL;
        sv_catsv_nomg(dstr, POPs);
        sv_catsv_nomg(dstr, POPs);
+       if (UNLIKELY(TAINT_get))
+           cx->sb_rxtainted |= SUBST_TAINT_REPL;
        if (CxONCE(cx) || s < orig ||
                 !CALLREGEXEC(rx, s, cx->sb_strend, orig,
                             (s == m), cx->sb_targ, NULL,
        if (CxONCE(cx) || s < orig ||
                 !CALLREGEXEC(rx, s, cx->sb_strend, orig,
                             (s == m), cx->sb_targ, NULL,
@@ -720,6 +715,7 @@ PP(pp_formline)
                SvSETMAGIC(sv);
                break;
            }
                SvSETMAGIC(sv);
                break;
            }
+            /* FALLTHROUGH */
 
        case FF_LINESNGL: /* process ^*  */
            chopspace = 0;
 
        case FF_LINESNGL: /* process ^*  */
            chopspace = 0;
@@ -872,9 +868,9 @@ PP(pp_formline)
                 }
 #else
                 /* we generate fmt ourselves so it is safe */
                 }
 #else
                 /* we generate fmt ourselves so it is safe */
-                GCC_DIAG_IGNORE(-Wformat-nonliteral);
+                GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral);
                 len = my_snprintf(t, max, fmt, (int) fieldsize, (int) arg, value);
                 len = my_snprintf(t, max, fmt, (int) fieldsize, (int) arg, value);
-                GCC_DIAG_RESTORE;
+                GCC_DIAG_RESTORE_STMT;
 #endif
                 PERL_MY_SNPRINTF_POST_GUARD(len, max);
                 RESTORE_LC_NUMERIC();
 #endif
                 PERL_MY_SNPRINTF_POST_GUARD(len, max);
                 RESTORE_LC_NUMERIC();
@@ -920,7 +916,7 @@ PP(pp_formline)
                            *t++ = ' ';
                    }
                    s1 = t - 3;
                            *t++ = ' ';
                    }
                    s1 = t - 3;
-                   if (strnEQ(s1,"   ",3)) {
+                   if (strBEGINs(s1,"   ")) {
                        while (s1 > SvPVX_const(PL_formtarget) && isSPACE(s1[-1]))
                            s1--;
                    }
                        while (s1 > SvPVX_const(PL_formtarget) && isSPACE(s1[-1]))
                            s1--;
                    }
@@ -957,7 +953,7 @@ PP(pp_grepstart)
     if (PL_stack_base + TOPMARK == SP) {
        (void)POPMARK;
        if (GIMME_V == G_SCALAR)
     if (PL_stack_base + TOPMARK == SP) {
        (void)POPMARK;
        if (GIMME_V == G_SCALAR)
-           mXPUSHi(0);
+           XPUSHs(&PL_sv_zero);
        RETURNOP(PL_op->op_next->op_next);
     }
     PL_stack_sp = PL_stack_base + TOPMARK + 1;
        RETURNOP(PL_op->op_next->op_next);
     }
     PL_stack_sp = PL_stack_base + TOPMARK + 1;
@@ -1127,9 +1123,11 @@ PP(pp_mapwhile)
 
 PP(pp_range)
 {
 
 PP(pp_range)
 {
+    dTARG;
     if (GIMME_V == G_ARRAY)
        return NORMAL;
     if (GIMME_V == G_ARRAY)
        return NORMAL;
-    if (SvTRUEx(PAD_SV(PL_op->op_targ)))
+    GETTARGET;
+    if (SvTRUE_NN(targ))
        return cLOGOP->op_other;
     else
        return NORMAL;
        return cLOGOP->op_other;
     else
        return NORMAL;
@@ -1157,7 +1155,7 @@ PP(pp_flip)
                    flip = SvIV(sv) == SvIV(GvSV(gv));
            }
        } else {
                    flip = SvIV(sv) == SvIV(GvSV(gv));
            }
        } else {
-           flip = SvTRUE(sv);
+           flip = SvTRUE_NN(sv);
        }
        if (flip) {
            sv_setiv(PAD_SV(cUNOP->op_first->op_targ), 1);
        }
        if (flip) {
            sv_setiv(PAD_SV(cUNOP->op_first->op_targ), 1);
@@ -1270,7 +1268,7 @@ PP(pp_flop)
            }
        }
        else {
            }
        }
        else {
-           flop = SvTRUE(sv);
+           flop = SvTRUE_NN(sv);
        }
 
        if (flop) {
        }
 
        if (flop) {
@@ -1287,9 +1285,9 @@ PP(pp_flop)
 
 static const char * const context_name[] = {
     "pseudo-block",
 
 static const char * const context_name[] = {
     "pseudo-block",
-    NULL, /* CXt_WHEN never actually needs "block" */
+    NULL, /* CXt_WHERESO never actually needs "block" */
     NULL, /* CXt_BLOCK never actually needs "block" */
     NULL, /* CXt_BLOCK never actually needs "block" */
-    NULL, /* CXt_GIVEN never actually needs "block" */
+    NULL, /* CXt_LOOP_GIVEN never actually needs "block" */
     NULL, /* CXt_LOOP_PLAIN never actually needs "loop" */
     NULL, /* CXt_LOOP_LAZYIV never actually needs "loop" */
     NULL, /* CXt_LOOP_LAZYSV never actually needs "loop" */
     NULL, /* CXt_LOOP_PLAIN never actually needs "loop" */
     NULL, /* CXt_LOOP_LAZYIV never actually needs "loop" */
     NULL, /* CXt_LOOP_LAZYSV never actually needs "loop" */
@@ -1322,6 +1320,7 @@ S_dopoptolabel(pTHX_ const char *label, STRLEN len, U32 flags)
            if (CxTYPE(cx) == CXt_NULL) /* sort BLOCK */
                return -1;
            break;
            if (CxTYPE(cx) == CXt_NULL) /* sort BLOCK */
                return -1;
            break;
+       case CXt_LOOP_GIVEN:
        case CXt_LOOP_PLAIN:
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
        case CXt_LOOP_PLAIN:
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
@@ -1470,6 +1469,7 @@ S_dopoptoloop(pTHX_ I32 startingblock)
            if ((CxTYPE(cx)) == CXt_NULL) /* sort BLOCK */
                return -1;
            break;
            if ((CxTYPE(cx)) == CXt_NULL) /* sort BLOCK */
                return -1;
            break;
+       case CXt_LOOP_GIVEN:
        case CXt_LOOP_PLAIN:
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
        case CXt_LOOP_PLAIN:
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
@@ -1482,38 +1482,8 @@ S_dopoptoloop(pTHX_ I32 startingblock)
     return i;
 }
 
     return i;
 }
 
-/* find the next GIVEN or FOR (with implicit $_) loop context block */
-
-STATIC I32
-S_dopoptogivenfor(pTHX_ I32 startingblock)
-{
-    I32 i;
-    for (i = startingblock; i >= 0; i--) {
-       const PERL_CONTEXT *cx = &cxstack[i];
-       switch (CxTYPE(cx)) {
-       default:
-           continue;
-       case CXt_GIVEN:
-           DEBUG_l( Perl_deb(aTHX_ "(dopoptogivenfor(): found given at cx=%ld)\n", (long)i));
-           return i;
-       case CXt_LOOP_PLAIN:
-            assert(!(cx->cx_type & CXp_FOR_DEF));
-           break;
-       case CXt_LOOP_LAZYIV:
-       case CXt_LOOP_LAZYSV:
-       case CXt_LOOP_LIST:
-       case CXt_LOOP_ARY:
-            if (cx->cx_type & CXp_FOR_DEF) {
-               DEBUG_l( Perl_deb(aTHX_ "(dopoptogivenfor(): found foreach at cx=%ld)\n", (long)i));
-               return i;
-           }
-       }
-    }
-    return i;
-}
-
 STATIC I32
 STATIC I32
-S_dopoptowhen(pTHX_ I32 startingblock)
+S_dopoptowhereso(pTHX_ I32 startingblock)
 {
     I32 i;
     for (i = startingblock; i >= 0; i--) {
 {
     I32 i;
     for (i = startingblock; i >= 0; i--) {
@@ -1521,8 +1491,8 @@ S_dopoptowhen(pTHX_ I32 startingblock)
        switch (CxTYPE(cx)) {
        default:
            continue;
        switch (CxTYPE(cx)) {
        default:
            continue;
-       case CXt_WHEN:
-           DEBUG_l( Perl_deb(aTHX_ "(dopoptowhen(): found when at cx=%ld)\n", (long)i));
+       case CXt_WHERESO:
+           DEBUG_l( Perl_deb(aTHX_ "(dopoptowhereso(): found whereso at cx=%ld)\n", (long)i));
            return i;
        }
     }
            return i;
        }
     }
@@ -1566,6 +1536,7 @@ Perl_dounwind(pTHX_ I32 cxix)
        case CXt_EVAL:
            cx_popeval(cx);
            break;
        case CXt_EVAL:
            cx_popeval(cx);
            break;
+       case CXt_LOOP_GIVEN:
        case CXt_LOOP_PLAIN:
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
        case CXt_LOOP_PLAIN:
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
@@ -1573,11 +1544,8 @@ Perl_dounwind(pTHX_ I32 cxix)
        case CXt_LOOP_ARY:
            cx_poploop(cx);
            break;
        case CXt_LOOP_ARY:
            cx_poploop(cx);
            break;
-       case CXt_WHEN:
-           cx_popwhen(cx);
-           break;
-       case CXt_GIVEN:
-           cx_popgiven(cx);
+       case CXt_WHERESO:
+           cx_popwhereso(cx);
            break;
        case CXt_BLOCK:
        case CXt_NULL:
            break;
        case CXt_BLOCK:
        case CXt_NULL:
@@ -1684,7 +1652,13 @@ Perl_die_unwind(pTHX_ SV *msv)
     if (in_eval) {
        I32 cxix;
 
     if (in_eval) {
        I32 cxix;
 
-        exceptsv = sv_2mortal(SvREFCNT_inc_simple_NN(exceptsv));
+        /* We need to keep this SV alive through all the stack unwinding
+         * and FREETMPSing below, while ensuing that it doesn't leak
+         * if we call out to something which then dies (e.g. sub STORE{die}
+         * when unlocalising a tied var). So we do a dance with
+         * mortalising and SAVEFREEing.
+         */
+        sv_2mortal(SvREFCNT_inc_simple_NN(exceptsv));
 
        /*
         * Historically, perl used to set ERRSV ($@) early in the die
 
        /*
         * Historically, perl used to set ERRSV ($@) early in the die
@@ -1753,6 +1727,24 @@ Perl_die_unwind(pTHX_ SV *msv)
 
            restartjmpenv = cx->blk_eval.cur_top_env;
            restartop     = cx->blk_eval.retop;
 
            restartjmpenv = cx->blk_eval.cur_top_env;
            restartop     = cx->blk_eval.retop;
+
+            /* We need a FREETMPS here to avoid late-called destructors
+             * clobbering $@ *after* we set it below, e.g.
+             *    sub DESTROY { eval { die "X" } }
+             *    eval { my $x = bless []; die $x = 0, "Y" };
+             *    is($@, "Y")
+             * Here the clearing of the $x ref mortalises the anon array,
+             * which needs to be freed *before* $& is set to "Y",
+             * otherwise it gets overwritten with "X".
+             *
+             * However, the FREETMPS will clobber exceptsv, so preserve it
+             * on the savestack for now.
+             */
+            SAVEFREESV(SvREFCNT_inc_simple_NN(exceptsv));
+            FREETMPS;
+            /* now we're about to pop the savestack, so re-mortalise it */
+            sv_2mortal(SvREFCNT_inc_simple_NN(exceptsv));
+
             /* Note that unlike pp_entereval, pp_require isn't supposed to
              * trap errors. So if we're a require, after we pop the
              * CXt_EVAL that pp_require pushed, rethrow the error with
             /* Note that unlike pp_entereval, pp_require isn't supposed to
              * trap errors. So if we're a require, after we pop the
              * CXt_EVAL that pp_require pushed, rethrow the error with
@@ -1778,7 +1770,7 @@ Perl_die_unwind(pTHX_ SV *msv)
 PP(pp_xor)
 {
     dSP; dPOPTOPssrl;
 PP(pp_xor)
 {
     dSP; dPOPTOPssrl;
-    if (SvTRUE(left) != SvTRUE(right))
+    if (SvTRUE_NN(left) != SvTRUE_NN(right))
        RETSETYES;
     else
        RETSETNO;
        RETSETYES;
     else
        RETSETNO;
@@ -1920,7 +1912,7 @@ PP(pp_caller)
     }
     else {
        PUSHs(newSVpvs_flags("(eval)", SVs_TEMP));
     }
     else {
        PUSHs(newSVpvs_flags("(eval)", SVs_TEMP));
-       mPUSHi(0);
+       PUSHs(&PL_sv_zero);
     }
     gimme = cx->blk_gimme;
     if (gimme == G_VOID)
     }
     gimme = cx->blk_gimme;
     if (gimme == G_VOID)
@@ -1970,7 +1962,8 @@ PP(pp_caller)
 
        if (AvMAX(PL_dbargs) < AvFILLp(ary) + off)
            av_extend(PL_dbargs, AvFILLp(ary) + off);
 
        if (AvMAX(PL_dbargs) < AvFILLp(ary) + off)
            av_extend(PL_dbargs, AvFILLp(ary) + off);
-       Copy(AvALLOC(ary), AvARRAY(PL_dbargs), AvFILLp(ary) + 1 + off, SV*);
+        if (AvFILLp(ary) + 1 + off)
+            Copy(AvALLOC(ary), AvARRAY(PL_dbargs), AvFILLp(ary) + 1 + off, SV*);
        AvFILLp(PL_dbargs) = AvFILLp(ary) + off;
     }
     mPUSHi(CopHINTS_get(cx->blk_oldcop));
        AvFILLp(PL_dbargs) = AvFILLp(ary) + off;
     }
     mPUSHi(CopHINTS_get(cx->blk_oldcop));
@@ -1984,16 +1977,7 @@ PP(pp_caller)
             mask = &PL_sv_undef ;
         else if (old_warnings == pWARN_ALL ||
                  (old_warnings == pWARN_STD && PL_dowarn & G_WARN_ON)) {
             mask = &PL_sv_undef ;
         else if (old_warnings == pWARN_ALL ||
                  (old_warnings == pWARN_STD && PL_dowarn & G_WARN_ON)) {
-           /* Get the bit mask for $warnings::Bits{all}, because
-            * it could have been extended by warnings::register */
-           SV **bits_all;
-           HV * const bits = get_hv("warnings::Bits", 0);
-           if (bits && (bits_all=hv_fetchs(bits, "all", FALSE))) {
-               mask = newSVsv(*bits_all);
-           }
-           else {
-               mask = newSVpvn(WARN_ALLstring, WARNsize) ;
-           }
+           mask = newSVpvn(WARN_ALLstring, WARNsize) ;
        }
         else
             mask = newSVpvn((char *) (old_warnings + 1), old_warnings[0]);
        }
         else
             mask = newSVpvn((char *) (old_warnings + 1), old_warnings[0]);
@@ -2011,8 +1995,10 @@ PP(pp_reset)
     dSP;
     const char * tmps;
     STRLEN len = 0;
     dSP;
     const char * tmps;
     STRLEN len = 0;
-    if (MAXARG < 1 || (!TOPs && !POPs))
+    if (MAXARG < 1 || (!TOPs && !POPs)) {
+        EXTEND(SP, 1);
        tmps = NULL, len = 0;
        tmps = NULL, len = 0;
+    }
     else
        tmps = SvPVx_const(POPs, len);
     sv_resetpvn(tmps, len, CopSTASH(PL_curcop));
     else
        tmps = SvPVx_const(POPs, len);
     sv_resetpvn(tmps, len, CopSTASH(PL_curcop));
@@ -2174,8 +2160,6 @@ PP(pp_enteriter)
             itersave = GvSV(sv);
             SvREFCNT_inc_simple_void(itersave);
             cxflags = CXp_FOR_GV;
             itersave = GvSV(sv);
             SvREFCNT_inc_simple_void(itersave);
             cxflags = CXp_FOR_GV;
-            if (PL_op->op_private & OPpITER_DEF)
-                cxflags |= CXp_FOR_DEF;
         }
         else {                          /* LV ref: for \$foo (...) */
             assert(SvTYPE(sv) == SVt_PVMG);
         }
         else {                          /* LV ref: for \$foo (...) */
             assert(SvTYPE(sv) == SVt_PVMG);
@@ -2185,8 +2169,6 @@ PP(pp_enteriter)
             cxflags = CXp_FOR_LVREF;
         }
     }
             cxflags = CXp_FOR_LVREF;
         }
     }
-    /* OPpITER_DEF (implicit $_) should only occur with a GV iter var */
-    assert((cxflags & CXp_FOR_GV) || !(PL_op->op_private & OPpITER_DEF));
 
     /* Note that this context is initially set as CXt_NULL. Further on
      * down it's changed to one of the CXt_LOOP_*. Before it's changed,
 
     /* Note that this context is initially set as CXt_NULL. Further on
      * down it's changed to one of the CXt_LOOP_*. Before it's changed,
@@ -2693,6 +2675,20 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac
 }
 
 
 }
 
 
+static void
+S_check_op_type(pTHX_ OP * const o)
+{
+    /* Eventually we may want to stack the needed arguments
+     * for each op.  For now, we punt on the hard ones. */
+    /* XXX This comment seems to me like wishful thinking.  --sprout */
+    if (o->op_type == OP_ENTERITER)
+        Perl_croak(aTHX_
+                  "Can't \"goto\" into the middle of a foreach loop");
+    if (o->op_type == OP_ENTERGIVEN)
+        Perl_croak(aTHX_
+                  "Can't \"goto\" into a \"given\" block");
+}
+
 /* also used for: pp_dump() */
 
 PP(pp_goto)
 /* also used for: pp_dump() */
 
 PP(pp_goto)
@@ -2974,8 +2970,8 @@ PP(pp_goto)
             case CXt_LOOP_LAZYSV:
             case CXt_LOOP_LIST:
             case CXt_LOOP_ARY:
             case CXt_LOOP_LAZYSV:
             case CXt_LOOP_LIST:
             case CXt_LOOP_ARY:
-           case CXt_GIVEN:
-           case CXt_WHEN:
+           case CXt_LOOP_GIVEN:
+           case CXt_WHERESO:
                gotoprobe = OpSIBLING(cx->blk_oldcop);
                break;
            case CXt_SUBST:
                gotoprobe = OpSIBLING(cx->blk_oldcop);
                break;
            case CXt_SUBST:
@@ -3034,8 +3030,7 @@ PP(pp_goto)
        if (leaving_eval && *enterops && enterops[1]) {
            I32 i;
             for (i = 1; enterops[i]; i++)
        if (leaving_eval && *enterops && enterops[1]) {
            I32 i;
             for (i = 1; enterops[i]; i++)
-                if (enterops[i]->op_type == OP_ENTERITER)
-                    DIE(aTHX_ "Can't \"goto\" into the middle of a foreach loop");
+                S_check_op_type(aTHX_ enterops[i]);
        }
 
        if (*enterops && enterops[1]) {
        }
 
        if (*enterops && enterops[1]) {
@@ -3061,10 +3056,9 @@ PP(pp_goto)
            ix = enterops[1]->op_type == OP_ENTER && in_block ? 2 : 1;
            for (; enterops[ix]; ix++) {
                PL_op = enterops[ix];
            ix = enterops[1]->op_type == OP_ENTER && in_block ? 2 : 1;
            for (; enterops[ix]; ix++) {
                PL_op = enterops[ix];
-               /* Eventually we may want to stack the needed arguments
-                * for each op.  For now, we punt on the hard ones. */
-               if (PL_op->op_type == OP_ENTERITER)
-                   DIE(aTHX_ "Can't \"goto\" into the middle of a foreach loop");
+               S_check_op_type(aTHX_ PL_op);
+               DEBUG_l( Perl_deb(aTHX_ "pp_goto: Entering %s\n",
+                                        OP_NAME(PL_op)));
                PL_op->op_ppaddr(aTHX);
            }
            PL_op = oldop;
                PL_op->op_ppaddr(aTHX);
            }
            PL_op = oldop;
@@ -3159,23 +3153,18 @@ establish a local jmpenv to handle exception traps.
 =cut
 */
 STATIC OP *
 =cut
 */
 STATIC OP *
-S_docatch(pTHX_ OP *o)
+S_docatch(pTHX_ Perl_ppaddr_t firstpp)
 {
     int ret;
     OP * const oldop = PL_op;
     dJMPENV;
 
 {
     int ret;
     OP * const oldop = PL_op;
     dJMPENV;
 
-#ifdef DEBUGGING
     assert(CATCH_GET == TRUE);
     assert(CATCH_GET == TRUE);
-#endif
-    PL_op = o;
 
     JMPENV_PUSH(ret);
     switch (ret) {
     case 0:
 
     JMPENV_PUSH(ret);
     switch (ret) {
     case 0:
-       assert(cxstack_ix >= 0);
-       assert(CxTYPE(CX_CUR()) == CXt_EVAL);
-        CX_CUR()->blk_eval.cur_top_env = PL_top_env;
+       PL_op = firstpp(aTHX);
  redo_body:
        CALLRUNOPS(aTHX);
        break;
  redo_body:
        CALLRUNOPS(aTHX);
        break;
@@ -3257,7 +3246,7 @@ Perl_find_runcv_where(pTHX_ U8 cond, IV arg, U32 *db_seqp)
                    return cv;
                case FIND_RUNCV_level_eq:
                    if (level++ != arg) continue;
                    return cv;
                case FIND_RUNCV_level_eq:
                    if (level++ != arg) continue;
-                   /* GERONIMO! */
+                    /* FALLTHROUGH */
                default:
                    return cv;
                }
                default:
                    return cv;
                }
@@ -3353,7 +3342,11 @@ S_doeval_compile(pTHX_ U8 gimme, CV* outside, U32 seq, HV *hh)
        SAVEGENERICSV(PL_curstash);
        PL_curstash = (HV *)CopSTASH(PL_curcop);
        if (SvTYPE(PL_curstash) != SVt_PVHV) PL_curstash = NULL;
        SAVEGENERICSV(PL_curstash);
        PL_curstash = (HV *)CopSTASH(PL_curcop);
        if (SvTYPE(PL_curstash) != SVt_PVHV) PL_curstash = NULL;
-       else SvREFCNT_inc_simple_void(PL_curstash);
+       else {
+           SvREFCNT_inc_simple_void(PL_curstash);
+           save_item(PL_curstname);
+           sv_sethek(PL_curstname, HvNAME_HEK(PL_curstash));
+       }
     }
     /* XXX:ajgo do we really need to alloc an AV for begin/checkunit */
     SAVESPTR(PL_beginav);
     }
     /* XXX:ajgo do we really need to alloc an AV for begin/checkunit */
     SAVESPTR(PL_beginav);
@@ -3538,15 +3531,22 @@ S_check_type_and_open(pTHX_ SV *name)
        errno EACCES, so only do a stat to separate a dir from a real EACCES
        caused by user perms */
 #ifndef WIN32
        errno EACCES, so only do a stat to separate a dir from a real EACCES
        caused by user perms */
 #ifndef WIN32
-    /* we use the value of errno later to see how stat() or open() failed.
-     * We don't want it set if the stat succeeded but we still failed,
-     * such as if the name exists, but is a directory */
-    errno = 0;
-
     st_rc = PerlLIO_stat(p, &st);
 
     st_rc = PerlLIO_stat(p, &st);
 
-    if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) {
+    if (st_rc < 0)
        return NULL;
        return NULL;
+    else {
+       int eno;
+       if(S_ISBLK(st.st_mode)) {
+           eno = EINVAL;
+           goto not_file;
+       }
+       else if(S_ISDIR(st.st_mode)) {
+           eno = EISDIR;
+           not_file:
+           errno = eno;
+           return NULL;
+       }
     }
 #endif
 
     }
 #endif
 
@@ -3558,8 +3558,10 @@ S_check_type_and_open(pTHX_ SV *name)
        int eno;
        st_rc = PerlLIO_stat(p, &st);
        if (st_rc >= 0) {
        int eno;
        st_rc = PerlLIO_stat(p, &st);
        if (st_rc >= 0) {
-           if(S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode))
-               eno = 0;
+           if(S_ISDIR(st.st_mode))
+               eno = EISDIR;
+           else if(S_ISBLK(st.st_mode))
+               eno = EINVAL;
            else
                eno = EACCES;
            errno = eno;
            else
                eno = EACCES;
            errno = eno;
@@ -3590,7 +3592,7 @@ S_doopen_pm(pTHX_ SV *name)
     if (!IS_SAFE_PATHNAME(p, namelen, "require"))
         return NULL;
 
     if (!IS_SAFE_PATHNAME(p, namelen, "require"))
         return NULL;
 
-    if (namelen > 3 && memEQs(p + namelen - 3, 3, ".pm")) {
+    if (memENDPs(p, namelen, ".pm")) {
        SV *const pmcsv = sv_newmortal();
        PerlIO * pmcio;
 
        SV *const pmcsv = sv_newmortal();
        PerlIO * pmcio;
 
@@ -3733,6 +3735,7 @@ S_require_file(pTHX_ SV *sv)
     I32 old_savestack_ix;
     const bool op_is_require = PL_op->op_type == OP_REQUIRE;
     const char *const op_name = op_is_require ? "require" : "do";
     I32 old_savestack_ix;
     const bool op_is_require = PL_op->op_type == OP_REQUIRE;
     const char *const op_name = op_is_require ? "require" : "do";
+    SV ** svp_cached = NULL;
 
     assert(op_is_require || PL_op->op_type == OP_DOFILE);
 
 
     assert(op_is_require || PL_op->op_type == OP_DOFILE);
 
@@ -3742,6 +3745,15 @@ S_require_file(pTHX_ SV *sv)
     if (!(name && len > 0 && *name))
         DIE(aTHX_ "Missing or undefined argument to %s", op_name);
 
     if (!(name && len > 0 && *name))
         DIE(aTHX_ "Missing or undefined argument to %s", op_name);
 
+#ifndef VMS
+       /* try to return earlier (save the SAFE_PATHNAME check) if INC already got the name */
+       if (op_is_require) {
+               /* can optimize to only perform one single lookup */
+               svp_cached = hv_fetch(GvHVn(PL_incgv), (char*) name, len, 0);
+               if ( svp_cached && *svp_cached != &PL_sv_undef ) RETPUSHYES;
+       }
+#endif
+
     if (!IS_SAFE_PATHNAME(name, len, op_name)) {
         if (!op_is_require) {
             CLEAR_ERRSV();
     if (!IS_SAFE_PATHNAME(name, len, op_name)) {
         if (!op_is_require) {
             CLEAR_ERRSV();
@@ -3780,8 +3792,8 @@ S_require_file(pTHX_ SV *sv)
        unixlen = len;
     }
     if (op_is_require) {
        unixlen = len;
     }
     if (op_is_require) {
-       SV * const * const svp = hv_fetch(GvHVn(PL_incgv),
-                                         unixname, unixlen, 0);
+       /* reuse the previous hv_fetch result if possible */
+       SV * const * const svp = svp_cached ? svp_cached : hv_fetch(GvHVn(PL_incgv), unixname, unixlen, 0);
        if ( svp ) {
            if (*svp != &PL_sv_undef)
                RETPUSHYES;
        if ( svp ) {
            if (*svp != &PL_sv_undef)
                RETPUSHYES;
@@ -3815,7 +3827,7 @@ S_require_file(pTHX_ SV *sv)
                    directory, or (*nix) hidden filenames.  Also sanity check
                    that the generated filename ends .pm  */
                 if (!path_searchable || len < 3 || name[0] == '.'
                    directory, or (*nix) hidden filenames.  Also sanity check
                    that the generated filename ends .pm  */
                 if (!path_searchable || len < 3 || name[0] == '.'
-                    || !memEQ(name + package_len, ".pm", 3))
+                    || !memEQs(name + package_len, len - package_len, ".pm"))
                     DIE(aTHX_ "Bareword in require maps to disallowed filename \"%" SVf "\"", sv);
                 if (memchr(name, 0, package_len)) {
                     /* diag_listed_as: Bareword in require contains "%s" */
                     DIE(aTHX_ "Bareword in require maps to disallowed filename \"%" SVf "\"", sv);
                 if (memchr(name, 0, package_len)) {
                     /* diag_listed_as: Bareword in require contains "%s" */
@@ -4019,8 +4031,7 @@ S_require_file(pTHX_ SV *sv)
                        continue;
                    sv_setpv(namesv, unixdir);
                    sv_catpv(namesv, unixname);
                        continue;
                    sv_setpv(namesv, unixdir);
                    sv_catpv(namesv, unixname);
-#else
-#  ifdef __SYMBIAN32__
+#elif defined(__SYMBIAN32__)
                    if (PL_origfilename[0] &&
                        PL_origfilename[1] == ':' &&
                        !(dir[0] && dir[1] == ':'))
                    if (PL_origfilename[0] &&
                        PL_origfilename[1] == ':' &&
                        !(dir[0] && dir[1] == ':'))
@@ -4032,7 +4043,7 @@ S_require_file(pTHX_ SV *sv)
                        Perl_sv_setpvf(aTHX_ namesv,
                                       "%s\\%s",
                                       dir, name);
                        Perl_sv_setpvf(aTHX_ namesv,
                                       "%s\\%s",
                                       dir, name);
-#  else
+#else
                    /* The equivalent of                    
                       Perl_sv_setpvf(aTHX_ namesv, "%s/%s", dir, name);
                       but without the need to parse the format string, or
                    /* The equivalent of                    
                       Perl_sv_setpvf(aTHX_ namesv, "%s/%s", dir, name);
                       but without the need to parse the format string, or
@@ -4059,7 +4070,6 @@ S_require_file(pTHX_ SV *sv)
                        SvCUR_set(namesv, dirlen + len + 1);
                        SvPOK_on(namesv);
                    }
                        SvCUR_set(namesv, dirlen + len + 1);
                        SvPOK_on(namesv);
                    }
-#  endif
 #endif
                    TAINT_PROPER(op_name);
                    tryname = SvPVX_const(namesv);
 #endif
                    TAINT_PROPER(op_name);
                    tryname = SvPVX_const(namesv);
@@ -4096,7 +4106,7 @@ S_require_file(pTHX_ SV *sv)
                DIE(aTHX_ "Can't locate %s:   %s: %s",
                    name, tryname, Strerror(saved_errno));
            } else {
                DIE(aTHX_ "Can't locate %s:   %s: %s",
                    name, tryname, Strerror(saved_errno));
            } else {
-               if (namesv) {                   /* did we lookup @INC? */
+               if (path_searchable) {          /* did we lookup @INC? */
                    AV * const ar = GvAVn(PL_incgv);
                    SSize_t i;
                    SV *const msg = newSVpvs_flags("", SVs_TEMP);
                    AV * const ar = GvAVn(PL_incgv);
                    SSize_t i;
                    SV *const msg = newSVpvs_flags("", SVs_TEMP);
@@ -4105,23 +4115,53 @@ S_require_file(pTHX_ SV *sv)
                        sv_catpvs(inc, " ");
                        sv_catsv(inc, *av_fetch(ar, i, TRUE));
                    }
                        sv_catpvs(inc, " ");
                        sv_catsv(inc, *av_fetch(ar, i, TRUE));
                    }
-                   if (len >= 4 && memEQ(name + len - 3, ".pm", 4)) {
-                       const char *c, *e = name + len - 3;
-                       sv_catpv(msg, " (you may need to install the ");
-                       for (c = name; c < e; c++) {
-                           if (*c == '/') {
-                               sv_catpvs(msg, "::");
-                           }
-                           else {
-                               sv_catpvn(msg, c, 1);
-                           }
-                       }
-                       sv_catpv(msg, " module)");
+                   if (memENDPs(name, len, ".pm")) {
+                        const char *e = name + len - (sizeof(".pm") - 1);
+                       const char *c;
+                        bool utf8 = cBOOL(SvUTF8(sv));
+
+                        /* if the filename, when converted from "Foo/Bar.pm"
+                         * form back to Foo::Bar form, makes a valid
+                         * package name (i.e. parseable by C<require
+                         * Foo::Bar>), then emit a hint.
+                         *
+                         * this loop is modelled after the one in
+                         S_parse_ident */
+                       c = name;
+                        while (c < e) {
+                            if (utf8 && isIDFIRST_utf8_safe(c, e)) {
+                                c += UTF8SKIP(c);
+                                while (c < e && isIDCONT_utf8_safe(
+                                            (const U8*) c, (const U8*) e))
+                                    c += UTF8SKIP(c);
+                            }
+                            else if (isWORDCHAR_A(*c)) {
+                                while (c < e && isWORDCHAR_A(*c))
+                                    c++;
+                            }
+                           else if (*c == '/')
+                                c++;
+                            else
+                                break;
+                        }
+
+                        if (c == e && isIDFIRST_lazy_if_safe(name, e, utf8)) {
+                            sv_catpv(msg, " (you may need to install the ");
+                            for (c = name; c < e; c++) {
+                                if (*c == '/') {
+                                    sv_catpvs(msg, "::");
+                                }
+                                else {
+                                    sv_catpvn(msg, c, 1);
+                                }
+                            }
+                            sv_catpv(msg, " module)");
+                        }
                    }
                    }
-                   else if (len >= 2 && memEQ(name + len - 2, ".h", 3)) {
+                   else if (memENDs(name, len, ".h")) {
                        sv_catpv(msg, " (change .h to .ph maybe?) (did you run h2ph?)");
                    }
                        sv_catpv(msg, " (change .h to .ph maybe?) (did you run h2ph?)");
                    }
-                   else if (len >= 3 && memEQ(name + len - 3, ".ph", 4)) {
+                   else if (memENDs(name, len, ".ph")) {
                        sv_catpv(msg, " (did you run h2ph?)");
                    }
 
                        sv_catpv(msg, " (did you run h2ph?)");
                    }
 
@@ -4197,6 +4237,7 @@ S_require_file(pTHX_ SV *sv)
     }
 
     /* switch to eval mode */
     }
 
     /* switch to eval mode */
+    assert(!CATCH_GET);
     cx = cx_pushblock(CXt_EVAL, gimme, SP, old_savestack_ix);
     cx_pusheval(cx, PL_op->op_next, newSVpv(name, 0));
 
     cx = cx_pushblock(CXt_EVAL, gimme, SP, old_savestack_ix);
     cx_pusheval(cx, PL_op->op_next, newSVpv(name, 0));
 
@@ -4206,7 +4247,7 @@ S_require_file(pTHX_ SV *sv)
     PUTBACK;
 
     if (doeval_compile(gimme, NULL, PL_curcop->cop_seq, NULL))
     PUTBACK;
 
     if (doeval_compile(gimme, NULL, PL_curcop->cop_seq, NULL))
-       op = DOCATCH(PL_eval_start);
+       op = PL_eval_start;
     else
        op = PL_op->op_next;
 
     else
        op = PL_op->op_next;
 
@@ -4220,13 +4261,17 @@ S_require_file(pTHX_ SV *sv)
 
 PP(pp_require)
 {
 
 PP(pp_require)
 {
-    dSP;
-    SV *sv = POPs;
-    SvGETMAGIC(sv);
-    PUTBACK;
-    return ((SvNIOKp(sv) || SvVOK(sv)) && PL_op->op_type != OP_DOFILE)
-        ? S_require_version(aTHX_ sv)
-        : S_require_file(aTHX_ sv);
+    RUN_PP_CATCHABLY(Perl_pp_require);
+
+    {
+       dSP;
+       SV *sv = POPs;
+       SvGETMAGIC(sv);
+       PUTBACK;
+       return ((SvNIOKp(sv) || SvVOK(sv)) && PL_op->op_type != OP_DOFILE)
+           ? S_require_version(aTHX_ sv)
+           : S_require_file(aTHX_ sv);
+    }
 }
 
 
 }
 
 
@@ -4247,18 +4292,28 @@ PP(pp_entereval)
     dSP;
     PERL_CONTEXT *cx;
     SV *sv;
     dSP;
     PERL_CONTEXT *cx;
     SV *sv;
-    const U8 gimme = GIMME_V;
-    const U32 was = PL_breakable_sub_gen;
+    U8 gimme;
+    U32 was;
     char tbuf[TYPE_DIGITS(long) + 12];
     char tbuf[TYPE_DIGITS(long) + 12];
-    bool saved_delete = FALSE;
-    char *tmpbuf = tbuf;
+    bool saved_delete;
+    char *tmpbuf;
     STRLEN len;
     CV* runcv;
     STRLEN len;
     CV* runcv;
-    U32 seq, lex_flags = 0;
-    HV *saved_hh = NULL;
-    const bool bytes = PL_op->op_private & OPpEVAL_BYTES;
+    U32 seq, lex_flags;
+    HV *saved_hh;
+    bool bytes;
     I32 old_savestack_ix;
 
     I32 old_savestack_ix;
 
+    RUN_PP_CATCHABLY(Perl_pp_entereval);
+
+    gimme = GIMME_V;
+    was = PL_breakable_sub_gen;
+    saved_delete = FALSE;
+    tmpbuf = tbuf;
+    lex_flags = 0;
+    saved_hh = NULL;
+    bytes = PL_op->op_private & OPpEVAL_BYTES;
+
     if (PL_op->op_private & OPpEVAL_HAS_HH) {
        saved_hh = MUTABLE_HV(SvREFCNT_inc(POPs));
     }
     if (PL_op->op_private & OPpEVAL_HAS_HH) {
        saved_hh = MUTABLE_HV(SvREFCNT_inc(POPs));
     }
@@ -4326,6 +4381,7 @@ PP(pp_entereval)
      * to do the dirty work for us */
     runcv = find_runcv(&seq);
 
      * to do the dirty work for us */
     runcv = find_runcv(&seq);
 
+    assert(!CATCH_GET);
     cx = cx_pushblock((CXt_EVAL|CXp_REAL), gimme, SP, old_savestack_ix);
     cx_pusheval(cx, PL_op->op_next, NULL);
 
     cx = cx_pushblock((CXt_EVAL|CXp_REAL), gimme, SP, old_savestack_ix);
     cx_pusheval(cx, PL_op->op_next, NULL);
 
@@ -4355,7 +4411,7 @@ PP(pp_entereval)
            char *const safestr = savepvn(tmpbuf, len);
            SAVEDELETE(PL_defstash, safestr, len);
        }
            char *const safestr = savepvn(tmpbuf, len);
            SAVEDELETE(PL_defstash, safestr, len);
        }
-       return DOCATCH(PL_eval_start);
+       return PL_eval_start;
     } else {
        /* We have already left the scope set up earlier thanks to the LEAVE
           in doeval_compile().  */
     } else {
        /* We have already left the scope set up earlier thanks to the LEAVE
           in doeval_compile().  */
@@ -4394,11 +4450,14 @@ PP(pp_leaveeval)
     /* did require return a false value? */
     failed =    CxOLD_OP_TYPE(cx) == OP_REQUIRE
              && !(gimme == G_SCALAR
     /* did require return a false value? */
     failed =    CxOLD_OP_TYPE(cx) == OP_REQUIRE
              && !(gimme == G_SCALAR
-                    ? SvTRUE(*PL_stack_sp)
+                    ? SvTRUE_NN(*PL_stack_sp)
                     : PL_stack_sp > oldsp);
 
                     : PL_stack_sp > oldsp);
 
-    if (gimme == G_VOID)
+    if (gimme == G_VOID) {
         PL_stack_sp = oldsp;
         PL_stack_sp = oldsp;
+        /* free now to avoid late-called destructors clobbering $@ */
+        FREETMPS;
+    }
     else
         leave_adjust_stacks(oldsp, oldsp, gimme, 0);
 
     else
         leave_adjust_stacks(oldsp, oldsp, gimme, 0);
 
@@ -4466,8 +4525,11 @@ Perl_create_eval_scope(pTHX_ OP *retop, U32 flags)
     
 PP(pp_entertry)
 {
     
 PP(pp_entertry)
 {
+    RUN_PP_CATCHABLY(Perl_pp_entertry);
+
+    assert(!CATCH_GET);
     create_eval_scope(cLOGOP->op_other->op_next, 0);
     create_eval_scope(cLOGOP->op_other->op_next, 0);
-    return DOCATCH(PL_op->op_next);
+    return PL_op->op_next;
 }
 
 
 }
 
 
@@ -4487,8 +4549,11 @@ PP(pp_leavetry)
     oldsp = PL_stack_base + cx->blk_oldsp;
     gimme = cx->blk_gimme;
 
     oldsp = PL_stack_base + cx->blk_oldsp;
     gimme = cx->blk_gimme;
 
-    if (gimme == G_VOID)
+    if (gimme == G_VOID) {
         PL_stack_sp = oldsp;
         PL_stack_sp = oldsp;
+        /* free now to avoid late-called destructors clobbering $@ */
+        FREETMPS;
+    }
     else
         leave_adjust_stacks(oldsp, oldsp, gimme, 1);
     CX_LEAVE_SCOPE(cx);
     else
         leave_adjust_stacks(oldsp, oldsp, gimme, 1);
     CX_LEAVE_SCOPE(cx);
@@ -4512,572 +4577,34 @@ PP(pp_entergiven)
     assert(!PL_op->op_targ); /* used to be set for lexical $_ */
     GvSV(PL_defgv) = SvREFCNT_inc(newsv);
 
     assert(!PL_op->op_targ); /* used to be set for lexical $_ */
     GvSV(PL_defgv) = SvREFCNT_inc(newsv);
 
-    cx = cx_pushblock(CXt_GIVEN, gimme, SP, PL_savestack_ix);
-    cx_pushgiven(cx, origsv);
+    cx = cx_pushblock(CXt_LOOP_GIVEN|CXp_FOR_GV, gimme, SP, PL_savestack_ix);
+    cx_pushloop_given(cx, origsv);
 
     RETURN;
 }
 
 
     RETURN;
 }
 
-PP(pp_leavegiven)
-{
-    PERL_CONTEXT *cx;
-    U8 gimme;
-    SV **oldsp;
-    PERL_UNUSED_CONTEXT;
-
-    cx = CX_CUR();
-    assert(CxTYPE(cx) == CXt_GIVEN);
-    oldsp = PL_stack_base + cx->blk_oldsp;
-    gimme = cx->blk_gimme;
-
-    if (gimme == G_VOID)
-        PL_stack_sp = oldsp;
-    else
-        leave_adjust_stacks(oldsp, oldsp, gimme, 1);
-
-    CX_LEAVE_SCOPE(cx);
-    cx_popgiven(cx);
-    cx_popblock(cx);
-    CX_POP(cx);
-
-    return NORMAL;
-}
-
-/* Helper routines used by pp_smartmatch */
-STATIC PMOP *
-S_make_matcher(pTHX_ REGEXP *re)
-{
-    PMOP *matcher = (PMOP *) newPMOP(OP_MATCH, OPf_WANT_SCALAR | OPf_STACKED);
-
-    PERL_ARGS_ASSERT_MAKE_MATCHER;
-
-    PM_SETRE(matcher, ReREFCNT_inc(re));
-
-    SAVEFREEOP((OP *) matcher);
-    ENTER_with_name("matcher"); SAVETMPS;
-    SAVEOP();
-    return matcher;
-}
-
-STATIC bool
-S_matcher_matches_sv(pTHX_ PMOP *matcher, SV *sv)
-{
-    dSP;
-    bool result;
-
-    PERL_ARGS_ASSERT_MATCHER_MATCHES_SV;
-    
-    PL_op = (OP *) matcher;
-    XPUSHs(sv);
-    PUTBACK;
-    (void) Perl_pp_match(aTHX);
-    SPAGAIN;
-    result = SvTRUEx(POPs);
-    PUTBACK;
-
-    return result;
-}
-
-STATIC void
-S_destroy_matcher(pTHX_ PMOP *matcher)
-{
-    PERL_ARGS_ASSERT_DESTROY_MATCHER;
-    PERL_UNUSED_ARG(matcher);
-
-    FREETMPS;
-    LEAVE_with_name("matcher");
-}
-
-/* Do a smart match */
 PP(pp_smartmatch)
 {
 PP(pp_smartmatch)
 {
-    DEBUG_M(Perl_deb(aTHX_ "Starting smart match resolution\n"));
-    return do_smartmatch(NULL, NULL, 0);
-}
-
-/* This version of do_smartmatch() implements the
- * table of smart matches that is found in perlsyn.
- */
-STATIC OP *
-S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
-{
     dSP;
     dSP;
-    
-    bool object_on_left = FALSE;
-    SV *e = TOPs;      /* e is for 'expression' */
-    SV *d = TOPm1s;    /* d is for 'default', as in PL_defgv */
-
-    /* Take care only to invoke mg_get() once for each argument.
-     * Currently we do this by copying the SV if it's magical. */
-    if (d) {
-       if (!copied && SvGMAGICAL(d))
-           d = sv_mortalcopy(d);
-    }
-    else
-       d = &PL_sv_undef;
+    SV *right = POPs;
+    SV *left = TOPs;
+    SV *result;
 
 
-    assert(e);
-    if (SvGMAGICAL(e))
-       e = sv_mortalcopy(e);
-
-    /* First of all, handle overload magic of the rightmost argument */
-    if (SvAMAGIC(e)) {
-       SV * tmpsv;
-       DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-Object\n"));
-       DEBUG_M(Perl_deb(aTHX_ "        attempting overload\n"));
-
-       tmpsv = amagic_call(d, e, smart_amg, AMGf_noleft);
-       if (tmpsv) {
-           SPAGAIN;
-           (void)POPs;
-           SETs(tmpsv);
-           RETURN;
-       }
-       DEBUG_M(Perl_deb(aTHX_ "        failed to run overload method; continuing...\n"));
-    }
-
-    SP -= 2;   /* Pop the values */
     PUTBACK;
     PUTBACK;
-
-    /* ~~ undef */
-    if (!SvOK(e)) {
-       DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-undef\n"));
-       if (SvOK(d))
-           RETPUSHNO;
-       else
-           RETPUSHYES;
-    }
-
-    if (SvROK(e) && SvOBJECT(SvRV(e)) && (SvTYPE(SvRV(e)) != SVt_REGEXP)) {
-       DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-Object\n"));
-       Perl_croak(aTHX_ "Smart matching a non-overloaded object breaks encapsulation");
-    }
-    if (SvROK(d) && SvOBJECT(SvRV(d)) && (SvTYPE(SvRV(d)) != SVt_REGEXP))
-       object_on_left = TRUE;
-
-    /* ~~ sub */
-    if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVCV) {
-       I32 c;
-       if (object_on_left) {
-           goto sm_any_sub; /* Treat objects like scalars */
-       }
-       else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
-           /* Test sub truth for each key */
-           HE *he;
-           bool andedresults = TRUE;
-           HV *hv = (HV*) SvRV(d);
-           I32 numkeys = hv_iterinit(hv);
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Hash-CodeRef\n"));
-           if (numkeys == 0)
-               RETPUSHYES;
-           while ( (he = hv_iternext(hv)) ) {
-               DEBUG_M(Perl_deb(aTHX_ "        testing hash key...\n"));
-               ENTER_with_name("smartmatch_hash_key_test");
-               SAVETMPS;
-               PUSHMARK(SP);
-               PUSHs(hv_iterkeysv(he));
-               PUTBACK;
-               c = call_sv(e, G_SCALAR);
-               SPAGAIN;
-               if (c == 0)
-                   andedresults = FALSE;
-               else
-                   andedresults = SvTRUEx(POPs) && andedresults;
-               FREETMPS;
-               LEAVE_with_name("smartmatch_hash_key_test");
-           }
-           if (andedresults)
-               RETPUSHYES;
-           else
-               RETPUSHNO;
-       }
-       else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) {
-           /* Test sub truth for each element */
-           SSize_t i;
-           bool andedresults = TRUE;
-           AV *av = (AV*) SvRV(d);
-           const I32 len = av_tindex(av);
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Array-CodeRef\n"));
-           if (len == -1)
-               RETPUSHYES;
-           for (i = 0; i <= len; ++i) {
-               SV * const * const svp = av_fetch(av, i, FALSE);
-               DEBUG_M(Perl_deb(aTHX_ "        testing array element...\n"));
-               ENTER_with_name("smartmatch_array_elem_test");
-               SAVETMPS;
-               PUSHMARK(SP);
-               if (svp)
-                   PUSHs(*svp);
-               PUTBACK;
-               c = call_sv(e, G_SCALAR);
-               SPAGAIN;
-               if (c == 0)
-                   andedresults = FALSE;
-               else
-                   andedresults = SvTRUEx(POPs) && andedresults;
-               FREETMPS;
-               LEAVE_with_name("smartmatch_array_elem_test");
-           }
-           if (andedresults)
-               RETPUSHYES;
-           else
-               RETPUSHNO;
-       }
-       else {
-         sm_any_sub:
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-CodeRef\n"));
-           ENTER_with_name("smartmatch_coderef");
-           SAVETMPS;
-           PUSHMARK(SP);
-           PUSHs(d);
-           PUTBACK;
-           c = call_sv(e, G_SCALAR);
-           SPAGAIN;
-           if (c == 0)
-               PUSHs(&PL_sv_no);
-           else if (SvTEMP(TOPs))
-               SvREFCNT_inc_void(TOPs);
-           FREETMPS;
-           LEAVE_with_name("smartmatch_coderef");
-           RETURN;
-       }
-    }
-    /* ~~ %hash */
-    else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVHV) {
-       if (object_on_left) {
-           goto sm_any_hash; /* Treat objects like scalars */
-       }
-       else if (!SvOK(d)) {
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-Hash ($a undef)\n"));
-           RETPUSHNO;
-       }
-       else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
-           /* Check that the key-sets are identical */
-           HE *he;
-           HV *other_hv = MUTABLE_HV(SvRV(d));
-           bool tied;
-           bool other_tied;
-           U32 this_key_count  = 0,
-               other_key_count = 0;
-           HV *hv = MUTABLE_HV(SvRV(e));
-
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Hash-Hash\n"));
-           /* Tied hashes don't know how many keys they have. */
-           tied = cBOOL(SvTIED_mg((SV*)hv, PERL_MAGIC_tied));
-           other_tied = cBOOL(SvTIED_mg((const SV *)other_hv, PERL_MAGIC_tied));
-           if (!tied ) {
-               if(other_tied) {
-                   /* swap HV sides */
-                   HV * const temp = other_hv;
-                   other_hv = hv;
-                   hv = temp;
-                   tied = TRUE;
-                   other_tied = FALSE;
-               }
-               else if(HvUSEDKEYS((const HV *) hv) != HvUSEDKEYS(other_hv))
-                   RETPUSHNO;
-           }
-
-           /* The hashes have the same number of keys, so it suffices
-              to check that one is a subset of the other. */
-           (void) hv_iterinit(hv);
-           while ( (he = hv_iternext(hv)) ) {
-               SV *key = hv_iterkeysv(he);
-
-               DEBUG_M(Perl_deb(aTHX_ "        comparing hash key...\n"));
-               ++ this_key_count;
-               
-               if(!hv_exists_ent(other_hv, key, 0)) {
-                   (void) hv_iterinit(hv);     /* reset iterator */
-                   RETPUSHNO;
-               }
-           }
-           
-           if (other_tied) {
-               (void) hv_iterinit(other_hv);
-               while ( hv_iternext(other_hv) )
-                   ++other_key_count;
-           }
-           else
-               other_key_count = HvUSEDKEYS(other_hv);
-           
-           if (this_key_count != other_key_count)
-               RETPUSHNO;
-           else
-               RETPUSHYES;
-       }
-       else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) {
-           AV * const other_av = MUTABLE_AV(SvRV(d));
-           const SSize_t other_len = av_tindex(other_av) + 1;
-           SSize_t i;
-           HV *hv = MUTABLE_HV(SvRV(e));
-
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Array-Hash\n"));
-           for (i = 0; i < other_len; ++i) {
-               SV ** const svp = av_fetch(other_av, i, FALSE);
-               DEBUG_M(Perl_deb(aTHX_ "        checking for key existence...\n"));
-               if (svp) {      /* ??? When can this not happen? */
-                   if (hv_exists_ent(hv, *svp, 0))
-                       RETPUSHYES;
-               }
-           }
-           RETPUSHNO;
-       }
-       else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_REGEXP) {
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Regex-Hash\n"));
-         sm_regex_hash:
-           {
-               PMOP * const matcher = make_matcher((REGEXP*) SvRV(d));
-               HE *he;
-               HV *hv = MUTABLE_HV(SvRV(e));
-
-               (void) hv_iterinit(hv);
-               while ( (he = hv_iternext(hv)) ) {
-                   DEBUG_M(Perl_deb(aTHX_ "        testing key against pattern...\n"));
-                    PUTBACK;
-                   if (matcher_matches_sv(matcher, hv_iterkeysv(he))) {
-                        SPAGAIN;
-                       (void) hv_iterinit(hv);
-                       destroy_matcher(matcher);
-                       RETPUSHYES;
-                   }
-                    SPAGAIN;
-               }
-               destroy_matcher(matcher);
-               RETPUSHNO;
-           }
-       }
-       else {
-         sm_any_hash:
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-Hash\n"));
-           if (hv_exists_ent(MUTABLE_HV(SvRV(e)), d, 0))
-               RETPUSHYES;
-           else
-               RETPUSHNO;
-       }
-    }
-    /* ~~ @array */
-    else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVAV) {
-       if (object_on_left) {
-           goto sm_any_array; /* Treat objects like scalars */
-       }
-       else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
-           AV * const other_av = MUTABLE_AV(SvRV(e));
-           const SSize_t other_len = av_tindex(other_av) + 1;
-           SSize_t i;
-
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Hash-Array\n"));
-           for (i = 0; i < other_len; ++i) {
-               SV ** const svp = av_fetch(other_av, i, FALSE);
-
-               DEBUG_M(Perl_deb(aTHX_ "        testing for key existence...\n"));
-               if (svp) {      /* ??? When can this not happen? */
-                   if (hv_exists_ent(MUTABLE_HV(SvRV(d)), *svp, 0))
-                       RETPUSHYES;
-               }
-           }
-           RETPUSHNO;
-       }
-       if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) {
-           AV *other_av = MUTABLE_AV(SvRV(d));
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Array-Array\n"));
-           if (av_tindex(MUTABLE_AV(SvRV(e))) != av_tindex(other_av))
-               RETPUSHNO;
-           else {
-               SSize_t i;
-                const SSize_t other_len = av_tindex(other_av);
-
-               if (NULL == seen_this) {
-                   seen_this = newHV();
-                   (void) sv_2mortal(MUTABLE_SV(seen_this));
-               }
-               if (NULL == seen_other) {
-                   seen_other = newHV();
-                   (void) sv_2mortal(MUTABLE_SV(seen_other));
-               }
-               for(i = 0; i <= other_len; ++i) {
-                   SV * const * const this_elem = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE);
-                   SV * const * const other_elem = av_fetch(other_av, i, FALSE);
-
-                   if (!this_elem || !other_elem) {
-                       if ((this_elem && SvOK(*this_elem))
-                               || (other_elem && SvOK(*other_elem)))
-                           RETPUSHNO;
-                   }
-                   else if (hv_exists_ent(seen_this,
-                               sv_2mortal(newSViv(PTR2IV(*this_elem))), 0) ||
-                           hv_exists_ent(seen_other,
-                               sv_2mortal(newSViv(PTR2IV(*other_elem))), 0))
-                   {
-                       if (*this_elem != *other_elem)
-                           RETPUSHNO;
-                   }
-                   else {
-                       (void)hv_store_ent(seen_this,
-                               sv_2mortal(newSViv(PTR2IV(*this_elem))),
-                               &PL_sv_undef, 0);
-                       (void)hv_store_ent(seen_other,
-                               sv_2mortal(newSViv(PTR2IV(*other_elem))),
-                               &PL_sv_undef, 0);
-                       PUSHs(*other_elem);
-                       PUSHs(*this_elem);
-                       
-                       PUTBACK;
-                       DEBUG_M(Perl_deb(aTHX_ "        recursively comparing array element...\n"));
-                       (void) do_smartmatch(seen_this, seen_other, 0);
-                       SPAGAIN;
-                       DEBUG_M(Perl_deb(aTHX_ "        recursion finished\n"));
-                       
-                       if (!SvTRUEx(POPs))
-                           RETPUSHNO;
-                   }
-               }
-               RETPUSHYES;
-           }
-       }
-       else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_REGEXP) {
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Regex-Array\n"));
-         sm_regex_array:
-           {
-               PMOP * const matcher = make_matcher((REGEXP*) SvRV(d));
-               const SSize_t this_len = av_tindex(MUTABLE_AV(SvRV(e)));
-               SSize_t i;
-
-               for(i = 0; i <= this_len; ++i) {
-                   SV * const * const svp = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE);
-                   DEBUG_M(Perl_deb(aTHX_ "        testing element against pattern...\n"));
-                    PUTBACK;
-                   if (svp && matcher_matches_sv(matcher, *svp)) {
-                        SPAGAIN;
-                       destroy_matcher(matcher);
-                       RETPUSHYES;
-                   }
-                    SPAGAIN;
-               }
-               destroy_matcher(matcher);
-               RETPUSHNO;
-           }
-       }
-       else if (!SvOK(d)) {
-           /* undef ~~ array */
-           const SSize_t this_len = av_tindex(MUTABLE_AV(SvRV(e)));
-           SSize_t i;
-
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Undef-Array\n"));
-           for (i = 0; i <= this_len; ++i) {
-               SV * const * const svp = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE);
-               DEBUG_M(Perl_deb(aTHX_ "        testing for undef element...\n"));
-               if (!svp || !SvOK(*svp))
-                   RETPUSHYES;
-           }
-           RETPUSHNO;
-       }
-       else {
-         sm_any_array:
-           {
-               SSize_t i;
-               const SSize_t this_len = av_tindex(MUTABLE_AV(SvRV(e)));
-
-               DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-Array\n"));
-               for (i = 0; i <= this_len; ++i) {
-                   SV * const * const svp = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE);
-                   if (!svp)
-                       continue;
-
-                   PUSHs(d);
-                   PUSHs(*svp);
-                   PUTBACK;
-                   /* infinite recursion isn't supposed to happen here */
-                   DEBUG_M(Perl_deb(aTHX_ "        recursively testing array element...\n"));
-                   (void) do_smartmatch(NULL, NULL, 1);
-                   SPAGAIN;
-                   DEBUG_M(Perl_deb(aTHX_ "        recursion finished\n"));
-                   if (SvTRUEx(POPs))
-                       RETPUSHYES;
-               }
-               RETPUSHNO;
-           }
-       }
-    }
-    /* ~~ qr// */
-    else if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_REGEXP) {
-       if (!object_on_left && SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
-           SV *t = d; d = e; e = t;
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Hash-Regex\n"));
-           goto sm_regex_hash;
-       }
-       else if (!object_on_left && SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) {
-           SV *t = d; d = e; e = t;
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Array-Regex\n"));
-           goto sm_regex_array;
-       }
-       else {
-           PMOP * const matcher = make_matcher((REGEXP*) SvRV(e));
-            bool result;
-
-           DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-Regex\n"));
-           PUTBACK;
-           result = matcher_matches_sv(matcher, d);
-            SPAGAIN;
-           PUSHs(result ? &PL_sv_yes : &PL_sv_no);
-           destroy_matcher(matcher);
-           RETURN;
-       }
-    }
-    /* ~~ scalar */
-    /* See if there is overload magic on left */
-    else if (object_on_left && SvAMAGIC(d)) {
-       SV *tmpsv;
-       DEBUG_M(Perl_deb(aTHX_ "    applying rule Object-Any\n"));
-       DEBUG_M(Perl_deb(aTHX_ "        attempting overload\n"));
-       PUSHs(d); PUSHs(e);
-       PUTBACK;
-       tmpsv = amagic_call(d, e, smart_amg, AMGf_noright);
-       if (tmpsv) {
-           SPAGAIN;
-           (void)POPs;
-           SETs(tmpsv);
-           RETURN;
-       }
-       SP -= 2;
-       DEBUG_M(Perl_deb(aTHX_ "        failed to run overload method; falling back...\n"));
-       goto sm_any_scalar;
-    }
-    else if (!SvOK(d)) {
-       /* undef ~~ scalar ; we already know that the scalar is SvOK */
-       DEBUG_M(Perl_deb(aTHX_ "    applying rule undef-Any\n"));
-       RETPUSHNO;
-    }
-    else
-  sm_any_scalar:
-    if (SvNIOK(e) || (SvPOK(e) && looks_like_number(e) && SvNIOK(d))) {
-       DEBUG_M(if (SvNIOK(e))
-                   Perl_deb(aTHX_ "    applying rule Any-Num\n");
-               else
-                   Perl_deb(aTHX_ "    applying rule Num-numish\n");
-       );
-       /* numeric comparison */
-       PUSHs(d); PUSHs(e);
-       PUTBACK;
-       if (CopHINTS_get(PL_curcop) & HINT_INTEGER)
-           (void) Perl_pp_i_eq(aTHX);
-       else
-           (void) Perl_pp_eq(aTHX);
+    if (SvGMAGICAL(left))
+       left = sv_mortalcopy(left);
+    if (SvGMAGICAL(right))
+       right = sv_mortalcopy(right);
+    if (SvAMAGIC(right) &&
+               (result = amagic_call(left, right, smart_amg, AMGf_noleft))) {
        SPAGAIN;
        SPAGAIN;
-       if (SvTRUEx(POPs))
-           RETPUSHYES;
-       else
-           RETPUSHNO;
+       SETs(boolSV(SvTRUE_NN(result)));
+       return NORMAL;
     }
     }
-    
-    /* As a last resort, use string comparison */
-    DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-Any\n"));
-    PUSHs(d); PUSHs(e);
-    PUTBACK;
-    return Perl_pp_seq(aTHX);
+    Perl_croak(aTHX_ "Cannot smart match without a matcher object");
 }
 
 }
 
-PP(pp_enterwhen)
+PP(pp_enterwhereso)
 {
     dSP;
     PERL_CONTEXT *cx;
 {
     dSP;
     PERL_CONTEXT *cx;
@@ -5086,19 +4613,19 @@ PP(pp_enterwhen)
     /* This is essentially an optimization: if the match
        fails, we don't want to push a context and then
        pop it again right away, so we skip straight
     /* This is essentially an optimization: if the match
        fails, we don't want to push a context and then
        pop it again right away, so we skip straight
-       to the op that follows the leavewhen.
+       to the op that follows the leavewhereso.
        RETURNOP calls PUTBACK which restores the stack pointer after the POPs.
     */
        RETURNOP calls PUTBACK which restores the stack pointer after the POPs.
     */
-    if (!(PL_op->op_flags & OPf_SPECIAL) && !SvTRUEx(POPs))
+    if (!SvTRUEx(POPs))
        RETURNOP(cLOGOP->op_other->op_next);
 
        RETURNOP(cLOGOP->op_other->op_next);
 
-    cx = cx_pushblock(CXt_WHEN, gimme, SP, PL_savestack_ix);
-    cx_pushwhen(cx);
+    cx = cx_pushblock(CXt_WHERESO, gimme, SP, PL_savestack_ix);
+    cx_pushwhereso(cx);
 
     RETURN;
 }
 
 
     RETURN;
 }
 
-PP(pp_leavewhen)
+PP(pp_leavewhereso)
 {
     I32 cxix;
     PERL_CONTEXT *cx;
 {
     I32 cxix;
     PERL_CONTEXT *cx;
@@ -5106,14 +4633,12 @@ PP(pp_leavewhen)
     SV **oldsp;
 
     cx = CX_CUR();
     SV **oldsp;
 
     cx = CX_CUR();
-    assert(CxTYPE(cx) == CXt_WHEN);
+    assert(CxTYPE(cx) == CXt_WHERESO);
     gimme = cx->blk_gimme;
 
     gimme = cx->blk_gimme;
 
-    cxix = dopoptogivenfor(cxstack_ix);
+    cxix = dopoptoloop(cxstack_ix);
     if (cxix < 0)
     if (cxix < 0)
-       /* diag_listed_as: Can't "when" outside a topicalizer */
-       DIE(aTHX_ "Can't \"%s\" outside a topicalizer",
-                  PL_op->op_flags & OPf_SPECIAL ? "default" : "when");
+       DIE(aTHX_ "Can't leave \"whereso\" outside a loop block");
 
     oldsp = PL_stack_base + cx->blk_oldsp;
     if (gimme == G_VOID)
 
     oldsp = PL_stack_base + cx->blk_oldsp;
     if (gimme == G_VOID)
@@ -5121,24 +4646,25 @@ PP(pp_leavewhen)
     else
         leave_adjust_stacks(oldsp, oldsp, gimme, 1);
 
     else
         leave_adjust_stacks(oldsp, oldsp, gimme, 1);
 
-    /* pop the WHEN, BLOCK and anything else before the GIVEN/FOR */
+    /* pop the WHERESO, BLOCK and anything else before the loop */
     assert(cxix < cxstack_ix);
     dounwind(cxix);
 
     cx = &cxstack[cxix];
 
     assert(cxix < cxstack_ix);
     dounwind(cxix);
 
     cx = &cxstack[cxix];
 
-    if (CxFOREACH(cx)) {
+    if (CxTYPE(cx) != CXt_LOOP_GIVEN) {
         /* emulate pp_next. Note that any stack(s) cleanup will be
          * done by the pp_unstack which op_nextop should point to */
         cx = CX_CUR();
        cx_topblock(cx);
        PL_curcop = cx->blk_oldcop;
         /* emulate pp_next. Note that any stack(s) cleanup will be
          * done by the pp_unstack which op_nextop should point to */
         cx = CX_CUR();
        cx_topblock(cx);
        PL_curcop = cx->blk_oldcop;
+       PERL_ASYNC_CHECK();
        return cx->blk_loop.my_op->op_nextop;
     }
     else {
        PERL_ASYNC_CHECK();
        return cx->blk_loop.my_op->op_nextop;
     }
     else {
        PERL_ASYNC_CHECK();
-        assert(cx->blk_givwhen.leave_op->op_type == OP_LEAVEGIVEN);
-       return cx->blk_givwhen.leave_op;
+        assert(cx->blk_loop.my_op->op_nextop->op_type == OP_LEAVELOOP);
+       return cx->blk_loop.my_op->op_nextop;
     }
 }
 
     }
 }
 
@@ -5148,48 +4674,25 @@ PP(pp_continue)
     PERL_CONTEXT *cx;
     OP *nextop;
     
     PERL_CONTEXT *cx;
     OP *nextop;
     
-    cxix = dopoptowhen(cxstack_ix); 
+    cxix = dopoptowhereso(cxstack_ix); 
     if (cxix < 0)   
     if (cxix < 0)   
-       DIE(aTHX_ "Can't \"continue\" outside a when block");
+       DIE(aTHX_ "Can't \"continue\" outside a whereso block");
 
     if (cxix < cxstack_ix)
         dounwind(cxix);
     
     cx = CX_CUR();
 
     if (cxix < cxstack_ix)
         dounwind(cxix);
     
     cx = CX_CUR();
-    assert(CxTYPE(cx) == CXt_WHEN);
+    assert(CxTYPE(cx) == CXt_WHERESO);
     PL_stack_sp = PL_stack_base + cx->blk_oldsp;
     CX_LEAVE_SCOPE(cx);
     PL_stack_sp = PL_stack_base + cx->blk_oldsp;
     CX_LEAVE_SCOPE(cx);
-    cx_popwhen(cx);
+    cx_popwhereso(cx);
     cx_popblock(cx);
     cx_popblock(cx);
-    nextop = cx->blk_givwhen.leave_op->op_next;
+    nextop = cx->blk_whereso.leave_op->op_next;
     CX_POP(cx);
 
     return nextop;
 }
 
     CX_POP(cx);
 
     return nextop;
 }
 
-PP(pp_break)
-{
-    I32 cxix;
-    PERL_CONTEXT *cx;
-
-    cxix = dopoptogivenfor(cxstack_ix);
-    if (cxix < 0)
-       DIE(aTHX_ "Can't \"break\" outside a given block");
-
-    cx = &cxstack[cxix];
-    if (CxFOREACH(cx))
-       DIE(aTHX_ "Can't \"break\" in a loop topicalizer");
-
-    if (cxix < cxstack_ix)
-        dounwind(cxix);
-
-    /* Restore the sp at the time we entered the given block */
-    cx = CX_CUR();
-    PL_stack_sp = PL_stack_base + cx->blk_oldsp;
-
-    return cx->blk_givwhen.leave_op;
-}
-
 static MAGIC *
 S_doparseform(pTHX_ SV *sv)
 {
 static MAGIC *
 S_doparseform(pTHX_ SV *sv)
 {
@@ -5289,7 +4792,8 @@ S_doparseform(pTHX_ SV *sv)
            if (s < send) {
                skipspaces = 0;
                 continue;
            if (s < send) {
                skipspaces = 0;
                 continue;
-            } /* else FALL THROUGH */
+            }
+            /* FALLTHROUGH */
        case '\n':
            arg = s - base;
            skipspaces++;
        case '\n':
            arg = s - base;
            skipspaces++;
@@ -5557,7 +5061,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
 
        DEFSV_set(upstream);
        PUSHMARK(SP);
 
        DEFSV_set(upstream);
        PUSHMARK(SP);
-       mPUSHi(0);
+       PUSHs(&PL_sv_zero);
        if (filter_state) {
            PUSHs(filter_state);
        }
        if (filter_state) {
            PUSHs(filter_state);
        }