As itersave points to the initial CxITERVAR(), and the state of
Nicholas Clark [Sat, 26 Jan 2008 16:03:03 +0000 (16:03 +0000)]
SvPADMY() does not change over the duration of the scope, we can
perform conditional actions at loop push time. For the non-pad case,
a reference to the initial CxITERVAR() is already held on the scope
stack thanks to SAVEGENERICSV(*svp); in pp_enteriter. So there is no
need to save another reference to it in itersave - it's not going away.

p4raw-id: //depot/perl@33076

cop.h

diff --git a/cop.h b/cop.h
index 359abd6..ca9dae2 100644 (file)
--- a/cop.h
+++ b/cop.h
@@ -469,14 +469,15 @@ struct block_loop {
         : (SV**)NULL)
 #  define CX_ITERDATA_SET(cx,idata)                                    \
        CX_CURPAD_SAVE(cx->blk_loop);                                   \
-       if ((cx->blk_loop.iterdata = (idata)))                          \
+       if ((cx->blk_loop.iterdata = (idata)) && SvPADMY(*CxITERVAR(cx))) \
            cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx));       \
        else                                                            \
            cx->blk_loop.itersave = NULL;
 #else
 #  define CxITERVAR(c)         ((c)->blk_loop.itervar)
 #  define CX_ITERDATA_SET(cx,ivar)                                     \
-       if ((cx->blk_loop.itervar = (SV**)(ivar)))                      \
+       if ((cx->blk_loop.itervar = (SV**)(ivar))                       \
+           && SvPADMY(*CxITERVAR(cx)))                                 \
            cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx));       \
        else                                                            \
            cx->blk_loop.itersave = NULL;
@@ -515,14 +516,10 @@ struct block_loop {
            SvREFCNT_dec(cx->blk_loop.state_u.lazysv.end);              \
        }                                                               \
        if (cx->blk_loop.itersave) {                                    \
-            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);                    \
-           }                                                           \
+           SV ** const s_v_p = CxITERVAR(cx);                          \
+           assert(SvPADMY(cx->blk_loop.itersave));                     \
+           sv_2mortal(*s_v_p);                                         \
+           *s_v_p = cx->blk_loop.itersave;                             \
        }                                                               \
        if (CxTYPE(cx) == CXt_LOOP_FOR)                                 \
            SvREFCNT_dec(cx->blk_loop.state_u.ary.ary);