Skip to content

Commit 4342210

Browse files
committed
Perl_leave_scope - sv_backoff shouldn't do an unnecessay string copy
When a `my` SV goes out of scope, any OOK hack on its string buffer is undone by `Perl_sv_backoff`. If the SV is `SvOK`, a copy of the buffer contents will occur, but since the contents are defunct at this point, the copy is unnecessary. See #23967 as an example of where this unnecessary copy had a noticeable effect on performance. This commit essentially inlines the necessary parts of `sv_backoff` to avoid the copy, without excessive messing around with `sv`'s flags at the call site in `Perl_leave_scope`.
1 parent e3b0f74 commit 4342210

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

scope.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,8 +1440,20 @@ Perl_leave_scope(pTHX_ I32 base)
14401440

14411441
if (SvTYPE(sv) == SVt_PVHV && HvHasAUX(sv))
14421442
Perl_hv_kill_backrefs(aTHX_ MUTABLE_HV(sv));
1443-
else if(SvOOK(sv))
1444-
sv_backoff(sv);
1443+
else if(SvOOK(sv)) {
1444+
/* Inlined sv_backoff() - the buffer contents are
1445+
* defunct and there's no need to copy them. All that
1446+
* is needed is resetting SvLEN and the SvPVX pointer. */
1447+
assert(SvTYPE(sv) != SVt_PVHV); /* the branch above */
1448+
assert(SvTYPE(sv) != SVt_PVAV);
1449+
1450+
STRLEN delta;
1451+
SvOOK_offset(sv, delta);
1452+
1453+
SvLEN_set(sv, SvLEN(sv) + delta);
1454+
SvPV_set(sv, SvPVX(sv) - delta);
1455+
SvFLAGS(sv) &= ~SVf_OOK;
1456+
}
14451457

14461458
if (SvMAGICAL(sv)) {
14471459
/* note that backrefs (either in HvAUX or magic)

0 commit comments

Comments
 (0)