X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/c5369ccc48261c8bf4ac3023a24c6090f52a03c6..8e7e33ef85748a7a693c09b1547c39c96575f347:/cop.h diff --git a/cop.h b/cop.h index 0798752..e1f429d 100644 --- a/cop.h +++ b/cop.h @@ -570,6 +570,10 @@ 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) + /* 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 +591,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 +624,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 +646,8 @@ struct block_format { AvFILLp(ary) = -1; \ } STMT_END -#define POPSUB(cx,sv) \ +#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) \ @@ -673,26 +672,18 @@ struct block_format { } \ } \ } \ - 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); \ + CvDEPTH((const CV*)cx->blk_sub.cv) = cx->blk_sub.olddepth; \ + SvREFCNT_dec_NN(cx->blk_sub.cv); \ } 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 +716,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; \ @@ -795,9 +784,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 +800,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 +819,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 +828,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 +836,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 +863,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 +894,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 +906,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 +938,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 +952,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 +964,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, \ @@ -1014,6 +991,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 +1002,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 +1021,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 +1044,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 +1260,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)++; \ @@ -1311,12 +1283,16 @@ See L. STMT_START { \ cx = &cxstack[cxstack_ix]; \ CvDEPTH(multicall_cv) = cx->blk_sub.olddepth; \ - LEAVESUB(multicall_cv); \ - POPBLOCK(cx,PL_curpm); \ + CX_LEAVE_SCOPE(cx); \ /* 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; \ + SvREFCNT_dec_NN(multicall_cv); \ + /* these two set for backcompat by callers */ \ + newsp = PL_stack_base + cx->blk_oldsp; \ + gimme = cx->blk_gimme; \ + POPBLOCK(cx); \ + cxstack_ix--; \ POPSTACK; \ CATCH_SET(multicall_oldcatch); \ SPAGAIN; \ @@ -1331,20 +1307,16 @@ See L. CV * const cv = _nOnclAshIngNamE_; \ PADLIST * const padlist = CvPADLIST(cv); \ cx = &cxstack[cxstack_ix]; \ - assert(cx->cx_type & CXp_MULTICALL); \ + assert(CxMULTICALL(cx)); \ CvDEPTH(multicall_cv) = cx->blk_sub.olddepth; \ - LEAVESUB(multicall_cv); \ + SvREFCNT_dec_NN(multicall_cv); \ 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; \ } \ if (!(flags & CXp_SUB_RE_FAKE)) \ CvDEPTH(cv)++; \