mirror of
https://github.com/Perl/perl5.git
synced 2026-01-26 08:38:23 +00:00
Clear all variable pad slots after multi-variable foreach loop
We need to remember to clear all the pad slots related to iteration variables, which means some number of additional ones after the main "itervar" when doing multi-variable iteration. This ensures we don't retain references or large scalar values longer than necessary.
This commit is contained in:
parent
47a5d1f4d9
commit
4430717932
19
inline.h
19
inline.h
@ -4152,6 +4152,25 @@ Perl_cx_poploop(pTHX_ PERL_CONTEXT *cx)
|
||||
cx->blk_loop.itersave = NULL;
|
||||
SvREFCNT_dec(cursv);
|
||||
}
|
||||
if (CxPADLOOP(cx)) {
|
||||
/* for my ... might be multivariable. my_op->op_next will point at
|
||||
* the OP_ITER whose op_targ contains the count of how many more
|
||||
* variables
|
||||
*/
|
||||
OP *iterop = cx->blk_loop.my_op->op_next;
|
||||
assert(iterop->op_type == OP_ITER);
|
||||
PADOFFSET how_many = iterop->op_targ;
|
||||
/* op_targ actually stores count - 1, so it's the count of additional
|
||||
* vars after itervar itself */
|
||||
for (SV **svp = cx->blk_loop.itervar_u.svp + 1; how_many; svp++, how_many--) {
|
||||
/* we didn't store an itersave for these, but we know they are all
|
||||
* scoped to the loop we have just left. It's therefore safe to store
|
||||
* &PL_sv_undef there since they weren't live before or afterwards.
|
||||
*/
|
||||
SvREFCNT_dec(*svp);
|
||||
*svp = &PL_sv_undef;
|
||||
}
|
||||
}
|
||||
if (cx->cx_type & CXp_FOR_LVREF) {
|
||||
SV *itervar = (SV *)(cx)->blk_loop.itervar_u.gv;
|
||||
SV *origval = (cx)->blk_loop.itersave;
|
||||
|
||||
@ -511,4 +511,19 @@ is($continue, 'xx', 'continue reached twice');
|
||||
pass '2-var for does not crash on lexical sub calls';
|
||||
}
|
||||
|
||||
# all foreach iteration vars are cleared in a timely manner
|
||||
{
|
||||
my @arrx;
|
||||
my @arry;
|
||||
|
||||
for my ($x, $y) (\@arrx, \@arry) {
|
||||
# list items are aliased; add 1 to account for \ ref in the following
|
||||
refcount_is \@arrx, 2+1, 'arrx refcount 2 inside loop';
|
||||
refcount_is \@arry, 2+1, 'arry refcount 2 inside loop';
|
||||
}
|
||||
|
||||
refcount_is \@arrx, 1+1, 'arrx refcount 1 after loop';
|
||||
refcount_is \@arry, 1+1, 'arry refcount 1 after loop';
|
||||
}
|
||||
|
||||
done_testing();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user