summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cop.h2
-rw-r--r--pp_ctl.c16
2 files changed, 16 insertions, 2 deletions
diff --git a/cop.h b/cop.h
index 172c265a60..cb60a34cd6 100644
--- a/cop.h
+++ b/cop.h
@@ -333,6 +333,7 @@ struct block_eval {
SV * cur_text;
CV * cv;
OP * retop; /* op to execute on exit from eval */
+ JMPENV * cur_top_env; /* value of PL_top_env when eval CX created */
};
#define PUSHEVAL(cx,n,fgv) \
@@ -344,6 +345,7 @@ struct block_eval {
cx->blk_eval.cur_text = PL_linestr; \
cx->blk_eval.cv = Nullcv; /* set by doeval(), as applicable */ \
cx->blk_eval.retop = Nullop; \
+ cx->blk_eval.cur_top_env = PL_top_env; \
} STMT_END
#define POPEVAL(cx) \
diff --git a/pp_ctl.c b/pp_ctl.c
index ea83d1805b..c4aa30ed72 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2681,7 +2681,6 @@ S_docatch(pTHX_ OP *o)
{
int ret;
OP * const oldop = PL_op;
- volatile PERL_SI *cursi = PL_curstackinfo;
dJMPENV;
#ifdef DEBUGGING
@@ -2692,12 +2691,25 @@ S_docatch(pTHX_ OP *o)
JMPENV_PUSH(ret);
switch (ret) {
case 0:
+ assert(cxstack_ix >= 0);
+ assert(CxTYPE(&cxstack[cxstack_ix]) == CXt_EVAL);
+ cxstack[cxstack_ix].blk_eval.cur_top_env = PL_top_env;
redo_body:
docatch_body();
break;
case 3:
/* die caught by an inner eval - continue inner loop */
- if (PL_restartop && cursi == PL_curstackinfo) {
+
+ /* NB XXX we rely on the old popped CxEVAL still being at the top
+ * of the stack; the way die_where() currently works, this
+ * assumption is valid. In theory The cur_top_env value should be
+ * returned in another global, the way retop (aka PL_restartop)
+ * is. */
+ assert(CxTYPE(&cxstack[cxstack_ix+1]) == CXt_EVAL);
+
+ if (PL_restartop
+ && cxstack[cxstack_ix+1].blk_eval.cur_top_env == PL_top_env)
+ {
PL_op = PL_restartop;
PL_restartop = 0;
goto redo_body;