Skip to content

Commit bd9b4e9

Browse files
committed
S_invlist_trim - don't SvPV_renew if SvLEN(invlist) is < PTRSIZE larger
Currently, `S_invlist_trim` always calls `SvPV_renew(invlist, <size>)`, which is a macro wrapping a call to `safesysrealloc()`. However, `SvLEN(invlist)` is often already exactly the desired size, or it is larger by less than the size of a pointer. With this commit, such cases just return without calling `SvPV_renew()`.
1 parent eb3dc27 commit bd9b4e9

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

regcomp_invlist.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,26 @@ S_invlist_trim(SV* invlist)
247247

248248
/* But don't free up the space needed for the 0 UV that is always at the
249249
* beginning of the list, nor the trailing NUL */
250-
const UV min_size = TO_INTERNAL_SIZE(1) + 1;
250+
const STRLEN want_size = MAX(
251+
TO_INTERNAL_SIZE(1) + 1, /* minimum length needed */
252+
SvCUR(invlist) + 1 /* SvCUR(invlist) can be 0,
253+
* often is TO_INTERNAL_SIZE(1) or larger */
254+
);
251255

252256
PERL_ARGS_ASSERT_INVLIST_TRIM;
253257

254258
assert(is_invlist(invlist));
255259

256-
SvPV_renew(invlist, MAX(min_size, SvCUR(invlist) + 1));
260+
/* It's very common for SvLEN(invlist) to be equal to:
261+
* TO_INTERNAL_SIZE(1) + 1
262+
* SvCUR(invlist) + 2
263+
* SvCUR(invlist) + "a few"
264+
* In such cases there's zero or negligible benefit to
265+
* calling SvPV_renew and thereby safesysrealloc().
266+
* So check if that really seems warranted. */
267+
if ( SvLEN(invlist) < want_size || SvLEN(invlist) > want_size + PTRSIZE ) {
268+
SvPV_renew(invlist, want_size);
269+
}
257270
}
258271

259272
PERL_STATIC_INLINE void

0 commit comments

Comments
 (0)