From c77e852a6f837836478e0f3b87e7a04e6076d3d8 Mon Sep 17 00:00:00 2001 From: bulk88 Date: Sun, 13 Oct 2024 09:06:36 -0400 Subject: [PATCH] de-mathom Perl_sv_taint() part 4 add SvTAINTTC() tailcall API Perl_newSVnv/Perl_newSViv/Perl_newSVuv, currently have to save the fresh SV *, either on C stack, or in non volatile registers, around the possible Perl_sv_taint() fn call inside SvTAINT(). If Perl_sv_taint() returns its SV * argument, and assigns it back to the same C var, now these 3 performance critical SV allocator functions, after plucking the SV head from the arena, these 3 function never ever have to store the fresh SV * back to C stack for any reason during their execution. This optimization removes pop/push pairs of the C compiler saving non-volatile registers and restoring them at function entry and exit since after SvTAINTTC() change, NO variables AT ALL, have to be saved around any function calls in Perl_newSVnv/Perl_newSViv/Perl_newSVuv. Also the SV head *, after being delinked/removed from an areana, can now be stored through the whole function, in the x86 EAX/x64 RAX register, and pass through to the caller, without a final (non vol) reg to (vol retval reg) mov/copy cpu op. Remember eax/rax/retval registers, are always wiped after each fn call, but the refactoring of SvTAINTTC() conviently returns the SV * back to us, in the ABI return register, and we let the fresh SV * glide through on the "heavy" Perl_sv_taint() branch, from Perl_sv_taint() to Perl_newSViv()'s caller, without touching it, 0 machine code ops. Few code sites were changed from SvTAINT() to SvTAINTTC(), to keep this patch smaller, and the Perl_sv_set*vXXX() category of functions, all have void return types and can't be chained. Also the Perl_sv_taint() branch can be tail called or converted to a JMP insted of CALL, if the CC/OS/ABI wants to now. This is the final part of speeding up Perl_newSVnv/Perl_newSViv/Perl_newSVuv there is nothing else to remove or optimze. --- hv.c | 4 ++-- sv.c | 6 +++--- sv.h | 18 ++++++++++++++++++ sv_inline.h | 2 +- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/hv.c b/hv.c index 7eaf6fc97063..63e17c0a0e38 100644 --- a/hv.c +++ b/hv.c @@ -1130,12 +1130,12 @@ Perl_hv_scalar(pTHX_ HV *hv) if (u <= (UV)IV_MAX) { SvIV_set(sv, (IV)u); (void)SvIOK_only(sv); - SvTAINT(sv); + sv = SvTAINTTC(sv); } else { SvIV_set(sv, 0); SvUV_set(sv, u); (void)SvIOK_only_UV(sv); - SvTAINT(sv); + sv = SvTAINTTC(sv); } return sv; diff --git a/sv.c b/sv.c index f8e2d42c2da0..e19a4e7f7d1f 100644 --- a/sv.c +++ b/sv.c @@ -10037,7 +10037,7 @@ Perl_newSVnv(pTHX_ const NV n) SvNV_set(sv, n); #endif - SvTAINT(sv); + sv = SvTAINTTC(sv); return sv; } @@ -10073,7 +10073,7 @@ Perl_newSViv(pTHX_ const IV i) SET_SVANY_FOR_BODYLESS_IV(sv); sv->sv_u.svu_iv = i; - SvTAINT(sv); + sv = SvTAINTTC(sv); return sv; } @@ -10175,7 +10175,7 @@ Perl_newSVuv(pTHX_ const UV u) SET_SVANY_FOR_BODYLESS_IV(sv); sv->sv_u.svu_uv = u; - SvTAINT(sv); + sv = SvTAINTTC(sv); return sv; } diff --git a/sv.h b/sv.h index 4264c21a3470..7297632ac72c 100644 --- a/sv.h +++ b/sv.h @@ -1721,6 +1721,21 @@ inputs such as locale settings. C propagates that taintedness to the outputs of an expression in a pessimistic fashion; i.e., without paying attention to precisely which outputs are influenced by which inputs. +=cut + +=for apidoc Cm|SV* sv|SvTAINTTC|SV* sv +Identical to C, except optimized for for C compilers to do tail calls. +Incoming arg I will be returned as the retval of I. +The return value I pointer will be identical to the incoming +argument I pointer. Ex. I). This way if I is on, and +the slow path branch executes, which has an internal helper function, that +helper function returns the argument passed in, and C compilers can optimize +the slowpath branch to a tail call, or use less registers. This macro is mostly +intended to be used if C is the last or almost last statement +in the caller function, and the caller has a I return type, and will +return C's arg I, to its caller as a return value. Similar idea +to C. + =cut */ @@ -1739,6 +1754,9 @@ attention to precisely which outputs are influenced by which inputs. sv_taint(sv); \ } STMT_END +#define SvTAINTTC(sv) ((assert(TAINTING_get || !TAINT_get), \ + TAINT_AND_TAINTING_get) ? sv_taint((sv)) : (sv)) + /* =for apidoc_section $SV =for apidoc Am|char*|SvPV_force |SV* sv|STRLEN len diff --git a/sv_inline.h b/sv_inline.h index a0fe8ec870c2..d65c784ca677 100644 --- a/sv_inline.h +++ b/sv_inline.h @@ -985,7 +985,7 @@ Perl_sv_setpv_freshbuf(pTHX_ SV *const sv) (void)SvPOK_only_UTF8(sv); /* UTF-8 flag will be 0; This is used instead of 'SvPOK_only' because the other sv_setpv functions use it */ - SvTAINT(sv); + SvTAINTTC(sv); return SvPVX(sv); }