This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
move and rename cx_old_savestack_ix
[perl5.git] / pp_ctl.c
index a443bdf..74c4f58 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1266,10 +1266,11 @@ static const char * const context_name[] = {
     NULL, /* CXt_WHEN never actually needs "block" */
     NULL, /* CXt_BLOCK never actually needs "block" */
     NULL, /* CXt_GIVEN never actually needs "block" */
-    NULL, /* CXt_LOOP_FOR never actually needs "loop" */
     NULL, /* CXt_LOOP_PLAIN never actually needs "loop" */
-    NULL, /* CXt_LOOP_LAZYSV never actually needs "loop" */
     NULL, /* CXt_LOOP_LAZYIV never actually needs "loop" */
+    NULL, /* CXt_LOOP_LAZYSV never actually needs "loop" */
+    NULL, /* CXt_LOOP_LIST never actually needs "loop" */
+    NULL, /* CXt_LOOP_ARY never actually needs "loop" */
     "subroutine",
     "format",
     "eval",
@@ -1297,10 +1298,11 @@ S_dopoptolabel(pTHX_ const char *label, STRLEN len, U32 flags)
            if (CxTYPE(cx) == CXt_NULL) /* sort BLOCK */
                return -1;
            break;
+       case CXt_LOOP_PLAIN:
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
-       case CXt_LOOP_FOR:
-       case CXt_LOOP_PLAIN:
+       case CXt_LOOP_LIST:
+       case CXt_LOOP_ARY:
          {
             STRLEN cx_label_len = 0;
             U32 cx_label_flags = 0;
@@ -1444,10 +1446,11 @@ S_dopoptoloop(pTHX_ I32 startingblock)
            if ((CxTYPE(cx)) == CXt_NULL) /* sort BLOCK */
                return -1;
            break;
+       case CXt_LOOP_PLAIN:
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
-       case CXt_LOOP_FOR:
-       case CXt_LOOP_PLAIN:
+       case CXt_LOOP_LIST:
+       case CXt_LOOP_ARY:
            DEBUG_l( Perl_deb(aTHX_ "(dopoptoloop(): found loop at cx=%ld)\n", (long)i));
            return i;
        }
@@ -1470,12 +1473,13 @@ S_dopoptogivenfor(pTHX_ I32 startingblock)
            DEBUG_l( Perl_deb(aTHX_ "(dopoptogivenfor(): found given at cx=%ld)\n", (long)i));
            return i;
        case CXt_LOOP_PLAIN:
-           assert(!CxFOREACHDEF(cx));
+            assert(!(cx->cx_type & CXp_FOR_DEF));
            break;
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
-       case CXt_LOOP_FOR:
-           if (CxFOREACHDEF(cx)) {
+       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;
            }
@@ -1527,10 +1531,11 @@ Perl_dounwind(pTHX_ I32 cxix)
        case CXt_BLOCK:
             POPBASICBLK(cx);
            break;
+       case CXt_LOOP_PLAIN:
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
-       case CXt_LOOP_FOR:
-       case CXt_LOOP_PLAIN:
+       case CXt_LOOP_LIST:
+       case CXt_LOOP_ARY:
            POPLOOP(cx);
            break;
        case CXt_WHEN:
@@ -1573,20 +1578,17 @@ Perl_qerror(pTHX_ SV *err)
 
 
 
-/* pop the cx, undef or delete the %INC entry, then croak.
+/* undef or delete the $INC{namesv} entry, then croak.
  * require0 indicates that the require didn't return a true value */
 
-void
-S_undo_inc_then_croak(pTHX_ PERL_CONTEXT *cx, SV *err, bool require0)
+static void
+S_undo_inc_then_croak(pTHX_ SV *namesv, SV *err, bool require0)
 {
     const char *fmt;
     HV *inc_hv = GvHVn(PL_incgv);
-    SV *namesv = cx->blk_eval.old_namesv;
     I32  klen  = SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)SvCUR(namesv);
     const char *key = SvPVX_const(namesv);
 
-    CX_POP(cx);
-
     if (require0) {
        (void)hv_delete(inc_hv, key, klen, G_DISCARD);
        fmt = "%"SVf" did not return a true value";
@@ -1598,10 +1600,6 @@ S_undo_inc_then_croak(pTHX_ PERL_CONTEXT *cx, SV *err, bool require0)
         err = err ? err : newSVpvs_flags("Unknown error\n", SVs_TEMP);
     }
 
-    /* note that unlike pp_entereval, pp_require isn't
-     * supposed to trap errors. So now that we've popped the
-     * EVAL that pp_require pushed, and processed the error
-     * message, rethrow the error */
     Perl_croak(aTHX_ fmt, SVfARG(err));
 }
 
