This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
add CXp_FOR_PAD, CXp_FOR_GV flags
[perl5.git] / pp_ctl.c
index d3c35c8..7b3589d 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1995,10 +1995,14 @@ PP(pp_dbstate)
 /* S_leave_common: Common code that many functions in this file use on
                   scope exit.
 
-   Process the return args on the stack in the range (mark..sp) based on
-   context, with any final args starting at newsp.
+   Process the return args on the stack in the range (mark+1..sp) based on
+   context, with any final args starting at newsp+1. Returns the new
+   top-of-stack position
    Args are mortal copied (or mortalied if lvalue) unless its safe to use
-   as-is, based on whether it the specified flags
+   as-is, based on whether it has the specified flags. Note that most
+   callers specify flags as (SVs_PADTMP|SVs_TEMP), while leaveeval skips
+   SVs_PADTMP since its optree gets immediately freed, freeing its padtmps
+   at the same time.
 
    Also, taintedness is cleared.
 */
@@ -2113,36 +2117,42 @@ PP(pp_enteriter)
     dSP; dMARK;
     PERL_CONTEXT *cx;
     const I32 gimme = GIMME_V;
-    void *itervar; /* location of the iteration variable */
+    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;
 
     ENTER_with_name("loop1");
     SAVETMPS;
 
     if (PL_op->op_targ) {                       /* "my" variable */
+       itervarp = &PAD_SVl(PL_op->op_targ);
+        itersave = *(SV**)itervarp;
+        assert(itersave);
        if (PL_op->op_private & OPpLVAL_INTRO) {        /* for my $x (...) */
             /* the SV currently in the pad slot is never live during
              * iteration (the slot is always aliased to one of the items)
              * so it's always stale */
-           SvPADSTALE_on(PAD_SVl(PL_op->op_targ));
+           SvPADSTALE_on(itersave);
        }
-       SAVEPADSVANDMORTALIZE(PL_op->op_targ);
-       itervar = &PAD_SVl(PL_op->op_targ);
+        SvREFCNT_inc_simple_void_NN(itersave);
+       cxtype |= CXp_FOR_PAD;
     }
     else if (LIKELY(isGV(TOPs))) {             /* symbol table variable */
        GV * const gv = MUTABLE_GV(POPs);
        SV** svp = &GvSV(gv);
-       save_pushptrptr(gv, SvREFCNT_inc(*svp), SAVEt_GVSV);
+       itervarp = (void *)gv;
+        itersave = *svp;
        *svp = newSV(0);
-       itervar = (void *)gv;
+       cxtype |= CXp_FOR_GV;
     }
     else {
        SV * const sv = POPs;
        assert(SvTYPE(sv) == SVt_PVMG);
        assert(SvMAGIC(sv));
        assert(SvMAGIC(sv)->mg_type == PERL_MAGIC_lvref);
-       itervar = (void *)sv;
+       itervarp = (void *)sv;
        cxtype |= CXp_FOR_LVREF;
+        itersave = NULL;
     }
 
     if (PL_op->op_private & OPpITER_DEF)
@@ -2151,7 +2161,7 @@ PP(pp_enteriter)
     ENTER_with_name("loop2");
 
     PUSHBLOCK(cx, cxtype, SP);
