X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=cop.h;h=39a6b01484bb307e9b87dc91499b86dfbe72a48e;hb=20caf59dc5a2137cdf1de6dae458da063417a8d2;hp=36f1a63fc7d50725aad0fe1963829b24be801405;hpb=493b0a3c46c2cc9f06bf88c450ded6aa981c4fd3;p=p5sagit%2Fp5-mst-13.2.git diff --git a/cop.h b/cop.h index 36f1a63..39a6b01 100644 --- a/cop.h +++ b/cop.h @@ -1,7 +1,7 @@ /* cop.h * - * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + * 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -139,7 +139,7 @@ struct cop { /* On LP64 putting this here takes advantage of the fact that BASEOP isn't an exact multiple of 8 bytes to save structure padding. */ line_t cop_line; /* line # of this command */ - char * cop_label; /* label for this construct */ + /* label for this construct is now stored in cop_hints_hash */ #ifdef USE_ITHREADS char * cop_stashpv; /* package line was compiled in */ char * cop_file; /* file name the following line # is from */ @@ -191,18 +191,12 @@ struct cop { ? gv_stashpv(CopSTASHPV(c),GV_ADD) : NULL) # define CopSTASH_set(c,hv) CopSTASHPV_set(c, (hv) ? HvNAME_get(hv) : NULL) # define CopSTASH_eq(c,hv) ((hv) && stashpv_hvname_match(c,hv)) -# define CopLABEL(c) ((c)->cop_label) -# define CopLABEL_set(c,pv) (CopLABEL(c) = (pv)) # ifdef NETWARE # define CopSTASH_free(c) SAVECOPSTASH_FREE(c) # define CopFILE_free(c) SAVECOPFILE_FREE(c) -# define CopLABEL_free(c) SAVECOPLABEL_FREE(c) -# define CopLABEL_alloc(pv) ((pv)?savepv(pv):NULL) # else # define CopSTASH_free(c) PerlMemShared_free(CopSTASHPV(c)) # define CopFILE_free(c) (PerlMemShared_free(CopFILE(c)),(CopFILE(c) = NULL)) -# define CopLABEL_free(c) (PerlMemShared_free(CopLABEL(c)),(CopLABEL(c) = NULL)) -# define CopLABEL_alloc(pv) ((pv)?savesharedpv(pv):NULL) # endif #else # define CopFILEGV(c) ((c)->cop_filegv) @@ -219,19 +213,17 @@ struct cop { # define CopFILE(c) (CopFILEGV(c) && GvSV(CopFILEGV(c)) \ ? SvPVX(GvSV(CopFILEGV(c))) : NULL) # define CopSTASH(c) ((c)->cop_stash) -# define CopLABEL(c) ((c)->cop_label) # define CopSTASH_set(c,hv) ((c)->cop_stash = (hv)) # define CopSTASHPV(c) (CopSTASH(c) ? HvNAME_get(CopSTASH(c)) : NULL) /* cop_stash is not refcounted */ # define CopSTASHPV_set(c,pv) CopSTASH_set((c), gv_stashpv(pv,GV_ADD)) # define CopSTASH_eq(c,hv) (CopSTASH(c) == (hv)) -# define CopLABEL_alloc(pv) ((pv)?savepv(pv):NULL) -# define CopLABEL_set(c,pv) (CopLABEL(c) = (pv)) # define CopSTASH_free(c) # define CopFILE_free(c) (SvREFCNT_dec(CopFILEGV(c)),(CopFILEGV(c) = NULL)) -# define CopLABEL_free(c) (Safefree(CopLABEL(c)),(CopLABEL(c) = NULL)) #endif /* USE_ITHREADS */ +#define CopLABEL(c) Perl_fetch_cop_label(aTHX_ (c)->cop_hints_hash, NULL, NULL) +#define CopLABEL_alloc(pv) ((pv)?savepv(pv):NULL) #define CopSTASH_ne(c,hv) (!CopSTASH_eq(c,hv)) #define CopLINE(c) ((c)->cop_line) @@ -306,8 +298,8 @@ struct block_format { #define PUSHSUB_BASE(cx) \ ENTRY_PROBE(GvENAME(CvGV(cv)), \ - CopFILE((COP*)CvSTART(cv)), \ - CopLINE((COP*)CvSTART(cv))); \ + CopFILE((const COP *)CvSTART(cv)), \ + CopLINE((const COP *)CvSTART(cv))); \ \ cx->blk_sub.cv = cv; \ cx->blk_sub.olddepth = CvDEPTH(cv); \ @@ -355,9 +347,9 @@ struct block_format { #define POPSUB(cx,sv) \ STMT_START { \ - RETURN_PROBE(GvENAME(CvGV((CV*)cx->blk_sub.cv)), \ - CopFILE((COP*)CvSTART((CV*)cx->blk_sub.cv)), \ - CopLINE((COP*)CvSTART((CV*)cx->blk_sub.cv))); \ + RETURN_PROBE(GvENAME(CvGV((const CV*)cx->blk_sub.cv)), \ + CopFILE((COP*)CvSTART((const CV*)cx->blk_sub.cv)), \ + CopLINE((COP*)CvSTART((const CV*)cx->blk_sub.cv))); \ \ if (CxHASARGS(cx)) { \ POP_SAVEARRAY(); \ @@ -368,14 +360,14 @@ struct block_format { cx->blk_sub.argarray = newAV(); \ av_extend(cx->blk_sub.argarray, fill); \ AvREIFY_only(cx->blk_sub.argarray); \ - CX_CURPAD_SV(cx->blk_sub, 0) = (SV*)cx->blk_sub.argarray; \ + CX_CURPAD_SV(cx->blk_sub, 0) = MUTABLE_SV(cx->blk_sub.argarray); \ } \ else { \ CLEAR_ARGARRAY(cx->blk_sub.argarray); \ } \ } \ - sv = (SV*)cx->blk_sub.cv; \ - if (sv && (CvDEPTH((CV*)sv) = cx->blk_sub.olddepth)) \ + sv = MUTABLE_SV(cx->blk_sub.cv); \ + if (sv && (CvDEPTH((const CV*)sv) = cx->blk_sub.olddepth)) \ sv = NULL; \ } STMT_END @@ -407,7 +399,7 @@ struct block_eval { #define CxOLD_IN_EVAL(cx) (((cx)->blk_u16) & 0x7F) #define CxOLD_OP_TYPE(cx) (((cx)->blk_u16) >> 7) -#define PUSHEVAL(cx,n,fgv) \ +#define PUSHEVAL(cx,n) \ STMT_START { \ assert(!(PL_in_eval & ~0x7F)); \ assert(!(PL_op->op_type & ~0x1FF)); \ @@ -436,56 +428,47 @@ struct block_loop { /* (except for non_ithreads we need to modify next_op in pp_ctl.c, hence why next_op is conditionally defined below.) */ #ifdef USE_ITHREADS - void * iterdata; - PAD *oldcomppad; + PAD *oldcomppad; /* Also used for the GV, if targoffset is 0 */ + /* This is also accesible via cx->blk_loop.my_op->op_targ */ + PADOFFSET targoffset; #else OP * next_op; SV ** itervar; #endif - SV * itersave; - union { - /* (from inspection of source code) for a .. range of strings this is the - current string. */ - SV * iterlval; - /* (from inspection of source code) for a .. range of numbers this is the - maximum value. */ - IV itermax; - } lval_max_u; union { - /* (from inspection of source code) for a foreach loop this is the array - being iterated over. For a .. range of numbers it's the current value. - A check is often made on the SvTYPE of iterary to determine whether - we are iterating over an array or a range. (numbers or strings) */ - AV * iterary; - /* Minimum stack index when reverse iterating as CXt_LOOP_STACK */ - IV itermin; - } ary_min_u; - IV iterix; + struct { /* valid if type is LOOP_FOR or LOOP_PLAIN (but {NULL,0})*/ + AV * ary; /* use the stack if this is NULL */ + IV ix; + } ary; + struct { /* valid if type is LOOP_LAZYIV */ + IV cur; + IV end; + } lazyiv; + struct { /* valid if type if LOOP_LAZYSV */ + SV * cur; + SV * end; /* maxiumum value (or minimum in reverse) */ + } lazysv; + } state_u; }; #ifdef USE_ITHREADS # define CxITERVAR(c) \ - ((c)->blk_loop.iterdata \ - ? (CxPADLOOP(cx) \ - ? &CX_CURPAD_SV( (c)->blk_loop, \ - INT2PTR(PADOFFSET, (c)->blk_loop.iterdata)) \ - : &GvSV((GV*)(c)->blk_loop.iterdata)) \ + ((c)->blk_loop.oldcomppad \ + ? (CxPADLOOP(c) \ + ? &CX_CURPAD_SV( (c)->blk_loop, (c)->blk_loop.targoffset ) \ + : &GvSV((GV*)(c)->blk_loop.oldcomppad)) \ : (SV**)NULL) -# define CX_ITERDATA_SET(cx,idata) \ - CX_CURPAD_SAVE(cx->blk_loop); \ - if ((cx->blk_loop.iterdata = (idata))) \ - cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx)); \ +# define CX_ITERDATA_SET(cx,idata,o) \ + if ((cx->blk_loop.targoffset = (o))) \ + CX_CURPAD_SAVE(cx->blk_loop); \ else \ - cx->blk_loop.itersave = NULL; + cx->blk_loop.oldcomppad = (idata); #else # define CxITERVAR(c) ((c)->blk_loop.itervar) -# define CX_ITERDATA_SET(cx,ivar) \ - if ((cx->blk_loop.itervar = (SV**)(ivar))) \ - cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx)); \ - else \ - cx->blk_loop.itersave = NULL; +# define CX_ITERDATA_SET(cx,ivar,o) \ + cx->blk_loop.itervar = (SV**)(ivar); #endif -#define CxLABEL(c) (0 + (c)->blk_oldcop->cop_label) +#define CxLABEL(c) (0 + CopLABEL((c)->blk_oldcop)) #define CxHASARGS(c) (((c)->cx_type & CXp_HASARGS) == CXp_HASARGS) #define CxLVAL(c) (0 + (c)->blk_u16) @@ -501,34 +484,25 @@ struct block_loop { cx->blk_loop.resetsp = s - PL_stack_base; \ cx->blk_loop.my_op = cLOOP; \ PUSHLOOP_OP_NEXT; \ - cx->blk_loop.lval_max_u.iterlval = NULL; \ - cx->blk_loop.ary_min_u.iterary = NULL; \ - CX_ITERDATA_SET(cx,NULL); + cx->blk_loop.state_u.ary.ary = NULL; \ + cx->blk_loop.state_u.ary.ix = 0; \ + CX_ITERDATA_SET(cx, NULL, 0); -#define PUSHLOOP_FOR(cx, dat, s) \ +#define PUSHLOOP_FOR(cx, dat, s, offset) \ cx->blk_loop.resetsp = s - PL_stack_base; \ cx->blk_loop.my_op = cLOOP; \ PUSHLOOP_OP_NEXT; \ - cx->blk_loop.lval_max_u.iterlval = NULL; \ - cx->blk_loop.ary_min_u.iterary = NULL; \ - cx->blk_loop.iterix = -1; \ - CX_ITERDATA_SET(cx,dat); + cx->blk_loop.state_u.ary.ary = NULL; \ + cx->blk_loop.state_u.ary.ix = 0; \ + CX_ITERDATA_SET(cx, dat, offset); #define POPLOOP(cx) \ - if (CxTYPE(cx) != CXt_LOOP_LAZYIV) \ - SvREFCNT_dec(cx->blk_loop.lval_max_u.iterlval); \ - if (CxITERVAR(cx)) { \ - if (SvPADMY(cx->blk_loop.itersave)) { \ - SV ** const s_v_p = CxITERVAR(cx); \ - sv_2mortal(*s_v_p); \ - *s_v_p = cx->blk_loop.itersave; \ - } \ - else { \ - SvREFCNT_dec(cx->blk_loop.itersave); \ - } \ + if (CxTYPE(cx) == CXt_LOOP_LAZYSV) { \ + SvREFCNT_dec(cx->blk_loop.state_u.lazysv.cur); \ + SvREFCNT_dec(cx->blk_loop.state_u.lazysv.end); \ } \ - if ((CxTYPE(cx) != CXt_LOOP_STACK) && cx->blk_loop.ary_min_u.iterary) \ - SvREFCNT_dec(cx->blk_loop.ary_min_u.iterary); + if (CxTYPE(cx) == CXt_LOOP_FOR) \ + SvREFCNT_dec(cx->blk_loop.state_u.ary.ary); /* given/when context */ struct block_givwhen { @@ -636,7 +610,8 @@ struct subst { #define sb_rxres cx_u.cx_subst.sbu_rxres #define sb_rx cx_u.cx_subst.sbu_rx -#define PUSHSUBST(cx) CXINC, cx = &cxstack[cxstack_ix], \ +#ifdef PERL_CORE +# define PUSHSUBST(cx) CXINC, cx = &cxstack[cxstack_ix], \ cx->sb_iters = iters, \ cx->sb_maxiters = maxiters, \ cx->sb_rflags = r_flags, \ @@ -654,11 +629,12 @@ struct subst { rxres_save(&cx->sb_rxres, rx); \ (void)ReREFCNT_inc(rx) -#define CxONCE(cx) ((cx)->cx_type & CXp_ONCE) - -#define POPSUBST(cx) cx = &cxstack[cxstack_ix--]; \ +# define POPSUBST(cx) cx = &cxstack[cxstack_ix--]; \ rxres_free(&cx->sb_rxres); \ ReREFCNT_dec(cx->sb_rx) +#endif + +#define CxONCE(cx) ((cx)->cx_type & CXp_ONCE) struct context { union { @@ -668,21 +644,27 @@ struct context { }; #define cx_type cx_u.cx_subst.sbu_type +/* 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_SUB 1 -#define CXt_EVAL 2 -#define CXt_WHEN 3 -#define CXt_SUBST 4 -#define CXt_BLOCK 5 -#define CXt_FORMAT 6 -#define CXt_GIVEN 7 +#define CXt_WHEN 1 +#define CXt_BLOCK 2 +/* When micro-optimising :-) keep GIVEN next to the LOOPs, as these 5 share a + jump table in pp_ctl.c + The first 4 don't have a 'case' in at least one switch statement in pp_ctl.c +*/ +#define CXt_GIVEN 3 /* This is first so that CXt_LOOP_FOR|CXt_LOOP_LAZYIV is CXt_LOOP_LAZYIV */ -#define CXt_LOOP_FOR 8 -#define CXt_LOOP_PLAIN 9 -/* Foreach on a temporary list on the stack */ -#define CXt_LOOP_STACK 10 -#define CXt_LOOP_LAZYIV 11 +#define CXt_LOOP_FOR 4 +#define CXt_LOOP_PLAIN 5 +#define CXt_LOOP_LAZYSV 6 +#define CXt_LOOP_LAZYIV 7 +#define CXt_SUB 8 +#define CXt_FORMAT 9 +#define CXt_EVAL 10 +#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 @@ -701,15 +683,14 @@ struct context { /* private flags for CXt_LOOP */ #define CXp_FOR_DEF 0x10 /* foreach using $_ */ #ifdef USE_ITHREADS -# define CXp_PADVAR 0x20 /* itervar lives on pad, iterdata has pad - offset; if not set, iterdata holds GV* */ -# define CxPADLOOP(c) (CxTYPE_is_LOOP(c) && ((c)->cx_type & (CXp_PADVAR))) +# define CxPADLOOP(c) ((c)->blk_loop.targoffset) #endif + /* private flags for CXt_SUBST */ #define CXp_ONCE 0x10 /* What was sbu_once in struct subst */ #define CxTYPE(c) ((c)->cx_type & CXTYPEMASK) -#define CxTYPE_is_LOOP(c) (((c)->cx_type & 0xC) == 0x8) +#define CxTYPE_is_LOOP(c) (((c)->cx_type & 0xC) == 0x4) #define CxMULTICALL(c) (((c)->cx_type & CXp_MULTICALL) \ == CXp_MULTICALL) #define CxREALEVAL(c) (((c)->cx_type & (CXTYPEMASK|CXp_REAL)) \