@@ -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,40 @@ 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
+ if (av == PL_curstack ) { /* Oops, grew stack (via av_store()?) */
179
177
PL_stack_sp = * allocp + (PL_stack_sp - PL_stack_base );
180
178
PL_stack_base = * allocp ;
181
179
PL_stack_max = PL_stack_base + newmax ;
182
180
}
183
- } else {
184
- newmax = key < 3 ? 3 : key ;
181
+ } else { /* there is no SV* array yet */
182
+ * maxp = key < 3 ? 3 : key ;
185
183
{
186
184
/* see comment above about newmax+1*/
187
- MEM_WRAP_CHECK_s (newmax , SV * , "Out of memory during array extend" );
185
+ MEM_WRAP_CHECK_s (* maxp , SV * ,
186
+ "Out of memory during array extend" );
188
187
}
189
- Newx (* allocp , newmax + 1 , SV * );
190
- ary = * allocp + 1 ;
191
- tmp = newmax ;
192
- * allocp [0 ] = NULL ; /* For the stacks */
188
+ /* Newxz isn't used below because testing showed it to be slower
189
+ * than Newx+Zero (also slower than Newx + the previous while
190
+ * loop) for small arrays, which are very common in perl. */
191
+ Newx (* allocp , * maxp + 1 , SV * );
192
+ /* Stacks require only the first element to be NULL, but all
193
+ * elements must be set to NULL for any other AV. Non-stack AVs
194
+ * are likely to dominate in modern production applications,
195
+ * so stacks don't get any special treatment here. */
196
+ ary_offset = 0 ;
197
+ to_null = * maxp + 1 ;
198
+ goto zero ;
193
199
}
200
+
194
201
if (av && AvREAL (av )) {
195
- while ( tmp )
196
- ary [ -- tmp ] = NULL ;
202
+ zero :
203
+ Zero ( * allocp + ary_offset , to_null , SV * ) ;
197
204
}
198
205
199
206
* arrayp = * allocp ;
200
- * maxp = newmax ;
201
207
}
202
208
}
203
209
0 commit comments