Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perl_leave_adjust_stacks: additional efficiency for mortal copies #22163

Open
wants to merge 1 commit into
base: blead
Choose a base branch
from

Conversation

richardleach
Copy link
Contributor

The existing code has a fast path for copying a SVt_NULL or SVt_IV. For all
other types, a new SVt_NULL is passed into sv_setsv_flags, where it will
be upgraded into the required type by sv_upgrade().

This commit makes two changes:

  1. Special case copying a SVt_NV where possible, as sv_setsv_flags does.
  2. It's safe and more efficient to directly create a new type of SVt_PVNV
    or below, rather than upgrade it later, so do that.

@richardleach
Copy link
Contributor Author

This can be defer-next-dev.

@tonycoz tonycoz added the defer-next-dev This PR should not be merged yet, but await the next development cycle label Apr 21, 2024
pp_hot.c Outdated
Comment on lines 6007 to 6011
#if NVSIZE <= IVSIZE
if (SvTYPE(sv) <= SVt_NV) {
#else
if (SvTYPE(sv) <= SVt_IV) {
/* arg must be one of undef, IV/UV, or RV: skip
* sv_setsv_flags() and do the copy directly */
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what our policy on preprocessor use is, but this could be written more compactly as

if (SvTYPE(sv) <= (NVSIZE <= IVSIZE ? SVt_NV : SVt_IV)) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm certainly happy to write it like that. The current form is just mirroring what's already been in use in Perl_sv_setsv_flags.

Anyone else want to weigh in on preprocessor policy?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the only concern would be C compilers which can't do simple constant folding, which I'm assuming would be rare these days.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The C standard requires constant folding.

A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.

In particular, you can use constant expressions as array sizes, case labels, bit-field sizes, and null pointer constants. If it doesn't constant fold, it's not a C compiler. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, making those changes as suggested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er, stuff has gone awry in tests, will have to look into it later.

pp_hot.c Show resolved Hide resolved
pp_hot.c Outdated
Comment on lines 6038 to 6051
else if (NVSIZE <= IVSIZE && (srcflags & SVf_NOK)) {
SET_SVANY_FOR_BODYLESS_NV(newsv);
dstflags = (SVt_NV|SVf_NOK|SVp_NOK|SVs_TEMP);

/* both src and dst are <= SVt_MV, so sv_any points to the
* head; so access the head directly
*/
assert( &(sv->sv_u.svu_nv)
== &(((XPVNV*) SvANY(sv))->xnv_u.xnv_nv));
assert( &(newsv->sv_u.svu_nv)
== &(((XPVNV*) SvANY(newsv))->xnv_u.xnv_nv));
newsv->sv_u.svu_nv = sv->sv_u.svu_nv;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alas, this needs to use the preprocessor, since for long double or quadmath builds NV is 12-16 bytes and IV is 8 bytes on 64-bit platforms.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Tony. I'll revert to the original PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SvTYPE() comparison that mauke suggested is still fine, it just doesn't work for this block.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I had been thinking about keeping the two changes consistent, but have just reverted this second one.

@iabyn
Copy link
Contributor

iabyn commented May 22, 2024

Apart from the issue of the macros, I approve of this PR.

The existing code has a fast path for copying a SVt_NULL or SVt_IV. For all
other types, a new SVt_NULL is passed into sv_setsv_flags, where it will
be upgraded into the required type by sv_upgrade().

This commit makes two changes:
1) Special case copying a SVt_NV where possible, as sv_setsv_flags does.
2) It's safe and more efficient to directly create a new type of SVt_PVNV
   or below, rather than upgrade it later, so do that.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
defer-next-dev This PR should not be merged yet, but await the next development cycle
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants