This is a live mirror of the Perl 5 development currently hosted at
Unwind save stack in sync with POPEVAL
authorDavid Mitchell <>
Wed, 1 Jul 2015 08:57:51 +0000 (09:57 +0100)
committerDavid Mitchell <>
Wed, 3 Feb 2016 08:59:34 +0000 (08:59 +0000)
During normal exit from an eval, both POPEVAL and LEAVE are done,
meaning that the context stack and save stack are unwound in lockstep.

However, during an exception, dounwind() does the POPEVAL but not the
LEAVE, leaving them temporarily out of step.

About a 2 years ago, with v5.19.3-139-g2537512, subs and formats were
changed so that the save stack popping was done in sync in dounwind.

This commit extends that to evals too.

I'm doing this principally so that PL_compad will always be restored at
the correct moment, which will shortly allow me to eliminate the argarray
field from the context struct.

NB: unlike POPSUB and POPFORMAT, I've added the LEAVE_SCOPE to dounwind
rather than directly adding to the POPEVAL macro - this is because the
various places that use POPEVAL typically use it earlier than the
comparable places with POPSUB, which means they aren't ready to pop the
save stack yet.

NNB: The LEAVE_SCOPE can't be extended to all context types in dounwind(),
only to sub-ish types - specifically the types that can be 'return'ed from.
This is because if you 'return' from a sub or eval, pp_return will
unwind all contexts down to the next sub or eval (discarding all the loops
etc that it escaping out of), but the args it is returning shouldn't
be prematurely freed.


index 96b6e9f..05dd5c2 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1519,6 +1519,7 @@ Perl_dounwind(pTHX_ I32 cxix)
        case CXt_EVAL:
+            LEAVE_SCOPE(PL_scopestack[cx->blk_oldscopesp-1]);
        case CXt_LOOP_LAZYIV:
        case CXt_LOOP_LAZYSV:
@@ -4257,6 +4258,7 @@ PP(pp_leaveeval)
                         SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)SvCUR(namesv),
+       LEAVE_with_name("eval");
        Perl_die(aTHX_ "%"SVf" did not return a true value", SVfARG(namesv));
        /* die_unwind() did LEAVE, or we won't be here */