@@ -1663,6 +1661,7 @@ Perl_die_unwind(pTHX_ SV *msv)
        }
 
        if (cxix >= 0) {
+            SV *namesv = NULL;
            PERL_CONTEXT *cx;
            SV **newsp;
             I32 gimme;
@@ -1685,14 +1684,20 @@ Perl_die_unwind(pTHX_ SV *msv)
             CX_LEAVE_SCOPE(cx);
            POPEVAL(cx);
            POPBLOCK(cx);
-
            restartjmpenv = cx->blk_eval.cur_top_env;
            restartop = cx->blk_eval.retop;
-            if (CxOLD_OP_TYPE(cx) == OP_REQUIRE) {
-                S_undo_inc_then_croak(aTHX_ cx, exceptsv, FALSE);
+            if (CxOLD_OP_TYPE(cx) == OP_REQUIRE)
+                namesv = cx->blk_eval.old_namesv;
+            CX_POP(cx);
+
+            if (namesv) {
+                /* note that unlike pp_entereval, pp_require isn't
+                 * supposed to trap errors. So now that we've popped the
+                 * EVAL that pp_require pushed, process the error message
+                 * and rethrow the error */
+                S_undo_inc_then_croak(aTHX_ namesv, exceptsv, FALSE);
                 NOT_REACHED; /* NOTREACHED */
             }
-            CX_POP(cx);
 
            if (!(in_eval & EVAL_KEEPERR))
                sv_setsv(ERRSV, exceptsv);
@@ -2000,7 +2005,7 @@ PP(pp_dbstate)
            PUSHBLOCK(cx, CXt_SUB, SP);
            PUSHSUB_DB(cx);
            cx->blk_sub.retop = PL_op->op_next;
-            cx->cx_old_savestack_ix = PL_savestack_ix;
+            cx->blk_oldsaveix = PL_savestack_ix;
 
             SAVEI32(PL_debug);
             PL_debug = 0;
@@ -2142,7 +2147,7 @@ PP(pp_enteriter)
     const I32 gimme = GIMME_V;
     void *itervarp; /* GV or pad slot of the iteration variable */
     SV   *itersave; /* the old var in the iterator var slot */
-    U8 cxtype = CXt_LOOP_FOR;
+    U8 cxflags = 0;
 
     if (PL_op->op_targ) {                       /* "my" variable */
        itervarp = &PAD_SVl(PL_op->op_targ);
@@ -2155,7 +2160,7 @@ PP(pp_enteriter)
            SvPADSTALE_on(itersave);
        }
         SvREFCNT_inc_simple_void_NN(itersave);
-       cxtype |= CXp_FOR_PAD;
+       cxflags = CXp_FOR_PAD;
     }
     else {
        SV * const sv = POPs;
@@ -2167,53 +2172,41 @@ PP(pp_enteriter)
                 SvREFCNT_inc_simple_void_NN(itersave);
             else
                 *svp = newSV(0);
-            cxtype |= CXp_FOR_GV;
+            cxflags = CXp_FOR_GV;
         }
         else {                          /* LV ref: for \$foo (...) */
             assert(SvTYPE(sv) == SVt_PVMG);
             assert(SvMAGIC(sv));
             assert(SvMAGIC(sv)->mg_type == PERL_MAGIC_lvref);
             itersave = NULL;
-            cxtype |= CXp_FOR_LVREF;
+            cxflags = CXp_FOR_LVREF;
         }
     }
 
     if (PL_op->op_private & OPpITER_DEF)
-       cxtype |= CXp_FOR_DEF;
+       cxflags |= CXp_FOR_DEF;
 
-    PUSHBLOCK(cx, cxtype, SP);
-    PUSHLOOP_FOR(cx, itervarp, itersave, MARK);
+    PUSHBLOCK(cx, cxflags, MARK);
+    PUSHLOOP_FOR(cx, itervarp, itersave);
     if (PL_op->op_flags & OPf_STACKED) {
        SV *maybe_ary = POPs;
        if (SvTYPE(maybe_ary) != SVt_PVAV) {
            dPOPss;
            SV * const right = maybe_ary;
-           if (UNLIKELY(cxtype & CXp_FOR_LVREF))
+           if (UNLIKELY(cxflags & CXp_FOR_LVREF))
                DIE(aTHX_ "Assigned value is not a reference");
            SvGETMAGIC(sv);
            SvGETMAGIC(right);
            if (RANGE_IS_NUMERIC(sv,right)) {
-               cx->cx_type &= ~CXTYPEMASK;
                cx->cx_type |= CXt_LOOP_LAZYIV;
-               /* Make sure that no-one re-orders cop.h and breaks our
-                  assumptions */
-               assert(CxTYPE(cx) == CXt_LOOP_LAZYIV);
                if (S_outside_integer(aTHX_ sv) ||
                     S_outside_integer(aTHX_ right))
                    DIE(aTHX_ "Range iterator outside integer range");
                cx->blk_loop.state_u.lazyiv.cur = SvIV_nomg(sv);
                cx->blk_loop.state_u.lazyiv.end = SvIV_nomg(right);
-#ifdef DEBUGGING
-               /* for correct -Dstv display */
-               cx->blk_oldsp = sp - PL_stack_base;
-#endif
            }
            else {
-               cx->cx_type &= ~CXTYPEMASK;
                cx->cx_type |= CXt_LOOP_LAZYSV;
-               /* Make sure that no-one re-orders cop.h and breaks our
-                  assumptions */
-               assert(CxTYPE(cx) == CXt_LOOP_LAZYSV);
                cx->blk_loop.state_u.lazysv.cur = newSVsv(sv);
                cx->blk_loop.state_u.lazysv.end = right;
                SvREFCNT_inc(right);
@@ -2230,6 +2223,7 @@ PP(pp_enteriter)
            }
        }
        else /* SvTYPE(maybe_ary) == SVt_PVAV */ {
+            cx->cx_type |= CXt_LOOP_ARY;
            cx->blk_loop.state_u.ary.ary = MUTABLE_AV(maybe_ary);
            SvREFCNT_inc(maybe_ary);
            cx->blk_loop.state_u.ary.ix =
@@ -2237,15 +2231,19 @@ PP(pp_enteriter)
                AvFILL(cx->blk_loop.state_u.ary.ary) + 1 :
                -1;
        }
+        /* EXTEND(SP, 1) not needed in this branch because we just did POPs */
     }
     else { /* iterating over items on the stack */
-       cx->blk_loop.state_u.ary.ary = NULL; /* means to use the stack */
-       if (PL_op->op_private & OPpITER_REVERSED) {
-           cx->blk_loop.state_u.ary.ix = cx->blk_oldsp + 1;
-       }
-       else {
-           cx->blk_loop.state_u.ary.ix = MARK - PL_stack_base;
-       }
+        cx->cx_type |= CXt_LOOP_LIST;
+        cx->blk_oldsp = SP - PL_stack_base;
+       cx->blk_loop.state_u.stack.basesp = MARK - PL_stack_base;
+        cx->blk_loop.state_u.stack.ix =
+            (PL_op->op_private & OPpITER_REVERSED)
+                ? cx->blk_oldsp + 1
+                : cx->blk_loop.state_u.stack.basesp;
+        /* pre-extend stack so pp_iter doesn't have to check every time
+         * it pushes yes/no */
+        EXTEND(SP, 1);
     }
 
     RETURN;
@@ -2258,7 +2256,7 @@ PP(pp_enterloop)
     const I32 gimme = GIMME_V;
 
     PUSHBLOCK(cx, CXt_LOOP_PLAIN, SP);
-    PUSHLOOP_PLAIN(cx, SP);
+    PUSHLOOP_PLAIN(cx);
 
     RETURN;
 }
@@ -2273,7 +2271,9 @@ PP(pp_leaveloop)
     cx = &cxstack[cxstack_ix];
     assert(CxTYPE_is_LOOP(cx));
     mark = PL_stack_base + cx->blk_oldsp;
-    newsp = PL_stack_base + cx->blk_loop.resetsp;
+    newsp = CxTYPE(cx) == CXt_LOOP_LIST
+                ? PL_stack_base + cx->blk_loop.state_u.stack.basesp
+                : mark;
     gimme = cx->blk_gimme;
 
     if (gimme == G_VOID)
@@ -2577,13 +2577,12 @@ PP(pp_last)
 
     cx = &cxstack[cxstack_ix];
 
-    assert(
-           CxTYPE(cx) == CXt_LOOP_LAZYIV
-        || CxTYPE(cx) == CXt_LOOP_LAZYSV
-        || CxTYPE(cx) == CXt_LOOP_FOR
-        || CxTYPE(cx) == CXt_LOOP_PLAIN
-    );
-    PL_stack_sp = PL_stack_base + cx->blk_loop.resetsp;
+    assert(CxTYPE_is_LOOP(cx));
+    PL_stack_sp = PL_stack_base
+                + (CxTYPE(cx) == CXt_LOOP_LIST
+                    ?  cx->blk_loop.state_u.stack.basesp
+                    : cx->blk_oldsp
+                );
 
     TAINT_NOT;
 
@@ -2969,10 +2968,11 @@ PP(pp_goto)
                    break;
                 }
                 /* else fall through */
-           case CXt_LOOP_LAZYIV:
-           case CXt_LOOP_LAZYSV:
-           case CXt_LOOP_FOR:
-           case CXt_LOOP_PLAIN:
+            case CXt_LOOP_PLAIN:
+            case CXt_LOOP_LAZYIV:
+            case CXt_LOOP_LAZYSV:
+            case CXt_LOOP_LIST:
+            case CXt_LOOP_ARY:
            case CXt_GIVEN:
            case CXt_WHEN:
                gotoprobe = OpSIBLING(cx->blk_oldcop);
@@ -3310,7 +3310,7 @@ S_try_yyparse(pTHX_ int gramtype)
  */
 
 STATIC bool
