summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-12-24 19:44:05 +0000
committerDavid Mitchell <davem@iabyn.com>2016-02-03 09:18:36 +0000
commitfc6e609e613c36ececcd37d4c7f023be35a36578 (patch)
tree888d7c496fbbbab325cc0e664630da5bf1f666a2 /pp_ctl.c
parent7e09e582198d13c19d8edacfdfee681daa3f07a2 (diff)
downloadperl-fc6e609e613c36ececcd37d4c7f023be35a36578.tar.gz
dounwind(): do a POPBLOCK for final cx frame.
Previously dounwind() relied on the caller to a TOPBLOCK or POPBLOCK following the call to dounwind(). It's debatable who should be responsible. Arguably its more efficient for dounwind() not to do a POPBLOCK, since the caller will probably immediately follow on with POPFOO; POPBLOCK for the next context frame anyway. Logically however, dounwind() should do this, and its not possible for the caller to do so retrospectively, as context frame cxstack_ix + 1 may have been overwritten by the time dounwind returns. Also, the changes in this branch mean that the old PL_tmps_floor is now saved in the context struct rather than on the save stack, so code that does C<dounwind(-1); LEAVE_SCOPE();> will no longer automatically restore PL_tmps_floor. With thiis commit, it will. The change to pp_return reflects that we now need to copy any return args *before* donwind() is called, so that "return $1" will mg_get($1) while the correct (inner) PL_curpm is still in scope.
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 10e258b37a..ce679738fe 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1506,12 +1506,10 @@ S_dopoptowhen(pTHX_ I32 startingblock)
}
/* dounwind(): pop all contexts above (but not including) cxix.
- * Leaves cxstack_ix equal to cxix. Note that for efficiency, it doesn't
- * call POPBLOCK at all; the caller should do
- * CX_LEAVE_SCOPE; POPFOO; POPBLOCK
- * or
- * TOPBLOCK
- * as appropriate.
+ * Note that it clears the savestack frame associated with each popped
+ * context entry, but doesn't free any temps.
+ * It does a POPBLOCK of the last frame that it pops, and leaves
+ * cxstack_ix equal to cxix.
*/
void
@@ -1561,8 +1559,12 @@ Perl_dounwind(pTHX_ I32 cxix)
POPFORMAT(cx);
break;
}
+ if (cxstack_ix == cxix + 1) {
+ POPBLOCK(cx);
+ }
cxstack_ix--;
}
+
}
void
@@ -2417,7 +2419,9 @@ PP(pp_return)
PUTBACK;
if (cx->blk_gimme != G_VOID)
leave_adjust_stacks(MARK, PL_stack_base + cx->blk_oldsp,
- cx->blk_gimme, 3);
+ cx->blk_gimme,
+ CxTYPE(cx) == CXt_SUB && CvLVALUE(cx->blk_sub.cv)
+ ? 3 : 0);
SPAGAIN;
dounwind(cxix);
cx = &cxstack[cxix]; /* CX stack may have been realloced */
@@ -2469,6 +2473,8 @@ PP(pp_return)
}
}
+/* find the enclosing loop or labelled loop and dounwind() back to it.
+ * opname is for errors */
static I32
S_unwind_loop(pTHX_ const char * const opname)