From: Nicholas Clark <nick@ccl4.org>
Date: Sat, 26 Jan 2008 17:54:29 +0000 (+0000)
Subject: Investigation reveals that the work of restoring the iterator to the
X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=09edbca0f5c7caf9dd4acef80d8e6275e5a95ea1;p=p5sagit%2Fp5-mst-13.2.git

Investigation reveals that the work of restoring the iterator to the
pad is shared between POPLOOP, using itersave, and the end of scope
restore action requested by Perl_save_padsv(). In fact, the only user
of SAVEt_PADSV is pp_enteriter, and it already provides enough
information to allow it to perform the sv_2mortal() in POPLOOP.
So make it do so. Rather than creating a new routine, use the existing
routine because nothing else (at least nothing else known to Google's
codesearch) uses it. But rename it just in case something we can't see
is being naughty and using our private functions - they will get
link errors against 5.12.

All this means that itersave is now redundant. So remove it.
This makes struct context 48 bytes on ILP32 platforms with 32bit IVs,
down from 64 bytes in 5.10. 33% more context stack in the same memory.

p4raw-id: //depot/perl@33080
---

diff --git a/cop.h b/cop.h
index ca9dae2..4af6b8f 100644
--- a/cop.h
+++ b/cop.h
@@ -442,7 +442,6 @@ struct block_loop {
     OP *	next_op;
     SV **	itervar;
 #endif
-    SV *	itersave;
     union {
 	struct { /* valid if type is LOOP_FOR or LOOP_PLAIN (but {NULL,0})*/
 	    AV * ary; /* use the stack if this is NULL */
@@ -469,18 +468,11 @@ struct block_loop {
 	 : (SV**)NULL)
 #  define CX_ITERDATA_SET(cx,idata)					\
 	CX_CURPAD_SAVE(cx->blk_loop);					\
-	if ((cx->blk_loop.iterdata = (idata)) && SvPADMY(*CxITERVAR(cx))) \
-	    cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx));	\
-	else								\
-	    cx->blk_loop.itersave = NULL;
+	cx->blk_loop.iterdata = (idata);
 #else
 #  define CxITERVAR(c)		((c)->blk_loop.itervar)
 #  define CX_ITERDATA_SET(cx,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;
+	cx->blk_loop.itervar = (SV**)(ivar);
 #endif
 #define CxLABEL(c)	(0 + (c)->blk_oldcop->cop_label)
 #define CxHASARGS(c)	(((c)->cx_type & CXp_HASARGS) == CXp_HASARGS)
@@ -515,12 +507,6 @@ struct block_loop {
 	    SvREFCNT_dec(cx->blk_loop.state_u.lazysv.cur);		\
 	    SvREFCNT_dec(cx->blk_loop.state_u.lazysv.end);		\
 	}								\
-	if (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);
 
diff --git a/embed.fnc b/embed.fnc
index 972e541..ef4ae06 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -775,7 +775,7 @@ Ap	|SV*	|save_scalar	|NN GV* gv
 Ap	|void	|save_pptr	|NN char** pptr
 Ap	|void	|save_vptr	|NN void* pptr
 Ap	|void	|save_re_context
-Ap	|void	|save_padsv	|PADOFFSET off
+Ap	|void	|save_padsv_and_mortalize|PADOFFSET off
 Ap	|void	|save_sptr	|NN SV** sptr
 Ap	|SV*	|save_svref	|NN SV** sptr
 p	|OP*	|sawparens	|NULLOK OP* o
diff --git a/embed.h b/embed.h
index c0bcae2..8d2d11e 100644
--- a/embed.h
+++ b/embed.h
@@ -781,7 +781,7 @@
 #define save_pptr		Perl_save_pptr
 #define save_vptr		Perl_save_vptr
 #define save_re_context		Perl_save_re_context
-#define save_padsv		Perl_save_padsv
+#define save_padsv_and_mortalize	Perl_save_padsv_and_mortalize
 #define save_sptr		Perl_save_sptr
 #define save_svref		Perl_save_svref
 #ifdef PERL_CORE
@@ -3085,7 +3085,7 @@
 #define save_pptr(a)		Perl_save_pptr(aTHX_ a)
 #define save_vptr(a)		Perl_save_vptr(aTHX_ a)
 #define save_re_context()	Perl_save_re_context(aTHX)
-#define save_padsv(a)		Perl_save_padsv(aTHX_ a)
+#define save_padsv_and_mortalize(a)	Perl_save_padsv_and_mortalize(aTHX_ a)
 #define save_sptr(a)		Perl_save_sptr(aTHX_ a)
 #define save_svref(a)		Perl_save_svref(aTHX_ a)
 #ifdef PERL_CORE
diff --git a/pp_ctl.c b/pp_ctl.c
index 5da6993..9c6e2b1 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1849,11 +1849,10 @@ PP(pp_enteriter)
 	    SAVESETSVFLAGS(PAD_SVl(PL_op->op_targ),
 		    SVs_PADSTALE, SVs_PADSTALE);
 	}
+	SAVEPADSVANDMORTALIZE(PL_op->op_targ);
 #ifndef USE_ITHREADS
 	svp = &PAD_SVl(PL_op->op_targ);		/* "my" variable */
-	SAVESPTR(*svp);
 #else
-	SAVEPADSV(PL_op->op_targ);
 	iterdata = INT2PTR(void*, PL_op->op_targ);
 	cxtype |= CXp_PADVAR;
 #endif
diff --git a/proto.h b/proto.h
index e1a3647..222bd14 100644
--- a/proto.h
+++ b/proto.h
@@ -2089,7 +2089,7 @@ PERL_CALLCONV void	Perl_save_vptr(pTHX_ void* pptr)
 			__attribute__nonnull__(pTHX_1);
 
 PERL_CALLCONV void	Perl_save_re_context(pTHX);
