Skip to content

Perl_sv_clear: unrolled SvREFCNT_dec and sv_free2....isn't that?! #22798

Closed
@richardleach

Description

@richardleach

Description
Towards the bottom of Perl_sv_clear, which is frequently a very hot function, there is the following comment:
/* unrolled SvREFCNT_dec and sv_free2 follows: */

Sounds good, makes sense that it would unroll SvREFCNT_dec and sv_free2.
But that's not actually what it does:

            /* unrolled SvREFCNT_dec and sv_free2 follows: */

            if (!sv)
                continue;
            if (!SvREFCNT(sv)) {
                sv_free(sv);
                continue;
            }
            .....

At least nowadays, sv_free means calling Perl_sv_free:

void
Perl_sv_free(pTHX_ SV *const sv)
{
    SvREFCNT_dec(sv);
}

SvREFCNT_dec is an inline function in sv_inline.h:

PERL_STATIC_INLINE void
Perl_SvREFCNT_dec(pTHX_ SV *sv)
{
    if (LIKELY(sv != NULL)) {
        U32 rc = SvREFCNT(sv);
        if (LIKELY(rc > 1))
            SvREFCNT(sv) = rc - 1;
        else
            Perl_sv_free2(aTHX_ sv, rc);
    }
}

So instead of unrolling SvREFCNT_dec and sv_free2, it calls a function (probably inlined)
to call SvREFCNT_dec which likely will call sv_free2. That's not unrolled at all!

The likely impact of this is some SV freeing is taking longer than it strictly has to. Looking at
gcov coverage when running the test harness, there are 35099459 calls to Perl_sv_free and
797851111 calls to Perl_sv_free2, so maybe ~4% of cleared SVs.

Expected behavior
I haven't sat down to figure this out. It seems like the status quo in Perl_sv_clear must be
wrong though and either the comment should be amended, (more likely) the call to sv_free
is intended to be a recursive call back to sv_free2, or some other code change should happen.

Besides Perl_sv_clear, only ext/Opcode/Opcode.xs and dist/Storable/Storable.xs seem
to call sv_free directly. Probably they should be using SvREFCNT_dec or calling sv_free2
instead.

Perl configuration
blead

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions