Skip to content

Commit 5e2b259

Browse files
committed
SvPV_shrink_to_cur: don't be unrealistic, do include space for COW
The `SvPV_shrink_to_cur` macro shrinks an allocation to `SvCUR(sv) + 1`, which does not include an additional byte for Copy-On-Write (COW). GH#22116 - a902d92 - short-circuited constant folding on CONST OPs, as this should be unnecessary. However, Dave Mitchell noticed that it had the inadvertent effect of disabling COW on SVs holding UTF8 string literals (e.g. `"\x{100}abcd"`). When a CONST OP is created, `Perl_ck_svconst` should mark its SV as being COW-able. But SVs built via `S_scan_const`, when that has called `SvPV_shrink_to_cur`, have resulting `SvLEN(sv)` values that fail the `SvCANCOW(sv)` test. Previously, constant folding had the effect of copying the literal into a buffer large enough for COW. This commit modifies `SvPV_shrink_to_cur` to: allocate an additional byte to allow for subsequent COWing directly. The macro has also been modified such that: * No reallocation will be attempted if the saving is unrealistically small, or otherwise no saving is likely to be achievable. * The intended saving is compared with SvLEN(sv), which enables checks at call sites to be simplified.
1 parent 482fd30 commit 5e2b259

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

sv.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,9 +1590,19 @@ L</C<SV_CHECK_THINKFIRST_COW_DROP>> before calling this.
15901590
=cut
15911591
*/
15921592

1593-
#define SvPV_shrink_to_cur(sv) STMT_START { \
1594-
const STRLEN _lEnGtH = SvCUR(sv) + 1; \
1595-
SvPV_renew(sv, _lEnGtH); \
1593+
/* Notes: Ensure the buffer is big enough to be COWed in the future, so
1594+
+ 1 for the trailing null byte + 1 for the COW count.
1595+
* Don't try to shrink if the saving is too small to be realistic (given
1596+
* the realities of allocators) or noticeable.
1597+
* Don't try to shrink smaller than PERL_STRLEN_NEW_MIN, as that is
1598+
* unlikely to result in a smaller allocation.
1599+
*/
1600+
1601+
#define SvPV_shrink_to_cur(sv) STMT_START { \
1602+
const STRLEN _lEnGtH = SvCUR(sv) + 2; \
1603+
if ((SvLEN(sv) > _lEnGtH + PTRSIZE) && \
1604+
( _lEnGtH >= PERL_STRLEN_NEW_MIN) ) \
1605+
SvPV_renew(sv, _lEnGtH); \
15961606
} STMT_END
15971607

15981608
/*

0 commit comments

Comments
 (0)