@@ -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
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4