This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
only set CXp_FOR_DEF with CXp_FOR_GV
authorDavid Mitchell <davem@iabyn.com>
Mon, 21 Dec 2015 13:32:13 +0000 (13:32 +0000)
committerDavid Mitchell <davem@iabyn.com>
Wed, 3 Feb 2016 09:18:36 +0000 (09:18 +0000)
C<for (...)> is a special-case of C<for $pkg_var (...)>, so CXp_FOR_DEF
should only be set when CXp_FOR_GV also is. So in pp_enteriter(), only
test for (PL_op->op_private & OPpITER_DEF) in the GV branch and assert
that it's otherwise unset. This is slightly more efficient in the non-GV
branches.

Also add some more commentary to the CXp_FOR_* flag definitions.

cop.h
pp_ctl.c

diff --git a/cop.h b/cop.h
index ef86f4f..ceb19ef 100644 (file)
--- a/cop.h
+++ b/cop.h
@@ -1087,10 +1087,14 @@ struct context {
 #define CXp_TRYBLOCK   0x40    /* eval{}, not eval'' or similar */
 
 /* private flags for CXt_LOOP */
 #define CXp_TRYBLOCK   0x40    /* eval{}, not eval'' or similar */
 
 /* private flags for CXt_LOOP */
+
+/* this is only set in conjunction with CXp_FOR_GV */
 #define CXp_FOR_DEF    0x10    /* foreach using $_ */
 #define CXp_FOR_DEF    0x10    /* foreach using $_ */
+/* these 3 are mutually exclusive */
 #define CXp_FOR_LVREF  0x20    /* foreach using \$var */
 #define CXp_FOR_GV     0x40    /* foreach using package var */
 #define CXp_FOR_PAD    0x80    /* foreach using lexical var */
 #define CXp_FOR_LVREF  0x20    /* foreach using \$var */
 #define CXp_FOR_GV     0x40    /* foreach using package var */
 #define CXp_FOR_PAD    0x80    /* foreach using lexical var */
+
 #define CxPADLOOP(c)   ((c)->cx_type & CXp_FOR_PAD)
 
 /* private flags for CXt_SUBST */
 #define CxPADLOOP(c)   ((c)->cx_type & CXp_FOR_PAD)
 
 /* private flags for CXt_SUBST */
index bc8b778..3643ec5 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1458,7 +1458,7 @@ S_dopoptoloop(pTHX_ I32 startingblock)
     return i;
 }
 
     return i;
 }
 
-/* find the next GIVEN or FOR loop context block */
+/* find the next GIVEN or FOR (with implicit $_) loop context block */
 
 STATIC I32
 S_dopoptogivenfor(pTHX_ I32 startingblock)
 
 STATIC I32
 S_dopoptogivenfor(pTHX_ I32 startingblock)
@@ -2126,6 +2126,8 @@ PP(pp_enteriter)
             itersave = GvSV(sv);
             SvREFCNT_inc_simple_void(itersave);
             cxflags = CXp_FOR_GV;
             itersave = GvSV(sv);
             SvREFCNT_inc_simple_void(itersave);
             cxflags = CXp_FOR_GV;
+            if (PL_op->op_private & OPpITER_DEF)
+                cxflags |= CXp_FOR_DEF;
         }
         else {                          /* LV ref: for \$foo (...) */
             assert(SvTYPE(sv) == SVt_PVMG);
         }
         else {                          /* LV ref: for \$foo (...) */
             assert(SvTYPE(sv) == SVt_PVMG);
@@ -2135,9 +2137,8 @@ PP(pp_enteriter)
             cxflags = CXp_FOR_LVREF;
         }
     }
             cxflags = CXp_FOR_LVREF;
         }
     }
-
-    if (PL_op->op_private & OPpITER_DEF)
-       cxflags |= CXp_FOR_DEF;
+    /* OPpITER_DEF (implicit $_) should only occur with a GV iter var */
+    assert((cxflags & CXp_FOR_GV) || !(PL_op->op_private & OPpITER_DEF));
 
     PUSHBLOCK(cx, cxflags, MARK);
     PUSHLOOP_FOR(cx, itervarp, itersave);
 
     PUSHBLOCK(cx, cxflags, MARK);
     PUSHLOOP_FOR(cx, itervarp, itersave);