-PERL_CALLCONV void	Perl_save_padsv(pTHX_ PADOFFSET off);
+PERL_CALLCONV void	Perl_save_padsv_and_mortalize(pTHX_ PADOFFSET off);
 PERL_CALLCONV void	Perl_save_sptr(pTHX_ SV** sptr)
 			__attribute__nonnull__(pTHX_1);
 
diff --git a/scope.c b/scope.c
index 616247e..fae4892 100644
--- a/scope.c
+++ b/scope.c
@@ -412,15 +412,15 @@ Perl_save_sptr(pTHX_ SV **sptr)
 }
 
 void
-Perl_save_padsv(pTHX_ PADOFFSET off)
+Perl_save_padsv_and_mortalize(pTHX_ PADOFFSET off)
 {
     dVAR;
     SSCHECK(4);
     ASSERT_CURPAD_ACTIVE("save_padsv");
-    SSPUSHPTR(PL_curpad[off]);
+    SSPUSHPTR(SvREFCNT_inc_simple_NN(PL_curpad[off]));
     SSPUSHPTR(PL_comppad);
     SSPUSHLONG((long)off);
-    SSPUSHINT(SAVEt_PADSV);
+    SSPUSHINT(SAVEt_PADSV_AND_MORTALIZE);
 }
 
 void
@@ -929,12 +929,18 @@ Perl_leave_scope(pTHX_ I32 base)
 	    else
 		PL_curpad = NULL;
 	    break;
-	case SAVEt_PADSV:
+	case SAVEt_PADSV_AND_MORTALIZE:
 	    {
 		const PADOFFSET off = (PADOFFSET)SSPOPLONG;
+		SV **svp;
 		ptr = SSPOPPTR;
-		if (ptr)
-		    assert(AvARRAY((PAD*)ptr)[off] == (SV*)SSPOPPTR);
+		assert (ptr);
+		svp = AvARRAY((PAD*)ptr) + off;
+		/* This mortalizing used to be done by POPLOOP() via itersave.
+		   But as we have all the information here, we can do it here,
+		   save even having to have itersave in the struct.  */
+		sv_2mortal(*svp);
+		*svp = (SV*)SSPOPPTR;
 	    }
 	    break;
 	case SAVEt_SAVESWITCHSTACK:
@@ -1101,9 +1107,6 @@ Perl_cx_dump(pTHX_ PERL_CONTEXT *cx)
 		(long)cx->blk_loop.state_u.ary.ix);
 	PerlIO_printf(Perl_debug_log, "BLK_LOOP.ITERVAR = 0x%"UVxf"\n",
 		PTR2UV(CxITERVAR(cx)));
-	if (CxITERVAR(cx))
-	    PerlIO_printf(Perl_debug_log, "BLK_LOOP.ITERSAVE = 0x%"UVxf"\n",
-		PTR2UV(cx->blk_loop.itersave));
 	break;
 
     case CXt_SUBST:
diff --git a/scope.h b/scope.h
index 606fbc2..7f56460 100644
--- a/scope.h
+++ b/scope.h
@@ -43,7 +43,7 @@
 #define SAVEt_I8		32
 #define SAVEt_COMPPAD		33
 #define SAVEt_GENERIC_PVREF	34
-#define SAVEt_PADSV		35
+#define SAVEt_PADSV_AND_MORTALIZE	35
 #define SAVEt_MORTALIZESV	36
 #define SAVEt_SHARED_PVREF	37
 #define SAVEt_BOOL		38
@@ -126,7 +126,7 @@ Closing bracket on a callback.  See C<ENTER> and L<perlcall>.
 #define SAVESPTR(s)	save_sptr((SV**)&(s))
 #define SAVEPPTR(s)	save_pptr((char**)&(s))
 #define SAVEVPTR(s)	save_vptr((void*)&(s))
-#define SAVEPADSV(s)	save_padsv(s)
+#define SAVEPADSVANDMORTALIZE(s)	save_padsv_and_mortalize(s)
 #define SAVEFREESV(s)	save_freesv((SV*)(s))
 #define SAVEMORTALIZESV(s)	save_mortalizesv((SV*)(s))
 #define SAVEFREEOP(o)	save_freeop((OP*)(o))
diff --git a/sv.c b/sv.c
index 925b83e..6d60eeb 100644
--- a/sv.c
+++ b/sv.c
@@ -10564,8 +10564,6 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param)
 		ncx->blk_loop.oldcomppad
 		    = (PAD*)ptr_table_fetch(PL_ptr_table,
 					    ncx->blk_loop.oldcomppad);
-		ncx->blk_loop.itersave	= sv_dup_inc(ncx->blk_loop.itersave,
-						     param);
 		break;
 	    case CXt_FORMAT:
 		ncx->blk_format.cv	= cv_dup(ncx->blk_format.cv, param);
@@ -10874,13 +10872,13 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
 		TOPPTR(nss,ix) = hv_dup_inc(hv, param);
 	    }
 	    break;
-	case SAVEt_PADSV:
+	case SAVEt_PADSV_AND_MORTALIZE:
 	    longval = (long)POPLONG(ss,ix);
 	    TOPLONG(nss,ix) = longval;
 	    ptr = POPPTR(ss,ix);
 	    TOPPTR(nss,ix) = any_dup(ptr, proto_perl);
 	    sv = (SV*)POPPTR(ss,ix);
-	    TOPPTR(nss,ix) = sv_dup(sv, param);
+	    TOPPTR(nss,ix) = sv_dup_inc(sv, param);
 	    break;
 	case SAVEt_BOOL:
 	    ptr = POPPTR(ss,ix);