OP * retop; /* op to execute on exit from sub */
/* Above here is the same for sub, format and eval. */
CV * cv;
- U8 lval; /* XXX merge lval and hasargs? */
/* Above here is the same for sub and format. */
AV * savearray;
AV * argarray;
OP * retop; /* op to execute on exit from sub */
/* Above here is the same for sub, format and eval. */
CV * cv;
- U8 lval; /* XXX merge lval and hasargs? */
/* Above here is the same for sub and format. */
GV * gv;
GV * dfoutgv;
#define PUSHSUB(cx) \
PUSHSUB_BASE(cx) \
- cx->blk_sub.lval = PL_op->op_private & \
+ cx->blk_u16 = PL_op->op_private & \
(OPpLVAL_INTRO|OPpENTERSUB_INARGS);
/* variant for use by OP_DBSTATE, where op_private holds hint bits */
#define PUSHSUB_DB(cx) \
PUSHSUB_BASE(cx) \
- cx->blk_sub.lval = 0;
+ cx->blk_u16 = 0;
#define PUSHFORMAT(cx, retop) \
struct block_eval {
OP * retop; /* op to execute on exit from eval */
/* Above here is the same for sub, format and eval. */
- U8 old_in_eval;
- U16 old_op_type;
SV * old_namesv;
OP * old_eval_root;
SV * cur_text;
JMPENV * cur_top_env; /* value of PL_top_env when eval CX created */
};
+/* If we ever need more than 512 op types, change the shift from 7.
+ blku_gimme is actually also only 2 bits, so could be merged with something.
+*/
+
+#define CxOLD_IN_EVAL(cx) (((cx)->blk_u16) & 0x7F)
+#define CxOLD_OP_TYPE(cx) (((cx)->blk_u16) >> 7)
+
#define PUSHEVAL(cx,n,fgv) \
STMT_START { \
- cx->blk_eval.old_in_eval = PL_in_eval; \
- cx->blk_eval.old_op_type = PL_op->op_type; \
+ 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->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; \
#define POPEVAL(cx) \
STMT_START { \
- PL_in_eval = cx->blk_eval.old_in_eval; \
- optype = cx->blk_eval.old_op_type; \
+ 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.old_namesv) \
sv_2mortal(cx->blk_eval.old_namesv); \
#endif
#define CxLABEL(c) (0 + (c)->blk_oldcop->cop_label)
#define CxHASARGS(c) (((c)->cx_type & CXp_HASARGS) == CXp_HASARGS)
-#define CxLVAL(c) (0 + (c)->blk_sub.lval)
+#define CxLVAL(c) (0 + (c)->blk_u16)
#ifdef USE_ITHREADS
# define PUSHLOOP_OP_NEXT /* No need to do anything. */
/* context common to subroutines, evals and loops */
struct block {
- U16 blku_type; /* what kind of context this is */
+ U8 blku_type; /* what kind of context this is */
U8 blku_gimme; /* is this block running in list context? */
- U8 blku_spare; /* Padding to match with struct subst */
+ U16 blku_u16; /* used by block_sub and block_eval (so far) */
I32 blku_oldsp; /* stack pointer to copy stuff down to */
COP * blku_oldcop; /* old curcop pointer */
I32 blku_oldmarksp; /* mark stack index */
#define blk_oldscopesp cx_u.cx_blk.blku_oldscopesp
#define blk_oldpm cx_u.cx_blk.blku_oldpm
#define blk_gimme cx_u.cx_blk.blku_gimme
+#define blk_u16 cx_u.cx_blk.blku_u16
#define blk_sub cx_u.cx_blk.blk_u.blku_sub
#define blk_format cx_u.cx_blk.blk_u.blku_format
#define blk_eval cx_u.cx_blk.blk_u.blku_eval
/* substitution context */
struct subst {
- U16 sbu_type; /* what kind of context this is */
- U8 sbu_once; /* Actually both booleans, but U8 to matches */
- U8 sbu_rxtainted; /* struct block */
+ U8 sbu_type; /* what kind of context this is */
+ U8 sbu_once; /* Actually both booleans, but U8/U16 */
+ U16 sbu_rxtainted; /* matches struct block */
I32 sbu_iters;
I32 sbu_maxiters;
I32 sbu_rflags;
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 0x0000040 /* part of a multicall (so don't
- tear down context on exit). */
+#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_HASARGS 0x00000020
+#define CXp_HASARGS 0x20
/* private flags for CXt_EVAL */
-#define CXp_REAL 0x00000010 /* truly eval'', not a lookalike */
-#define CXp_TRYBLOCK 0x00000020 /* eval{}, not eval'' or similar */
+#define CXp_REAL 0x20 /* truly eval'', not a lookalike */
+#define CXp_TRYBLOCK 0x40 /* eval{}, not eval'' or similar */
/* private flags for CXt_LOOP */
-#define CXp_FOREACH 0x00000020 /* a foreach loop */
-#define CXp_FOR_DEF 0x00000040 /* foreach using $_ */
+#define CXp_FOR_DEF 0x10 /* foreach using $_ */
+#define CXp_FOREACH 0x20 /* a foreach loop */
#ifdef USE_ITHREADS
-# define CXp_PADVAR 0x00000010 /* itervar lives on pad, iterdata
- has pad offset; if not set,
- iterdata holds GV* */
+# define CXp_PADVAR 0x40 /* itervar lives on pad, iterdata has pad
+ offset; if not set, iterdata holds GV* */
# define CxPADLOOP(c) (((c)->cx_type & (CXt_LOOP|CXp_PADVAR)) \
== (CXt_LOOP|CXp_PADVAR))
#endif