X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/c5369ccc48261c8bf4ac3023a24c6090f52a03c6..42831ce4bbb728b1e5cfa313cf99a85712eb080f:/cop.h diff --git a/cop.h b/cop.h index 0798752..525f546 100644 --- a/cop.h +++ b/cop.h @@ -570,6 +570,23 @@ struct block_format { GV * dfoutgv; }; +/* free all savestack items back to the watermark of the specified context */ + +#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 */ @@ -587,9 +604,7 @@ struct block_format { cx->blk_sub.prevcomppad = PL_comppad; \ cx->cx_type |= (hasargs) ? CXp_HASARGS : 0; \ cx->blk_sub.retop = NULL; \ - SvREFCNT_inc_simple_void_NN(cv); \ - cx->cx_u.cx_blk.blku_old_tmpsfloor = PL_tmps_floor; \ - PL_tmps_floor = PL_tmps_ix; + SvREFCNT_inc_simple_void_NN(cv); #define PUSHSUB_GET_LVALUE_MASK(func) \ /* If the context is indeterminate, then only the lvalue */ \ @@ -622,9 +637,7 @@ struct block_format { cx->blk_format.dfoutgv = PL_defoutgv; \ cx->blk_format.prevcomppad = PL_comppad; \ cx->blk_u16 = 0; \ - cx->cx_u.cx_blk.blku_old_savestack_ix = PL_savestack_ix; \ - cx->cx_u.cx_blk.blku_old_tmpsfloor = PL_tmps_floor; \ - PL_tmps_floor = PL_tmps_ix; \ + cx->cx_old_savestack_ix = PL_savestack_ix; \ SvREFCNT_inc_simple_void_NN(cv); \ CvDEPTH(cv)++; \ SvREFCNT_inc_void(cx->blk_format.dfoutgv) @@ -646,9 +659,35 @@ struct block_format { AvFILLp(ary) = -1; \ } STMT_END -#define POPSUB(cx,sv) \ + +/* subsets of POPSUB */ + +#define POPSUB_COMMON(cx) \ + PL_comppad = cx->blk_sub.prevcomppad; \ + PL_curpad = LIKELY(PL_comppad) ? AvARRAY(PL_comppad) : NULL; \ + 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 { \ - LEAVE_SCOPE(cx->cx_u.cx_blk.blku_old_savestack_ix); \ if (!(cx->blk_u16 & CxPOPSUB_DONE)) { \ cx->blk_u16 |= CxPOPSUB_DONE; \ RETURN_PROBE(CvNAMED(cx->blk_sub.cv) \ @@ -659,40 +698,18 @@ struct block_format { 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); \ } \ } \ - PL_tmps_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; \ - PL_comppad = cx->blk_sub.prevcomppad; \ - PL_curpad = LIKELY(PL_comppad) ? AvARRAY(PL_comppad) : NULL; \ - sv = MUTABLE_SV(cx->blk_sub.cv); \ - CvDEPTH((const CV*)sv) = cx->blk_sub.olddepth; \ - } STMT_END - -#define LEAVESUB(sv) \ - STMT_START { \ - SvREFCNT_dec(sv); \ + POPSUB_COMMON(cx); \ } STMT_END #define POPFORMAT(cx) \ STMT_START { \ - LEAVE_SCOPE(cx->cx_u.cx_blk.blku_old_savestack_ix); \ if (!(cx->blk_u16 & CxPOPSUB_DONE)) { \ CV * const cv = cx->blk_format.cv; \ GV * const dfuot = cx->blk_format.dfoutgv; \ cx->blk_u16 |= CxPOPSUB_DONE; \ - PL_tmps_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; \ setdefout(dfuot); \ PL_comppad = cx->blk_format.prevcomppad; \ PL_curpad = LIKELY(PL_comppad) ? AvARRAY(PL_comppad) : NULL; \ @@ -725,8 +742,6 @@ struct block_eval { assert(!(PL_in_eval & ~0x7F)); \ assert(!(PL_op->op_type & ~0x1FF)); \ cx->blk_u16 = (PL_in_eval & 0x7F) | ((U16)PL_op->op_type << 7); \ - cx->cx_u.cx_blk.blku_old_tmpsfloor = PL_tmps_floor; \ - PL_tmps_floor = PL_tmps_ix; \ cx->blk_eval.old_namesv = (n ? newSVpv(n,0) : NULL); \ cx->blk_eval.old_eval_root = PL_eval_root; \ cx->blk_eval.cur_text = PL_parser ? PL_parser->linestr : NULL; \ @@ -738,7 +753,6 @@ struct block_eval { #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); \ @@ -795,9 +809,7 @@ struct block_loop { cx->blk_loop.my_op = cLOOP; \ cx->blk_loop.state_u.ary.ary = NULL; \ cx->blk_loop.state_u.ary.ix = 0; \ - cx->cx_u.cx_blk.blku_old_savestack_ix = PL_savestack_ix; \ - cx->cx_u.cx_blk.blku_old_tmpsfloor = PL_tmps_floor; \ - PL_tmps_floor = PL_tmps_ix; \ + cx->cx_old_savestack_ix = PL_savestack_ix; \ cx->blk_loop.itervar_u.svp = NULL; \ cx->blk_loop.itersave = NULL; @@ -813,14 +825,11 @@ struct block_loop { cx->blk_loop.state_u.ary.ary = NULL; \ cx->blk_loop.state_u.ary.ix = 0; \ cx->blk_loop.itervar_u.svp = (SV**)(ivar); \ - cx->cx_u.cx_blk.blku_old_savestack_ix = PL_savestack_ix; \ - cx->cx_u.cx_blk.blku_old_tmpsfloor = PL_tmps_floor; \ - PL_tmps_floor = PL_tmps_ix; \ + cx->cx_old_savestack_ix = PL_savestack_ix; \ cx->blk_loop.itersave = isave; \ PUSHLOOP_FOR_setpad(cx); #define POPLOOP(cx) \ - LEAVE_SCOPE(cx->cx_u.cx_blk.blku_old_savestack_ix); \ if (CxTYPE(cx) == CXt_LOOP_LAZYSV) { \ SvREFCNT_dec_NN(cx->blk_loop.state_u.lazysv.cur); \ SvREFCNT_dec_NN(cx->blk_loop.state_u.lazysv.end); \ @@ -835,8 +844,7 @@ struct block_loop { cursv = *svp; \ *svp = cx->blk_loop.itersave; \ SvREFCNT_dec(cursv); \ - } \ - PL_tmps_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; + } /* given/when context */ struct block_givwhen { @@ -845,9 +853,7 @@ struct block_givwhen { }; #define PUSHWHEN(cx) \ - cx->cx_u.cx_blk.blku_old_savestack_ix = PL_savestack_ix; \ - cx->cx_u.cx_blk.blku_old_tmpsfloor = PL_tmps_floor; \ - PL_tmps_floor = PL_tmps_ix; \ + cx->cx_old_savestack_ix = PL_savestack_ix; \ cx->blk_givwhen.leave_op = cLOGOP->op_other; #define PUSHGIVEN(cx, orig_var) \ @@ -855,26 +861,20 @@ struct block_givwhen { cx->blk_givwhen.defsv_save = orig_var; #define POPWHEN(cx) \ - LEAVE_SCOPE(cx->cx_u.cx_blk.blku_old_savestack_ix); \ - PL_tmps_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; + NOOP; #define POPGIVEN(cx) \ - LEAVE_SCOPE(cx->cx_u.cx_blk.blku_old_savestack_ix); \ SvREFCNT_dec(GvSV(PL_defgv)); \ - GvSV(PL_defgv) = cx->blk_givwhen.defsv_save; \ - PL_tmps_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; + GvSV(PL_defgv) = cx->blk_givwhen.defsv_save; /* basic block, i.e. pp_enter/leave */ -#define PUSHBASICBLK(cx) \ - cx->cx_u.cx_blk.blku_old_savestack_ix = PL_savestack_ix; \ - cx->cx_u.cx_blk.blku_old_tmpsfloor = PL_tmps_floor; \ - PL_tmps_floor = PL_tmps_ix; +#define PUSHBASICBLK(cx) \ + cx->cx_old_savestack_ix = PL_savestack_ix; -#define POPBASICBLK(cx) \ - LEAVE_SCOPE(cx->cx_u.cx_blk.blku_old_savestack_ix); \ - PL_tmps_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; +#define POPBASICBLK(cx) \ + NOOP; /* context common to subroutines, evals and loops */ @@ -888,7 +888,6 @@ struct block { I32 blku_oldscopesp; /* scope stack index */ PMOP * blku_oldpm; /* values of pattern match vars */ SSize_t blku_old_tmpsfloor; /* saved PL_tmps_floor */ - I32 blku_old_savestack_ix; /* saved PL_savestack_ix */ union { struct block_sub blku_sub; @@ -920,7 +919,7 @@ struct block { (long)PL_scopestack_ix, \ (long)(cxstack[cxstack_ix].blk_oldscopesp), \ (long)PL_savestack_ix, \ - (long)(cxstack[cxstack_ix].cx_u.cx_blk.blku_old_savestack_ix),\ + (long)(cxstack[cxstack_ix].cx_old_savestack_ix), \ __FILE__, __LINE__)); /* Enter a block. */ @@ -932,18 +931,23 @@ struct block { cx->blk_oldscopesp = PL_scopestack_ix, \ cx->blk_oldpm = PL_curpm, \ cx->blk_gimme = (U8)gimme; \ + cx->cx_u.cx_blk.blku_old_tmpsfloor = PL_tmps_floor; \ + PL_tmps_floor = PL_tmps_ix; \ DEBUG_CX("PUSH"); /* Exit a block (RETURN and LAST). */ -#define POPBLOCK(cx,pm) \ +#define POPBLOCK(cx) \ DEBUG_CX("POP"); \ - cx = &cxstack[cxstack_ix--], \ - newsp = PL_stack_base + cx->blk_oldsp, \ PL_curcop = cx->blk_oldcop, \ PL_markstack_ptr = PL_markstack + cx->blk_oldmarksp, \ PL_scopestack_ix = cx->blk_oldscopesp, \ - pm = cx->blk_oldpm, \ - gimme = cx->blk_gimme; + /* LEAVE_SCOPE() should have made this true. /(?{})/ cheats + * and leaves a CX entry lying around for repeated use, so + * skip for multicall */ \ + assert( (CxTYPE(cx) == CXt_SUB && CxMULTICALL(cx)) \ + || PL_savestack_ix == cx->cx_old_savestack_ix); \ + PL_tmps_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; \ + PL_curpm = cx->blk_oldpm; /* Continue a block elsewhere (NEXT and REDO). */ #define TOPBLOCK(cx) \ @@ -959,7 +963,6 @@ struct subst { U8 sbu_type; /* what kind of context this is */ U8 sbu_rflags; U16 sbu_rxtainted; /* matches struct block */ - I32 sbu_oldsave; SSize_t sbu_iters; SSize_t sbu_maxiters; char * sbu_orig; @@ -974,7 +977,6 @@ struct subst { #define sb_iters cx_u.cx_subst.sbu_iters #define sb_maxiters cx_u.cx_subst.sbu_maxiters #define sb_rflags cx_u.cx_subst.sbu_rflags -#define sb_oldsave cx_u.cx_subst.sbu_oldsave #define sb_rxtainted cx_u.cx_subst.sbu_rxtainted #define sb_orig cx_u.cx_subst.sbu_orig #define sb_dstr cx_u.cx_subst.sbu_dstr @@ -987,10 +989,10 @@ struct subst { #ifdef PERL_CORE # define PUSHSUBST(cx) CXINC, cx = &cxstack[cxstack_ix], \ + cx->cx_old_savestack_ix = oldsave, \ cx->sb_iters = iters, \ cx->sb_maxiters = maxiters, \ cx->sb_rflags = r_flags, \ - cx->sb_oldsave = oldsave, \ cx->sb_rxtainted = rxtainted, \ cx->sb_orig = orig, \ cx->sb_dstr = dstr, \ @@ -1005,7 +1007,7 @@ struct subst { (void)ReREFCNT_inc(rx); \ SvREFCNT_inc_void_NN(targ) -# define POPSUBST(cx) cx = &cxstack[cxstack_ix--]; \ +# define POPSUBST(cx) \ rxres_free(&cx->sb_rxres); \ ReREFCNT_dec(cx->sb_rx); \ SvREFCNT_dec_NN(cx->sb_targ) @@ -1014,6 +1016,7 @@ struct subst { #define CxONCE(cx) ((cx)->cx_type & CXp_ONCE) struct context { + I32 cx_old_savestack_ix; /* saved PL_savestack_ix */ union { struct block cx_blk; struct subst cx_subst; @@ -1024,7 +1027,7 @@ struct context { /* If you re-order these, there is also an array of uppercase names in perl.h and a static array of context names in pp_ctl.c */ #define CXTYPEMASK 0xf -#define CXt_NULL 0 +#define CXt_NULL 0 /* currently only used for sort BLOCK */ #define CXt_WHEN 1 #define CXt_BLOCK 2 /* When micro-optimising :-) keep GIVEN next to the LOOPs, as these 5 share a @@ -1043,14 +1046,9 @@ struct context { #define CXt_SUBST 11 /* SUBST doesn't feature in all switch statements. */ -/* private flags for CXt_SUB and CXt_NULL - However, this is checked in many places which do not check the type, so - this bit needs to be kept clear for most everything else. For reasons I - haven't investigated, it can coexist with CXp_FOR_DEF */ -#define CXp_MULTICALL 0x10 /* part of a multicall (so don't - tear down context on exit). */ - /* private flags for CXt_SUB and CXt_FORMAT */ +#define CXp_MULTICALL 0x10 /* part of a multicall (so don't tear down + context on exit). (not CXt_FORMAT) */ #define CXp_HASARGS 0x20 #define CXp_SUB_RE 0x40 /* code called within regex, i.e. (?{}) */ #define CXp_SUB_RE_FAKE 0x80 /* fake sub CX for (?{}) in current scope */ @@ -1071,8 +1069,7 @@ struct context { #define CxTYPE(c) ((c)->cx_type & CXTYPEMASK) #define CxTYPE_is_LOOP(c) (((c)->cx_type & 0xC) == 0x4) -#define CxMULTICALL(c) (((c)->cx_type & CXp_MULTICALL) \ - == CXp_MULTICALL) +#define CxMULTICALL(c) ((c)->cx_type & CXp_MULTICALL) #define CxREALEVAL(c) (((c)->cx_type & (CXTYPEMASK|CXp_REAL)) \ == (CXt_EVAL|CXp_REAL)) #define CxTRYBLOCK(c) (((c)->cx_type & (CXTYPEMASK|CXp_TRYBLOCK)) \ @@ -1288,7 +1285,7 @@ See L. PUSHSTACKi(PERLSI_MULTICALL); \ PUSHBLOCK(cx, (CXt_SUB|CXp_MULTICALL|flags), PL_stack_sp); \ PUSHSUB(cx); \ - cx->cx_u.cx_blk.blku_old_savestack_ix = PL_savestack_ix; \ + cx->cx_old_savestack_ix = PL_savestack_ix; \ SAVEVPTR(PL_op); \ if (!(flags & CXp_SUB_RE_FAKE)) \ CvDEPTH(cv)++; \ @@ -1298,6 +1295,7 @@ See L. } \ PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); \ multicall_cv = cv; \ + PERL_UNUSED_VAR(multicall_cv); /* for API */ \ multicall_cop = CvSTART(cv); \ } STMT_END @@ -1310,13 +1308,14 @@ See L. #define POP_MULTICALL \ STMT_START { \ cx = &cxstack[cxstack_ix]; \ - CvDEPTH(multicall_cv) = cx->blk_sub.olddepth; \ - LEAVESUB(multicall_cv); \ - POPBLOCK(cx,PL_curpm); \ - /* includes partial unrolled POPSUB(): */ \ - LEAVE_SCOPE(cx->cx_u.cx_blk.blku_old_savestack_ix); \ - PL_comppad = cx->blk_sub.prevcomppad; \ - PL_curpad = LIKELY(PL_comppad) ? AvARRAY(PL_comppad) : NULL; \ + CX_LEAVE_SCOPE(cx); \ + POPSUB_COMMON(cx); \ + newsp = PL_stack_base + cx->blk_oldsp; \ + gimme = cx->blk_gimme; \ + PERL_UNUSED_VAR(newsp); /* for API */ \ + PERL_UNUSED_VAR(gimme); /* for API */ \ + POPBLOCK(cx); \ + CX_POP(cx); \ POPSTACK; \ CATCH_SET(multicall_oldcatch); \ SPAGAIN; \ @@ -1331,21 +1330,10 @@ See L. CV * const cv = _nOnclAshIngNamE_; \ PADLIST * const padlist = CvPADLIST(cv); \ cx = &cxstack[cxstack_ix]; \ - assert(cx->cx_type & CXp_MULTICALL); \ - CvDEPTH(multicall_cv) = cx->blk_sub.olddepth; \ - LEAVESUB(multicall_cv); \ + assert(CxMULTICALL(cx)); \ + 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; \ - SSize_t old_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; \ - SSize_t floor = PL_tmps_floor; \ - PUSHSUB(cx); \ - /* undo the stuff that PUSHSUB zapped */ \ - cx->blk_sub.prevcomppad = prevcomppad ; \ - cx->cx_u.cx_blk.blku_old_tmpsfloor = old_floor; \ - PL_tmps_floor = floor; \ - } \ + PUSHSUB(cx); \ if (!(flags & CXp_SUB_RE_FAKE)) \ CvDEPTH(cv)++; \ if (CvDEPTH(cv) >= 2) { \