summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-01-09 19:54:26 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-01-09 19:54:26 -0800
commit60edcf09a5cb026822f99270a4bfbe3149cfbb52 (patch)
tree9651ece6289498ae99ca78bc4da131b5c22be3b6 /pp_hot.c
parentf09f972badf5b299d86c10b00897652752e314ed (diff)
downloadperl-60edcf09a5cb026822f99270a4bfbe3149cfbb52.tar.gz
Better fix for perl #107440
> > Actually, the simplest solution seem to be to put the av or hv on > > the mortals stack in pp_aassign and pp_undef, rather than in > > [ah]v_undef/clear. > > This makes me nervous. The tmps stack is typically cleared only on > statement boundaries, so we run the risks of > > * user-visible delaying of freeing elements; > * large tmps stack growth might be possible with > certain types of loop that repeatedly assign to an array without > freeing tmps (eg map? I think I fixed most map/grep tmps leakage > a > while back, but there may still be some edge cases). > > Surely an ENTER/SAVEFREESV/LEAVE inside pp_aassign is just as > efficient, > without any attendant risks? > > Also, although pp_aassign and pp_undef are now fixed, the > [ah]v_undef/clear functions aren't, and they're part of the public API > that can be called independently of pp_aassign etc. Ideally they > should > be fixed (so they don't crash in mid-loop), and their documentation > updated to point out that on return, their AV/HV arg may have been > freed. This commit takes care of the first part; it changes pp_aassign to use ENTER/SAVEFREESV/LEAVE and adds the same to h_freeentries (called both by hv_undef and hv_clear), av_undef and av_clear. It effectively reverts the C code part of 9f71cfe6ef2.
Diffstat (limited to 'pp_hot.c')
-rw-r--r--pp_hot.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/pp_hot.c b/pp_hot.c
index add940049b..ff834a924e 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -993,8 +993,10 @@ PP(pp_aassign)
sv = *lelem++;
switch (SvTYPE(sv)) {
case SVt_PVAV:
- ary = MUTABLE_AV(sv_2mortal(SvREFCNT_inc_simple_NN(sv)));
+ ary = MUTABLE_AV(sv);
magic = SvMAGICAL(ary) != 0;
+ ENTER;
+ SAVEFREESV(SvREFCNT_inc_simple_NN(sv));
av_clear(ary);
av_extend(ary, lastrelem - relem);
i = 0;
@@ -1015,13 +1017,16 @@ PP(pp_aassign)
}
if (PL_delaymagic & DM_ARRAY_ISA)
SvSETMAGIC(MUTABLE_SV(ary));
+ LEAVE;
break;
case SVt_PVHV: { /* normal hash */
SV *tmpstr;
SV** topelem = relem;
- hash = MUTABLE_HV(sv_2mortal(SvREFCNT_inc_simple_NN(sv)));
+ hash = MUTABLE_HV(sv);
magic = SvMAGICAL(hash) != 0;
+ ENTER;
+ SAVEFREESV(SvREFCNT_inc_simple_NN(sv));
hv_clear(hash);
firsthashrelem = relem;
@@ -1058,6 +1063,7 @@ PP(pp_aassign)
do_oddball(hash, relem, firstrelem);
relem++;
}
+ LEAVE;
}
break;
default: