diff options
author | David Mitchell <davem@iabyn.com> | 2015-12-24 19:44:05 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2016-02-03 09:18:36 +0000 |
commit | fc6e609e613c36ececcd37d4c7f023be35a36578 (patch) | |
tree | 888d7c496fbbbab325cc0e664630da5bf1f666a2 /pp_ctl.c | |
parent | 7e09e582198d13c19d8edacfdfee681daa3f07a2 (diff) | |
download | perl-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.c | 20 |
1 files changed, 13 insertions, 7 deletions
@@ -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) |