-    PUSHLOOP_FOR(cx, itervar, MARK);
+    PUSHLOOP_FOR(cx, itervarp, itersave, MARK);
     if (PL_op->op_flags & OPf_STACKED) {
        SV *maybe_ary = POPs;
        if (SvTYPE(maybe_ary) != SVt_PVAV) {
@@ -2252,7 +2262,7 @@ PP(pp_leaveloop)
 
     SP = (gimme == G_VOID)
         ? newsp
-        : leave_common(newsp, SP, MARK, gimme, 0,
+        : leave_common(newsp, SP, MARK, gimme, SVs_PADTMP|SVs_TEMP,
                               PL_op->op_private & OPpLVALUE);
     PUTBACK;
 
@@ -2304,7 +2314,6 @@ PP(pp_leavesublv)
        if (CxLVAL(cx) && !ref) {     /* Leave it as it is if we can. */
            SV *sv;
            if (MARK <= SP) {
-               assert(MARK == SP);
                if ((SvPADTMP(TOPs) || SvREADONLY(TOPs)) &&
                    !SvSMAGICAL(TOPs)) {
                    what =
@@ -2401,55 +2410,81 @@ PP(pp_return)
 {
     dSP; dMARK;
     PERL_CONTEXT *cx;
-    SV **oldsp;
     const I32 cxix = dopoptosub(cxstack_ix);
 
     assert(cxstack_ix >= 0);
     if (cxix < cxstack_ix) {
         if (cxix < 0) {
-            if (CxMULTICALL(cxstack)) { /* In this case we must be in a
-                                         * sort block, which is a CXt_NULL
-                                         * not a CXt_SUB */
-                dounwind(0);
-                /* if we were in list context, we would have to splice out
-                 * any junk before the return args, like we do in the general
-                 * pp_return case, e.g.
-                 *   sub f { for (junk1, junk2) { return arg1, arg2 }}
-                 */
+            if (!CxMULTICALL(cxstack))
+                DIE(aTHX_ "Can't return outside a subroutine");
+            /* We must be in a sort block, which is a CXt_NULL not a
+             * CXt_SUB. Handle specially. */
+            if (cxstack_ix > 0) {
+                /* See comment below about context popping. Since we know
+                 * we're scalar and not lvalue, we can preserve the return
+                 * value in a simpler fashion than there. */
+                SV *sv = *SP;
                 assert(cxstack[0].blk_gimme == G_SCALAR);
-                return 0;
+                if (   (sp != PL_stack_base)
+                    && !(SvFLAGS(sv) & (SVs_TEMP|SVs_PADTMP))
+                )
+                    *SP = sv_mortalcopy(sv);
+                dounwind(0);
             }
-            else
-                DIE(aTHX_ "Can't return outside a subroutine");
+            /* caller responsible for popping cxstack[0] */
+            return 0;
         }
-       dounwind(cxix);
-    }
-
-    cx = &cxstack[cxix];
 
-    oldsp = PL_stack_base + cx->blk_oldsp;
-    if (oldsp != MARK) {
-        /* Handle extra junk on the stack. For example,
+        /* There are contexts that need popping. Doing this may free the
+         * return value(s), so preserve them first, e.g. popping the plain
+         * loop here would free $x:
+         *     sub f {  { my $x = 1; return $x } }
+         * We may also need to shift the args down; for example,
          *    for (1,2) { return 3,4 }
-         * leaves 1,2,3,4 on the stack. In list context we
-         * have to splice out the 1,2; In scalar context for
+         * leaves 1,2,3,4 on the stack. Both these actions can be done by
+         * leave_common().  By calling it with lvalue=TRUE, we just bump
+         * the ref count and mortalise the args that need it.  The "scan
+         * the args and maybe copy them" process will be repeated by
+         * whoever we tail-call (e.g. pp_leaveeval), where any copying etc
+         * will be done. That is to say, in this code path two scans of
+         * the args will be done; the first just shifts and preserves; the
+         * second is the "real" arg processing, based on the type of
+         * return.
+         */
+        cx = &cxstack[cxix];
+        SP = leave_common(PL_stack_base + cx->blk_oldsp, SP, MARK,
+                            cx->blk_gimme, SVs_TEMP|SVs_PADTMP, TRUE);
+        PUTBACK;
+       dounwind(cxix);
+    }
+    else {
+        /* Like in the branch above, we need to handle any extra junk on
+         * the stack. But because we're not also popping extra contexts, we
+         * don't have to worry about prematurely freeing args. So we just
+         * need to do the bare minimum to handle junk, and leave the main
+         * arg processing in the function we tail call, e.g. pp_leavesub.
+         * In list context we have to splice out the junk; in scalar
+         * context we can leave as-is (pp_leavesub will later return the
+         * top stack element). But for an  empty arg list, e.g.
          *    for (1,2) { return }
-         * we need to set sp = oldsp so that pp_leavesub knows
-         * to push &PL_sv_undef onto the stack.
-         * Note that in pp_return we only do the extra processing
-         * required to handle junk; everything else we leave to
-         * pp_leavesub.
+         * we need to set sp = oldsp so that pp_leavesub knows to push
+         * &PL_sv_undef onto the stack.
          */
-        SSize_t nargs = SP - MARK;
-        if (nargs) {
-            if (cx->blk_gimme == G_ARRAY) {
-                /* shift return args to base of call stack frame */
-                Move(MARK + 1, oldsp + 1, nargs, SV*);
-                PL_stack_sp  = oldsp + nargs;
+        SV **oldsp;
+        cx = &cxstack[cxix];
+        oldsp = PL_stack_base + cx->blk_oldsp;
+        if (oldsp != MARK) {
+            SSize_t nargs = SP - MARK;
+            if (nargs) {
+                if (cx->blk_gimme == G_ARRAY) {
+                    /* shift return args to base of call stack frame */
+                    Move(MARK + 1, oldsp + 1, nargs, SV*);
+                    PL_stack_sp  = oldsp + nargs;
+                }
             }
+            else
+                PL_stack_sp  = oldsp;
         }
-        else
-            PL_stack_sp  = oldsp;
     }
 
     /* fall through to a normal exit */