Skip to content

Commit 399fef9

Browse files
richardleachkhwilliamson
authored andcommitted
Perl_av_extend_guts: use Zero() rather than a while loop to set NULLs
1 parent 440c185 commit 399fef9

File tree

1 file changed

+42
-35
lines changed

1 file changed

+42
-35
lines changed

av.c

+42-35
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ Perl_av_extend(pTHX_ AV *av, SSize_t key)
9595
}
9696

9797
/* The guts of av_extend. *Not* for general use! */
98+
/* Also called directly from pp_assign, padlist_store, padnamelist_store */
9899
void
99100
Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
100101
SV ***arrayp)
@@ -106,25 +107,21 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
106107
"panic: av_extend_guts() negative count (%" IVdf ")", (IV)key);
107108

108109
if (key > *maxp) {
109-
SV** ary;
110-
SSize_t tmp;
111-
SSize_t newmax;
110+
SSize_t ary_offset = *maxp + 1;
111+
SSize_t to_null = 0;
112+
SSize_t newmax = 0;
113+
114+
if (av && *allocp != *arrayp) { /* a shifted SV* array exists */
115+
to_null = *arrayp - *allocp;
116+
*maxp += to_null;
112117

113-
if (av && *allocp != *arrayp) {
114-
ary = *allocp + AvFILLp(av) + 1;
115-
tmp = *arrayp - *allocp;
116118
Move(*arrayp, *allocp, AvFILLp(av)+1, SV*);
117-
*maxp += tmp;
118-
*arrayp = *allocp;
119-
if (AvREAL(av)) {
120-
while (tmp)
121-
ary[--tmp] = NULL;
122-
}
119+
123120
if (key > *maxp - 10) {
124121
newmax = key + *maxp;
125122
goto resize;
126123
}
127-
} else if (*allocp) {
124+
} else if (*allocp) { /* a full SV* array exists */
128125

129126
#ifdef Perl_safesysmalloc_size
130127
/* Whilst it would be quite possible to move this logic around
@@ -151,15 +148,15 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
151148
newmax = (key > SSize_t_MAX - newmax)
152149
? SSize_t_MAX : key + newmax;
153150
resize:
154-
{
155-
/* it should really be newmax+1 here, but if newmax
156-
* happens to equal SSize_t_MAX, then newmax+1 is
157-
* undefined. This means technically we croak one
158-
* index lower than we should in theory; in practice
159-
* its unlikely the system has SSize_t_MAX/sizeof(SV*)
160-
* bytes to spare! */
161-
MEM_WRAP_CHECK_s(newmax, SV*, "Out of memory during array extend");
162-
}
151+
{
152+
/* it should really be newmax+1 here, but if newmax
153+
* happens to equal SSize_t_MAX, then newmax+1 is
154+
* undefined. This means technically we croak one
155+
* index lower than we should in theory; in practice
156+
* its unlikely the system has SSize_t_MAX/sizeof(SV*)
157+
* bytes to spare! */
158+
MEM_WRAP_CHECK_s(newmax, SV*, "Out of memory during array extend");
159+
}
163160
#ifdef STRESS_REALLOC
164161
{
165162
SV ** const old_alloc = *allocp;
@@ -173,31 +170,41 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
173170
#ifdef Perl_safesysmalloc_size
174171
resized:
175172
#endif
176-
ary = *allocp + *maxp + 1;
177-
tmp = newmax - *maxp;
178-
if (av == PL_curstack) { /* Oops, grew stack (via av_store()?) */
173+
to_null += newmax - *maxp;
174+
*maxp = newmax;
175+
176+
/* See GH#18014 for discussion of when this might be needed: */
177+
if (av == PL_curstack) { /* Oops, grew stack (via av_store()?) */
179178
PL_stack_sp = *allocp + (PL_stack_sp - PL_stack_base);
180179
PL_stack_base = *allocp;
181180
PL_stack_max = PL_stack_base + newmax;
182181
}
183-
} else {
184-
newmax = key < 3 ? 3 : key;
182+
} else { /* there is no SV* array yet */
183+
*maxp = key < 3 ? 3 : key;
185184
{
186185
/* see comment above about newmax+1*/
187-
MEM_WRAP_CHECK_s(newmax, SV*, "Out of memory during array extend");
186+
MEM_WRAP_CHECK_s(*maxp, SV*,
187+
"Out of memory during array extend");
188188
}
189-
Newx(*allocp, newmax+1, SV*);
190-
ary = *allocp + 1;
191-
tmp = newmax;
192-
*allocp[0] = NULL; /* For the stacks */
189+
/* Newxz isn't used below because testing showed it to be slower
190+
* than Newx+Zero (also slower than Newx + the previous while
191+
* loop) for small arrays, which are very common in perl. */
192+
Newx(*allocp, *maxp+1, SV*);
193+
/* Stacks require only the first element to be &PL_sv_undef
194+
* (set elsewhere). However, since non-stack AVs are likely
195+
* to dominate in modern production applications, stacks
196+
* don't get any special treatment here. */
197+
ary_offset = 0;
198+
to_null = *maxp+1;
199+
goto zero;
193200
}
201+
194202
if (av && AvREAL(av)) {
195-
while (tmp)
196-
ary[--tmp] = NULL;
203+
zero:
204+
Zero(*allocp + ary_offset,to_null,SV*);
197205
}
198206

199207
*arrayp = *allocp;
200-
*maxp = newmax;
201208
}
202209
}
203210

0 commit comments

Comments
 (0)