Perl_sv_backoff - only copy the buffer contents if SvOK(sv)

When undoing an OOK, `Perl_sv_backoff` will always copy the shifted buffer
contents down to the start of the buffer. That's required when the contents
are live, unfortunate when the contents are defunct but tiny, and can have a
noticeably bad effect on performance when the contents are defunct but large.

See https://github.com/Perl/perl5/issues/23967 for an example of the latter.

With this commit the copy will only occur if `SvOK(sv)`. This test is expected
to indicate whether the buffer contents are active or defunct.
This commit is contained in:
Richard Leach 2025-11-29 00:25:01 +00:00
parent dd8309d23d
commit e3b0f74b83

8
sv.c
View File

@ -1336,6 +1336,8 @@ wrapper instead.
/* prior to 5.000 stable, this function returned the new OOK-less SvFLAGS
prior to 5.23.4 this function always returned 0
prior to 5.43.x, the contents of the string buffer were always copied
down to the start of the buffer. Now, this only happens if SvOK(sv)
*/
void
@ -1355,7 +1357,11 @@ Perl_sv_backoff(SV *const sv)
SvLEN_set(sv, SvLEN(sv) + delta);
SvPV_set(sv, SvPVX(sv) - delta);
SvFLAGS(sv) &= ~SVf_OOK;
Move(s, SvPVX(sv), SvCUR(sv)+1, char);
/* Don't copy a buffer if the contents are already defunct. */
if (SvOK(sv))
Move(s, SvPVX(sv), SvCUR(sv)+1, char);
return;
}