This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Eliminate cx->blk_loop.resetsp
authorDavid Mitchell <davem@iabyn.com>
Sat, 17 Oct 2015 11:56:15 +0000 (12:56 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 3 Feb 2016 09:18:30 +0000 (09:18 +0000)
Of all the loop types, only CXt_LOOP_LIST, i.e. for (1,2,3) {},
needs to keep anything on the stack, i.e. for all the others,
cx->blk_loop.resetsp can always equal cx->blk_oldsp.
For CXt_LOOP_LIST, the same value as resetsp is stored as
blk_loop.state_u.stack.basesp.

So we can eliminate the resetsp field. This is good as the loop substruct
is the largest (ITHREADS) or joint largest with eval (non-threaded).

Also, we now don't have to store that value for non-CXt_LOOP_LIST loops.
The downside is we now have to choose between basesp and oldsp in
pp_leaveloop and pp_last, based on CX type.

cop.h
pp_ctl.c
scope.c

diff --git a/cop.h b/cop.h
index 05458c5..252eeb9 100644 (file)
--- a/cop.h
+++ b/cop.h
@@ -762,7 +762,6 @@ struct block_eval {
 
 /* loop context */
 struct block_loop {
-    I32                resetsp;
     LOOP *     my_op;  /* My op, that contains redo, next and last ops.  */
     union {    /* different ways of locating the iteration variable */
        SV      **svp; /* for lexicals: address of pad slot */
@@ -808,8 +807,7 @@ struct block_loop {
 #define CxPOPSUB_DONE 0x100
 
 
-#define PUSHLOOP_PLAIN(cx, s)                                          \
-       cx->blk_loop.resetsp = s - PL_stack_base;                       \
+#define PUSHLOOP_PLAIN(cx)                                             \
        cx->blk_loop.my_op = cLOOP;                                     \
        cx->blk_loop.state_u.ary.ary = NULL;                            \
        cx->blk_loop.state_u.ary.ix = 0;                                \
@@ -823,8 +821,7 @@ struct block_loop {
 #  define PUSHLOOP_FOR_setpad(c) NOOP
 #endif
 
-#define PUSHLOOP_FOR(cx, ivar, isave, s)                               \
-       cx->blk_loop.resetsp = s - PL_stack_base;                       \
+#define PUSHLOOP_FOR(cx, ivar, isave)                                  \
        cx->blk_loop.my_op = cLOOP;                                     \
        cx->blk_loop.itervar_u.svp = (SV**)(ivar);                      \
         cx->cx_old_savestack_ix = PL_savestack_ix;                      \
@@ -884,7 +881,7 @@ struct block {
     U8         blku_type;      /* what kind of context this is */
     U8         blku_gimme;     /* is this block running in list context? */
     U16                blku_u16;       /* used by block_sub and block_eval (so far) */
-    I32                blku_oldsp;     /* stack pointer to copy stuff down to */
+    I32                blku_oldsp;     /* current sp floor: where nextstate pops to */
     COP *      blku_oldcop;    /* old curcop pointer */
     I32                blku_oldmarksp; /* mark stack index */
     I32                blku_oldscopesp;        /* scope stack index */
index 16891ab..b73c95c 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2186,8 +2186,8 @@ PP(pp_enteriter)
     if (PL_op->op_private & OPpITER_DEF)
        cxflags |= CXp_FOR_DEF;
 
-    PUSHBLOCK(cx, cxflags, SP);
-    PUSHLOOP_FOR(cx, itervarp, itersave, MARK);
+    PUSHBLOCK(cx, cxflags, MARK);
+    PUSHLOOP_FOR(cx, itervarp, itersave);
     if (PL_op->op_flags & OPf_STACKED) {
        SV *maybe_ary = POPs;
        if (SvTYPE(maybe_ary) != SVt_PVAV) {
@@ -2204,10 +2204,6 @@ PP(pp_enteriter)
                    DIE(aTHX_ "Range iterator outside integer range");
                cx->blk_loop.state_u.lazyiv.cur = SvIV_nomg(sv);
                cx->blk_loop.state_u.lazyiv.end = SvIV_nomg(right);
-#ifdef DEBUGGING
-               /* for correct -Dstv display */
-               cx->blk_oldsp = sp - PL_stack_base;
-#endif
            }
            else {
                cx->cx_type |= CXt_LOOP_LAZYSV;
@@ -2239,6 +2235,7 @@ PP(pp_enteriter)
     }
     else { /* iterating over items on the stack */
         cx->cx_type |= CXt_LOOP_LIST;
+        cx->blk_oldsp = SP - PL_stack_base;
        cx->blk_loop.state_u.stack.basesp = MARK - PL_stack_base;
         cx->blk_loop.state_u.stack.ix =
             (PL_op->op_private & OPpITER_REVERSED)
@@ -2259,7 +2256,7 @@ PP(pp_enterloop)
     const I32 gimme = GIMME_V;
 
     PUSHBLOCK(cx, CXt_LOOP_PLAIN, SP);
-    PUSHLOOP_PLAIN(cx, SP);
+    PUSHLOOP_PLAIN(cx);
 
     RETURN;
 }
@@ -2274,7 +2271,9 @@ PP(pp_leaveloop)
     cx = &cxstack[cxstack_ix];
     assert(CxTYPE_is_LOOP(cx));
     mark = PL_stack_base + cx->blk_oldsp;
-    newsp = PL_stack_base + cx->blk_loop.resetsp;
+    newsp = CxTYPE(cx) == CXt_LOOP_LIST
+                ? PL_stack_base + cx->blk_loop.state_u.stack.basesp
+                : mark;
     gimme = cx->blk_gimme;
 
     if (gimme == G_VOID)
@@ -2579,7 +2578,11 @@ PP(pp_last)
     cx = &cxstack[cxstack_ix];
 
     assert(CxTYPE_is_LOOP(cx));
-    PL_stack_sp = PL_stack_base + cx->blk_loop.resetsp;
+    PL_stack_sp = PL_stack_base
+                + (CxTYPE(cx) == CXt_LOOP_LIST
+                    ?  cx->blk_loop.state_u.stack.basesp
+                    : cx->blk_oldsp
+                );
 
     TAINT_NOT;
 
diff --git a/scope.c b/scope.c
index 08456d4..0188dd1 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -1372,8 +1372,6 @@ Perl_cx_dump(pTHX_ PERL_CONTEXT *cx)
     case CXt_LOOP_LIST:
     case CXt_LOOP_ARY:
        PerlIO_printf(Perl_debug_log, "BLK_LOOP.LABEL = %s\n", CxLABEL(cx));
-       PerlIO_printf(Perl_debug_log, "BLK_LOOP.RESETSP = %ld\n",
-               (long)cx->blk_loop.resetsp);
        PerlIO_printf(Perl_debug_log, "BLK_LOOP.MY_OP = 0x%"UVxf"\n",
                PTR2UV(cx->blk_loop.my_op));
        /* XXX: not accurate for LAZYSV/IV */