-S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
+S_doeval_compile(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
 {
     dSP;
     OP * const saveop = PL_op;
@@ -3434,6 +3434,7 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
     yystatus = (!in_require && CATCH_GET) ? S_try_yyparse(aTHX_ GRAMPROG) : yyparse(GRAMPROG);
 
     if (yystatus || PL_parser->error_count || !PL_eval_root) {
+        SV *namesv = NULL; /* initialise  to avoid compiler warning */
        PERL_CONTEXT *cx;
         SV *errsv;
 
@@ -3451,19 +3452,19 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
             CX_LEAVE_SCOPE(cx);
            POPEVAL(cx);
            POPBLOCK(cx);
-            if (in_require) {
-                S_undo_inc_then_croak(aTHX_ cx, ERRSV, FALSE);
-                NOT_REACHED; /* NOTREACHED */
-            }
+            if (in_require)
+                namesv = cx->blk_eval.old_namesv;
             CX_POP(cx);
        }
 
        errsv = ERRSV;
        if (in_require) {
-            assert(yystatus == 3);
-            cx = &cxstack[cxstack_ix];
-            assert(CxTYPE(cx) == CXt_EVAL);
-            S_undo_inc_then_croak(aTHX_ cx, errsv, FALSE);
+            if (yystatus == 3) {
+                cx = &cxstack[cxstack_ix];
+                assert(CxTYPE(cx) == CXt_EVAL);
+                namesv = cx->blk_eval.old_namesv;
+            }
+            S_undo_inc_then_croak(aTHX_ namesv, errsv, FALSE);
             NOT_REACHED; /* NOTREACHED */
        }
 
@@ -4096,7 +4097,7 @@ PP(pp_require)
     /* switch to eval mode */
     PUSHBLOCK(cx, CXt_EVAL, SP);
     PUSHEVAL(cx, name);
-    cx->cx_old_savestack_ix = old_savestack_ix;
+    cx->blk_oldsaveix = old_savestack_ix;
     cx->blk_eval.retop = PL_op->op_next;
 
     SAVECOPLINE(&PL_compiling);
@@ -4104,7 +4105,7 @@ PP(pp_require)
 
     PUTBACK;
 
-    if (doeval(gimme, NULL, PL_curcop->cop_seq, NULL))
+    if (doeval_compile(gimme, NULL, PL_curcop->cop_seq, NULL))
        op = DOCATCH(PL_eval_start);
     else
        op = PL_op->op_next;
@@ -4212,7 +4213,7 @@ PP(pp_entereval)
 
     PUSHBLOCK(cx, (CXt_EVAL|CXp_REAL), SP);
     PUSHEVAL(cx, 0);
-    cx->cx_old_savestack_ix = old_savestack_ix;
+    cx->blk_oldsaveix = old_savestack_ix;
     cx->blk_eval.retop = PL_op->op_next;
 
     /* prepare to compile string */
@@ -4232,7 +4233,7 @@ PP(pp_entereval)
     
     PUTBACK;
 
-    if (doeval(gimme, runcv, seq, saved_hh)) {
+    if (doeval_compile(gimme, runcv, seq, saved_hh)) {
        if (was != PL_breakable_sub_gen /* Some subs defined here. */
            ?  PERLDB_LINE_OR_SAVESRC
            :  PERLDB_SAVESRC_NOSUBS) {
@@ -4244,7 +4245,7 @@ PP(pp_entereval)
        return DOCATCH(PL_eval_start);
     } else {
        /* We have already left the scope set up earlier thanks to the LEAVE
-          in doeval().  */
+          in doeval_compile().  */
        if (was != PL_breakable_sub_gen /* Some subs defined here. */
            ?  PERLDB_LINE_OR_SAVESRC
            :  PERLDB_SAVESRC_INVALID) {
@@ -4258,12 +4259,11 @@ PP(pp_entereval)
 
 PP(pp_leaveeval)
 {
-    dSP;
     SV **newsp;
     I32 gimme;
     PERL_CONTEXT *cx;
     OP *retop;
-    I32 optype;
+    SV *namesv = NULL;
     CV *evalcv;
     /* grab this value before POPEVAL restores old PL_in_eval */
     bool keep = cBOOL(PL_in_eval & EVAL_KEEPERR);
@@ -4272,14 +4272,23 @@ PP(pp_leaveeval)
 
     cx = &cxstack[cxstack_ix];
     assert(CxTYPE(cx) == CXt_EVAL);
+
     newsp = PL_stack_base + cx->blk_oldsp;
     gimme = cx->blk_gimme;
 
-    if (gimme != G_VOID) {
-        PUTBACK;
+    /* did require return a false value? */
+    if (       CxOLD_OP_TYPE(cx) == OP_REQUIRE
+            && !(gimme == G_SCALAR
+                    ? SvTRUE(*PL_stack_sp)
+                : PL_stack_sp > newsp)
+    )
+        namesv = cx->blk_eval.old_namesv;
+
+    if (gimme == G_VOID)
+        PL_stack_sp = newsp;
+    else
         leave_common(newsp, newsp, gimme, SVs_TEMP, FALSE);
-        SPAGAIN;
-    }
+
     /* the POPEVAL does a leavescope, which frees the optree associated
      * with eval, which if it frees the nextstate associated with
      * PL_curcop, sets PL_curcop to NULL. Which can mess up freeing a
@@ -4287,33 +4296,29 @@ PP(pp_leaveeval)
      * to get the current hints. So restore it early.
      */
     PL_curcop = cx->blk_oldcop;
+
     CX_LEAVE_SCOPE(cx);
     POPEVAL(cx);
     POPBLOCK(cx);
     retop = cx->blk_eval.retop;
     evalcv = cx->blk_eval.cv;
-    optype = CxOLD_OP_TYPE(cx);
-
+    CX_POP(cx);
 
 #ifdef DEBUGGING
     assert(CvDEPTH(evalcv) == 1);
 #endif
     CvDEPTH(evalcv) = 0;
 
-    if (optype == OP_REQUIRE &&
-       !(gimme == G_SCALAR ? SvTRUE(*SP) : SP > newsp))
-    {
+    if (namesv) { /* require returned false */
        /* Unassume the success we assumed earlier. */
-        S_undo_inc_then_croak(aTHX_ cx, NULL, TRUE);
+        S_undo_inc_then_croak(aTHX_ namesv, NULL, TRUE);
         NOT_REACHED; /* NOTREACHED */
     }
 
-    CX_POP(cx);
-
     if (!keep)
         CLEAR_ERRSV();
 
-    RETURNOP(retop);
+    return retop;
 }
 
 /* Common code for Perl_call_sv and Perl_fold_constants, put here to keep it
@@ -4340,7 +4345,7 @@ Perl_create_eval_scope(pTHX_ U32 flags)
        
     PUSHBLOCK(cx, (CXt_EVAL|CXp_TRYBLOCK), PL_stack_sp);
     PUSHEVAL(cx, 0);
-    cx->cx_old_savestack_ix = PL_savestack_ix;
+    cx->blk_oldsaveix = PL_savestack_ix;
 
     PL_in_eval = EVAL_INEVAL;
     if (flags & G_KEEPERR)