diff --git a/regcomp_invlist.c b/regcomp_invlist.c index 5289d5a5d53d..3583087b041f 100644 --- a/regcomp_invlist.c +++ b/regcomp_invlist.c @@ -247,13 +247,26 @@ S_invlist_trim(SV* invlist) /* But don't free up the space needed for the 0 UV that is always at the * beginning of the list, nor the trailing NUL */ - const UV min_size = TO_INTERNAL_SIZE(1) + 1; + const STRLEN want_size = MAX( + TO_INTERNAL_SIZE(1) + 1, /* minimum length needed */ + SvCUR(invlist) + 1 /* SvCUR(invlist) can be 0, + * often is TO_INTERNAL_SIZE(1) or larger */ + ); PERL_ARGS_ASSERT_INVLIST_TRIM; assert(is_invlist(invlist)); - SvPV_renew(invlist, MAX(min_size, SvCUR(invlist) + 1)); + /* It's very common for SvLEN(invlist) to be equal to: + * TO_INTERNAL_SIZE(1) + 1 + * SvCUR(invlist) + 2 + * SvCUR(invlist) + "a few" + * In such cases there's zero or negligible benefit to + * calling SvPV_renew and thereby safesysrealloc(). + * So check if that really seems warranted. */ + if ( SvLEN(invlist) < want_size || SvLEN(invlist) > want_size + PTRSIZE ) { + SvPV_renew(invlist, want_size); + } } PERL_STATIC_INLINE void