#define CX_LEAVE_SCOPE(cx) LEAVE_SCOPE(cx->cx_old_savestack_ix)
+#ifdef DEBUGGING
+/* on debugging builds, poison cx afterwards so we know no code
+ * uses it - because after doing cxstack_ix--, any ties, exceptions etc
+ * may overwrite the current stack frame */
+# define CX_POP(cx) \
+ assert(&cxstack[cxstack_ix] == cx); \
+ cxstack_ix--; \
+ cx = NULL;
+#else
+# define CX_POP(cx) cxstack_ix--;
+#endif
+
+
/* base for the next two macros. Don't use directly.
* The context frame holds a reference to the CV so that it can't be
* freed while we're executing it */
CvDEPTH((const CV*)cx->blk_sub.cv) = cx->blk_sub.olddepth; \
SvREFCNT_dec_NN(cx->blk_sub.cv);
+/* handle the @_ part of leaving a sub */
+
+#define POPSUB_ARGS(cx) \
+ STMT_START { \
+ AV *av; \
+ assert(AvARRAY(MUTABLE_AV( \
+ PadlistARRAY(CvPADLIST(cx->blk_sub.cv))[ \
+ CvDEPTH(cx->blk_sub.cv)])) == PL_curpad); \
+ POP_SAVEARRAY(); \
+ /* abandon @_ if it got reified */ \
+ av = MUTABLE_AV(PAD_SVl(0)); \
+ if (UNLIKELY(AvREAL(av))) \
+ clear_defarray(av, 0); \
+ else { \
+ CLEAR_ARGARRAY(av); \
+ } \
+ } STMT_END
#define POPSUB(cx) \
STMT_START { \
CopSTASHPV((COP*)CvSTART((const CV*)cx->blk_sub.cv))); \
\
if (CxHASARGS(cx)) { \
- AV *av; \
- assert(AvARRAY(MUTABLE_AV( \
- PadlistARRAY(CvPADLIST(cx->blk_sub.cv))[ \
- CvDEPTH(cx->blk_sub.cv)])) == PL_curpad); \
- POP_SAVEARRAY(); \
- /* abandon @_ if it got reified */ \
- av = MUTABLE_AV(PAD_SVl(0)); \
- if (UNLIKELY(AvREAL(av))) \
- clear_defarray(av, 0); \
- else { \
- CLEAR_ARGARRAY(av); \
- } \
+ POPSUB_ARGS(cx); \
} \
} \
POPSUB_COMMON(cx); \
#define POPEVAL(cx) \
STMT_START { \
PL_in_eval = CxOLD_IN_EVAL(cx); \
- optype = CxOLD_OP_TYPE(cx); \
PL_eval_root = cx->blk_eval.old_eval_root; \
if (cx->blk_eval.cur_text && SvSCREAM(cx->blk_eval.cur_text)) \
SvREFCNT_dec_NN(cx->blk_eval.cur_text); \
cx = &cxstack[cxstack_ix]; \
CX_LEAVE_SCOPE(cx); \
POPSUB_COMMON(cx); \
- POPBLOCK(cx); \
newsp = PL_stack_base + cx->blk_oldsp; \
gimme = cx->blk_gimme; \
PERL_UNUSED_VAR(newsp); /* for API */ \
PERL_UNUSED_VAR(gimme); /* for API */ \
- cxstack_ix--; \
+ POPBLOCK(cx); \
+ CX_POP(cx); \
POPSTACK; \
CATCH_SET(multicall_oldcatch); \
SPAGAIN; \
PADLIST * const padlist = CvPADLIST(cv); \
cx = &cxstack[cxstack_ix]; \
assert(CxMULTICALL(cx)); \
- CvDEPTH(multicall_cv) = cx->blk_sub.olddepth; \
- SvREFCNT_dec_NN(multicall_cv); \
+ POPSUB_COMMON(cx); \
cx->cx_type = (CXt_SUB|CXp_MULTICALL|flags); \
- { \
- /* save a few things that we don't want PUSHSUB to zap */ \
- PAD * const prevcomppad = cx->blk_sub.prevcomppad; \
- PUSHSUB(cx); \
- /* undo the stuff that PUSHSUB zapped */ \
- cx->blk_sub.prevcomppad = prevcomppad ; \
- } \
+ PUSHSUB(cx); \
if (!(flags & CXp_SUB_RE_FAKE)) \
CvDEPTH(cv)++; \
if (CvDEPTH(cv) >= 2) { \