@@ -95,6 +95,7 @@ Perl_av_extend(pTHX_ AV *av, SSize_t key)
95
95
}
96
96
97
97
/* The guts of av_extend. *Not* for general use! */
98
+ /* Also called directly from pp_assign, padlist_store, padnamelist_store */
98
99
void
99
100
Perl_av_extend_guts (pTHX_ AV * av , SSize_t key , SSize_t * maxp , SV * * * allocp ,
100
101
SV * * * arrayp )
@@ -106,25 +107,21 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
106
107
"panic: av_extend_guts() negative count (%" IVdf ")" , (IV )key );
107
108
108
109
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 ;
112
117
113
- if (av && * allocp != * arrayp ) {
114
- ary = * allocp + AvFILLp (av ) + 1 ;
115
- tmp = * arrayp - * allocp ;
116
118
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
+
123
120
if (key > * maxp - 10 ) {
124
121
newmax = key + * maxp ;
125
122
goto resize ;
126
123
}
127
- } else if (* allocp ) {
124
+ } else if (* allocp ) { /* a full SV* array exists */
128
125
129
126
#ifdef Perl_safesysmalloc_size
130
127
/* 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,
151
148
newmax = (key > SSize_t_MAX - newmax )
152
149
? SSize_t_MAX : key + newmax ;
153
150
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
+ }
163
160
#ifdef STRESS_REALLOC
164
161
{
165
162
SV * * const old_alloc = * allocp ;
@@ -173,31 +170,41 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
173
170
#ifdef Perl_safesysmalloc_size
174
171
resized :
175
172
#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()?) */
179
178
PL_stack_sp = * allocp + (PL_stack_sp - PL_stack_base );
180
179
PL_stack_base = * allocp ;
181
180
PL_stack_max = PL_stack_base + newmax ;
182
181
}
183
- } else {
184
- newmax = key < 3 ? 3 : key ;
182
+ } else { /* there is no SV* array yet */
183
+ * maxp = key < 3 ? 3 : key ;
185
184
{
186
185
/* 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" );
188
188
}
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 ;
193
200
}
201
+
194
202
if (av && AvREAL (av )) {
195
- while ( tmp )
196
- ary [ -- tmp ] = NULL ;
203
+ zero :
204
+ Zero ( * allocp + ary_offset , to_null , SV * ) ;
197
205
}
198
206
199
207
* arrayp = * allocp ;
200
- * maxp = newmax ;
201
208
}
202
209
}
203
210
0 commit comments