Skip to content

Commit 80dd43e

Browse files
committed
S_invlist_trim - don't SvPV_renew where no change is likely
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, the new `expected_size` macro is used to reduce the number of cases in which S_invlist_trim will try to shrink a buffer but no shrinkage is likely to occur. (For example, if the desired size is less than the minimum actual allocation size.)
1 parent 4a38ddc commit 80dd43e

File tree

1 file changed

+22
-3
lines changed

1 file changed

+22
-3
lines changed

regcomp_invlist.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,14 +246,33 @@ S_invlist_trim(SV* invlist)
246246
/* Free the not currently-being-used space in an inversion list */
247247

248248
/* But don't free up the space needed for the 0 UV that is always at the
249-
* beginning of the list, nor the trailing NUL */
250-
const UV min_size = TO_INTERNAL_SIZE(1) + 1;
249+
* beginning of the list, nor the trailing NUL. The smallest possible
250+
* allocation size may or may not be larger than this, depending upon
251+
* the malloc implementation in use. */
252+
253+
const STRLEN min_size = (PERL_STRLEN_NEW_MIN > TO_INTERNAL_SIZE(1) + 1)
254+
? PERL_STRLEN_NEW_MIN : TO_INTERNAL_SIZE(1) + 1;
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+
/* Notes:
261+
* SvCUR(invlist) can be 0, often is min_size or larger
262+
*
263+
* It's very common for SvLEN(invlist) to be equal to:
264+
* (TO_INTERNAL_SIZE(1) + 1)
265+
* ...or the minimum allocation size if larger
266+
* SvCUR(invlist) + 2
267+
* SvCUR(invlist) + "a few"
268+
*/
269+
270+
const STRLEN realistic_size = expected_size(
271+
MAX( min_size, SvCUR(invlist) + 1) );
272+
273+
if ( SvLEN(invlist) > realistic_size ) {
274+
SvPV_renew(invlist, realistic_size);
275+
}
257276
}
258277

259278
PERL_STATIC_INLINE void

0 commit comments

Comments
 (0)