#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)); \
/* (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;
#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); \
- cx->blk_loop.iterdata = (idata);
+# define CX_ITERDATA_SET(cx,idata,o) \
+ if ((cx->blk_loop.targoffset = (o))) \
+ CX_CURPAD_SAVE(cx->blk_loop); \
+ else \
+ cx->blk_loop.oldcomppad = (idata);
#else
# define CxITERVAR(c) ((c)->blk_loop.itervar)
-# define CX_ITERDATA_SET(cx,ivar) \
+# define CX_ITERDATA_SET(cx,ivar,o) \
cx->blk_loop.itervar = (SV**)(ivar);
#endif
#define CxLABEL(c) (0 + (c)->blk_oldcop->cop_label)
PUSHLOOP_OP_NEXT; \
cx->blk_loop.state_u.ary.ary = NULL; \
cx->blk_loop.state_u.ary.ix = 0; \
- CX_ITERDATA_SET(cx,NULL);
+ 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.state_u.ary.ary = NULL; \
cx->blk_loop.state_u.ary.ix = 0; \
- CX_ITERDATA_SET(cx,dat);
+ CX_ITERDATA_SET(cx, dat, offset);
#define POPLOOP(cx) \
if (CxTYPE(cx) == CXt_LOOP_LAZYSV) { \
};
#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
-#define CXt_LOOP_LAZYSV 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
/* 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)) \