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

op.c: slim down const_av_xsub const_sv_xsub XSUB.h: add GetXSTARG() #23156

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

Conversation

bulk88
Copy link
Contributor

@bulk88 bulk88 commented Mar 25, 2025

-don't use XSRETURN() macros, they use "unit of 1" relative offset "ax"
and constantly reread global my_parl->Istack_base and constant rescale
ax from unit of 1 to unit of 4/8
-don't use ST() macros for the same reason
-in const_sv_xsub() use XSTARG if its available, but just put our long
life SV* right on the PL stack if we can't write directly into the
caller lval SV*. Don't do "sv_setsv(sv_newmortal(), ssv);" on missing
XSTARG branch. Don't use dXSTARG; 50% chance there will be a 2nd!!!
secret "sv_setsv(sv_newmortal(),rval)" or "newSVsv(rval)" right after
this XSUB anyways, so just pass our SV* on stack instead of TWO
"sv_setsv(sv_newmortal(), ssv);" statements executing in a row.

const_av_xsub():
-if we will croak, do it ASAP once the minimum amount of data has been
read from global memory, AV* is delivered through C function argument
CV* cv, its not from the PL stack. So do the check and execute the
no return before creating/reading/writing a ton of PL stack related
global vars and C auto vars.
-GetXSTARG() and GIMME_V() both dig inside PL_op, keep them together w/o
any func calls in between such as EXTEND() so the CC can read OP* stored
in PL_op only once
-break apart Copy()'s overflow bounds checks so we can write a new "length"
to global state before copying the large in bytes array, historically
Perl has issues with letting PP end users code to keep running for severe
overflows/heap corruption/CVE type stuff, eval{}, %SIG, tied, MG,
sub END, etc. So do the asserts early before the actual memcpy or PUTBACK.
-handle an empty/0 elems long AV* better, don't EXTEND(0), don't call
extern libc memcpy with 0 size
-don't keep re-reading the AV head and AV body and AvFILLp(av) over and
over, func calls EXTEND() and memcpy() won't realloc the AV body ptr or
modify the AvFILL member in the body struct

XSUB.h:

-add a version of dXSTARG where the user handles what to do, if parent
frame didn't supply a SV* TARG for lval filling. This gets rid of the
inefficient sv_newmortal() that is forced on users when there almost
always better faster recipie of how to create a 0, 1, or G_LIST PL
stack retval. &PL_sv_undef, newSVpvn_flags(SVs_TEMP),
sv_2mortal(newSViv()), return your hash key's value SV* directly, etc.
Macro undocumented until further notice, so it can gather some unofficial
usage/CORE usage and some opinions regarding is it good or flawed.


The POD for macro GetXSTARG() was already written in this PR, it just not being made public ATM but its POD already exists if it becomes public one day.


  • This set of changes does not require a perldelta entry.

PR doesn't add public API.

op.c Outdated
Comment on lines 16292 to 16294
U8 gm;
SV * retsv;
SSize_t av_cur;
Copy link
Contributor

Choose a reason for hiding this comment

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

These should all be defined at or closer to point of first use.

XSUB.h Outdated
Comment on lines 184 to 274
/* A faster, more efficient variant of C<dXSTARG>. Similar to the optree's
GETTARGET, but "specialized" for XSUBs written by core or written by CPAN.
Do not evaluate this macro multiple times. Save the result of this macro to
a C<SV*> var. You must test the returned value for C<NULL> and procede
accordingly. Do not make any assumptions on why did or did not get NULL
from this macro. This macro is not a substitute for using L<GIMME_V>.
The non-NULL or NULL result of this macro has no correlation to what
C<@_> context, the caller PP/XS sub, has requested from your XSUB through
C<GIMME_V>.

Assume C<GIMME_V> can return <G_VOID> while at the same time C<GetXSTARG>
returns non-NULL. Also assume C<if (!(sv = GetXSTARG()) && GIMME_V == G_SCALAR)>
can happen and therefore you very likely will need to allocate a new C<SV*>
and mortalize it. It is discouraged and probably a bug, for an XSUB to
bump the C<SvREFCNT(sv)> on C<TARG> and save the C<SV*> for later use.
Do not make assumptions about C<TARG>'s C<SvREFCNT>, or what is the outer
container that really the C<SV*>. Something else inside the interpreter
which is unspecified, owns C<SV* TARG>, and unspecified caller, probably
wants you to write into this C<SV*> as an lval, vs you doing a less
efficient C<sv_newmortal()>/C<sv_2mortal(newSVxxxv())>, and later on the
unspecified caller has to call <sv_setsv()>, and let the mortal stack dispose
of your short lived <SV*>.

Although this is undocumented and private to the interpreter and you may not
write code that is aware of this private implementation detail. Keep in
mind the interpreter uses the C<SV* TARG> concept for both input and/or output
in various places between parts of itself and might be using C<SV* TARG> as
lvalue scratch pad in a loop.

Remember that the C<SV*> from C<dXSTARG> or C<GetXSTARG>, might be C<SvOK()>
and have stale prior contents that you need to wipe or free. C<sv_setxxx()>
functions will always do this for you. There is no guarentee the <SV*>
from C<dXSTARG> or C<GetXSTARG> will be set to C<undef> when you get it.
If you need to return C<undef>, you have 2 choices. Don't fetch and
don't use C<TARG>, and push C<&PL_sv_undef> on the stack. The other choices
you have is to call, sorted most efficient to least efficient:

sv_setsv_undef(my_targ); SvSETMAGIC(my_targ);
sv_setpv_mg(my_targ, NULL);
sv_setsv_mg(my_targ, NULL);
sv_setsv_mg(my_targ, &PL_sv_undef); //more readable

Also consider, there is no clear guidance for this. Do you think you the
PP or XS caller, that called your XSUB, if it is interested in getting a
C<@_> return value in the first place. Is the caller going to write it as
a true/false check, like C<if(do_xsub()) {0;}>, or will it write
C<my $result = do_xsub();> and capture your return value for future use.
The first probably don't set up a TARG for your to use. The 2nd probably
will, but there are no guarentees it will set one up ahead of time.

Returning address C<&PL_sv_undef> is much faster than C<sv_newmortal()> or
C<sv_set_undef()>. C<sv_set_undef()> is faster than the caller later on
doing a C<sv_setsv()>. C<sv_setsv()> has a quick bailout shortcut in it
if src and dest C<SV*>s are the same addr.

There is also no guarentee about what its C<SvTYPE()> is.
Always assume it is of type <SVt_NULL>, and it has no SV body until you
you test its type and possibly call C<SvUPGRADE> or <sv_setiv>/C<sv_setpvn>
on it. There is no guarentee C<SvANY()> is non-NULL or C<SvANY()> contains
a valid address or points to initialized memory. There is no guarentee
C<SvTYPE()> is at minimum C<SVt_IV> and reading C<SvIVX()> won't SEGV. */

Copy link
Contributor

Choose a reason for hiding this comment

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

Way too much. Just say what it does, mention the SV may not be fresh and you're done.

Any more belongs in pod/something.pod, somewhere.

If this is intended for use only by core it should be guarded by #ifdef PERL_CORE.

Copy link
Contributor Author

@bulk88 bulk88 Mar 27, 2025

Choose a reason for hiding this comment

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

Way too much. Just say what it does, mention the SV may not be fresh and you're done.

Agree. Revision 1's api desc is too many bytes getting sent through the CPP and too many bytes to PgDn through.

Revision 2 inside XSUB.h, on my side is currently

/* A faster, more efficient variant of C<dXSTARG>.  Similar to the optree's
   GETTARGET, but "specialized" for XSUBs written by core or written by CPAN.
   The benefit of C<GetXSTARG> over C<dXSTARG> is that C<GetXSTARG> will return
   C<NULL> if a targ C<SV *> isn't currently available and lets the user decide
   how to go forward.  Meanwhile C<dXSTARG> will always internally call
   C<sv_newmortal()> if a targ C<SV *> isn't available at that moment.
   Do not evaluate this macro multiple times.  Save the result of this macro to
   a C<SV*> var.

   Just like C<dXSTARG>, the C<SV *> returned by C<GetXSTARG> may have stale
   prior contents in it. */

Any more belongs in pod/something.pod, somewhere.

Agree.

If this is intended for use only by core it should be guarded by #ifdef PERL_CORE.

Agree. I want to see other ppl usage before calling something public API. My definition of "other people usage" is a minimum of 1 other person somewhere typing it in and clicking save. My api doc is written in a way, that Im leaving a provision, that macro GetXSTARG() could become a static inline or a libperl exported function in the future if there is some reason to do so.

GIMME_V used to be a horrible multi eval mouse trap perl 5.1X era. Its been optimized to a macro/fn call free inline in modern perl. CvGV() and GvSV() used to be fast func call free macros in 5.8 and older. In modern perl they are horrible multi eval mouse traps (vivifiers/malloc/getter methods). Dangerous ultra-fast macros, use-brain-thinking-required fast macros/fast static inlines, and full service heavy weight exported functions all need to be labeled and documented correctly from day 1. Which one causes subtle heap corruption and SEGVs, and which one tells you through STDERR $@ what you did wrong, every person needs to know that ahead of time.

Do you or anyone else know what file to hide the pod I wrote in? I want it to be inside pod/perlintern.pod, but that file can't be hand edited, and I don't want the CPP to see my pod text. I straced autodoc.pl but I still can't find anywhere to put my pod text. If I put it in a .h or .c, the CPP will see it, no good. If I put it in perlguts.pod, now its public API, no good. pod/perlhack.pod looks like someone talking while sipping a beer. Its writing style is edutainment or learning to code in C by watching Instagram videos. Its my last resort .pod file wise where to put a formal API description.

Maybe this GH PR is enough "POD" just by itself since P5P's GH bug tracker is a perm un-deleteable archive just like RT was? Correct?

I'm not sure if your quote above will loose its code citation to my "failed" commit, when I delete or repush the commit/branch on my side.

strace log from autodoc.pl. Click to Expand. ``` C:\sources\perl5\amigaos4 C:\sources\perl5\amigaos4\amigaio.c C:\sources\perl5\amigaos4\amigaio.h C:\sources\perl5\amigaos4\amigaos.c C:\sources\perl5\amigaos4\amigaos.h C:\sources\perl5\autodoc.pl C:\sources\perl5\av.c C:\sources\perl5\av.h C:\sources\perl5\builtin.c C:\sources\perl5\caretx.c C:\sources\perl5\class.c C:\sources\perl5\cop.h C:\sources\perl5\cpan\AutoLoader\lib\HeaderParser.pm C:\sources\perl5\cpan\ExtUtils-Constant\lib\HeaderParser.pm C:\sources\perl5\cpan\ExtUtils-Install\lib\HeaderParser.pm C:\sources\perl5\cpan\ExtUtils-MakeMaker\lib\HeaderParser.pm C:\sources\perl5\cpan\ExtUtils-Manifest\lib\HeaderParser.pm C:\sources\perl5\cpan\ExtUtils-PL2Bat\lib\HeaderParser.pm C:\sources\perl5\cpan\File-Path\lib\HeaderParser.pm C:\sources\perl5\cpan\Getopt-Long\lib\HeaderParser.pm C:\sources\perl5\cpan\parent\lib\HeaderParser.pm C:\sources\perl5\cpan\Text-ParseWords\lib\HeaderParser.pm C:\sources\perl5\cpan\Text-Tabs\lib\HeaderParser.pm C:\sources\perl5\cpan\version\lib\HeaderParser.pm C:\sources\perl5\cv.h C:\sources\perl5\cygwin C:\sources\perl5\cygwin\cygwin.c C:\sources\perl5\deb.c C:\sources\perl5\dist C:\sources\perl5\dist\base\lib\HeaderParser.pm C:\sources\perl5\dist\Carp\lib\HeaderParser.pm C:\sources\perl5\dist\constant\lib\HeaderParser.pm C:\sources\perl5\dist\Exporter\lib\HeaderParser.pm C:\sources\perl5\dist\ExtUtils-ParseXS C:\sources\perl5\dist\ExtUtils-ParseXS\lib C:\sources\perl5\dist\ExtUtils-ParseXS\lib\HeaderParser.pm C:\sources\perl5\dist\ExtUtils-ParseXS\lib\perlxs.pod C:\sources\perl5\dist\PathTools\HeaderParser.pm C:\sources\perl5\dist\PathTools\lib\HeaderParser.pm C:\sources\perl5\dist\Term-ReadLine\lib\HeaderParser.pm C:\sources\perl5\doio.c C:\sources\perl5\doop.c C:\sources\perl5\dosish.h C:\sources\perl5\dquote.c C:\sources\perl5\dump.c C:\sources\perl5\ebcdic_tables.h C:\sources\perl5\embed.fnc C:\sources\perl5\embed.h C:\sources\perl5\embedvar.h C:\sources\perl5\EXTERN.h C:\sources\perl5\ext\File-Find\lib\HeaderParser.pm C:\sources\perl5\ext\re\HeaderParser.pm C:\sources\perl5\fakesdio.h C:\sources\perl5\feature.h C:\sources\perl5\form.h C:\sources\perl5\generate_uudmap.c C:\sources\perl5\globals.c C:\sources\perl5\gv.c C:\sources\perl5\gv.h C:\sources\perl5\haiku C:\sources\perl5\haiku\haikuish.h C:\sources\perl5\handy.h C:\sources\perl5\HeaderParser.pm C:\sources\perl5\hints C:\sources\perl5\hints\t001.c C:\sources\perl5\hv.c C:\sources\perl5\hv.h C:\sources\perl5\hv_func.h C:\sources\perl5\hv_macro.h C:\sources\perl5\inline.h C:\sources\perl5\INTERN.h C:\sources\perl5\intrpvar.h C:\sources\perl5\invlist_inline.h C:\sources\perl5\iperlsys.h C:\sources\perl5\keywords.c C:\sources\perl5\keywords.h C:\sources\perl5\l1_char_class_tab.h C:\sources\perl5\lib C:\sources\perl5\lib\buildcustomize.pl C:\sources\perl5\lib\Carp.pm C:\sources\perl5\lib\Config.pm C:\sources\perl5\lib\constant.pm C:\sources\perl5\lib\CORE.pod C:\sources\perl5\lib\DynaLoader.pm C:\sources\perl5\lib\Exporter C:\sources\perl5\lib\Exporter.pm C:\sources\perl5\lib\Exporter\Heavy.pm C:\sources\perl5\lib\Fcntl.pm C:\sources\perl5\lib\File C:\sources\perl5\lib\File\Compare.pm C:\sources\perl5\lib\HeaderParser.pm C:\sources\perl5\lib\integer.pm C:\sources\perl5\lib\Internals.pod C:\sources\perl5\lib\overloading.pm C:\sources\perl5\lib\re.pm C:\sources\perl5\lib\Storable.pm C:\sources\perl5\lib\strict.pm C:\sources\perl5\lib\Symbol.pm C:\sources\perl5\lib\Text C:\sources\perl5\lib\Text\Tabs.pm C:\sources\perl5\lib\Text\Wrap.pm C:\sources\perl5\lib\vars.pm C:\sources\perl5\lib\warnings C:\sources\perl5\lib\warnings.pm C:\sources\perl5\lib\warnings\register.pm C:\sources\perl5\lib\XSLoader.pm C:\sources\perl5\locale.c C:\sources\perl5\locale_table.h C:\sources\perl5\malloc.c C:\sources\perl5\malloc_ctl.h C:\sources\perl5\MANIFEST C:\sources\perl5\mathoms.c C:\sources\perl5\metaconfig.h C:\sources\perl5\mg.c C:\sources\perl5\mg.h C:\sources\perl5\mg_raw.h C:\sources\perl5\mg_vtable.h C:\sources\perl5\miniperl.exe C:\sources\perl5\miniperl.exe.Local C:\sources\perl5\miniperlmain.c C:\sources\perl5\mro_core.c C:\sources\perl5\mydtrace.h C:\sources\perl5\nostdio.h C:\sources\perl5\numeric.c C:\sources\perl5\op.c C:\sources\perl5\op.h C:\sources\perl5\opcode.h C:\sources\perl5\opnames.h C:\sources\perl5\op_reg_common.h C:\sources\perl5\os2 C:\sources\perl5\os2\dlfcn.h C:\sources\perl5\os2\dl_os2.c C:\sources\perl5\os2\OS2 C:\sources\perl5\os2\os2.c C:\sources\perl5\os2\os2ish.h C:\sources\perl5\os2\os2thread.h C:\sources\perl5\os2\OS2\OS2-ExtAttr C:\sources\perl5\os2\OS2\OS2-ExtAttr\myea.h C:\sources\perl5\os2\perlrexx.c C:\sources\perl5\overload.h C:\sources\perl5\pad.c C:\sources\perl5\pad.h C:\sources\perl5\parser.h C:\sources\perl5\patchlevel.h C:\sources\perl5\peep.c C:\sources\perl5\perl.c C:\sources\perl5\perl.h C:\sources\perl5\perlapi.h C:\sources\perl5\perlio.c C:\sources\perl5\perlio.h C:\sources\perl5\perliol.h C:\sources\perl5\perlsdio.h C:\sources\perl5\perlstatic.h C:\sources\perl5\perlvars.h C:\sources\perl5\perly.c C:\sources\perl5\perly.h C:\sources\perl5\perl_inc_macro.h C:\sources\perl5\perl_langinfo.h C:\sources\perl5\perl_siphash.h C:\sources\perl5\plan9 C:\sources\perl5\plan9\arpa C:\sources\perl5\plan9\arpa\inet.h C:\sources\perl5\plan9\math.h C:\sources\perl5\plan9\plan9.c C:\sources\perl5\plan9\plan9ish.h C:\sources\perl5\pod C:\sources\perl5\pod\perl.pod C:\sources\perl5\pod\perl5004delta.pod C:\sources\perl5\pod\perl5005delta.pod C:\sources\perl5\pod\perl5100delta.pod C:\sources\perl5\pod\perl5101delta.pod C:\sources\perl5\pod\perl5120delta.pod C:\sources\perl5\pod\perl5121delta.pod C:\sources\perl5\pod\perl5122delta.pod C:\sources\perl5\pod\perl5123delta.pod C:\sources\perl5\pod\perl5124delta.pod C:\sources\perl5\pod\perl5125delta.pod C:\sources\perl5\pod\perl5140delta.pod C:\sources\perl5\pod\perl5141delta.pod C:\sources\perl5\pod\perl5142delta.pod C:\sources\perl5\pod\perl5143delta.pod C:\sources\perl5\pod\perl5144delta.pod C:\sources\perl5\pod\perl5160delta.pod C:\sources\perl5\pod\perl5161delta.pod C:\sources\perl5\pod\perl5162delta.pod C:\sources\perl5\pod\perl5163delta.pod C:\sources\perl5\pod\perl5180delta.pod C:\sources\perl5\pod\perl5181delta.pod C:\sources\perl5\pod\perl5182delta.pod C:\sources\perl5\pod\perl5184delta.pod C:\sources\perl5\pod\perl5200delta.pod C:\sources\perl5\pod\perl5201delta.pod C:\sources\perl5\pod\perl5202delta.pod C:\sources\perl5\pod\perl5203delta.pod C:\sources\perl5\pod\perl5220delta.pod C:\sources\perl5\pod\perl5221delta.pod C:\sources\perl5\pod\perl5222delta.pod C:\sources\perl5\pod\perl5223delta.pod C:\sources\perl5\pod\perl5224delta.pod C:\sources\perl5\pod\perl5240delta.pod C:\sources\perl5\pod\perl5241delta.pod C:\sources\perl5\pod\perl5242delta.pod C:\sources\perl5\pod\perl5243delta.pod C:\sources\perl5\pod\perl5244delta.pod C:\sources\perl5\pod\perl5260delta.pod C:\sources\perl5\pod\perl5261delta.pod C:\sources\perl5\pod\perl5262delta.pod C:\sources\perl5\pod\perl5263delta.pod C:\sources\perl5\pod\perl5280delta.pod C:\sources\perl5\pod\perl5281delta.pod C:\sources\perl5\pod\perl5282delta.pod C:\sources\perl5\pod\perl5283delta.pod C:\sources\perl5\pod\perl5300delta.pod C:\sources\perl5\pod\perl5301delta.pod C:\sources\perl5\pod\perl5302delta.pod C:\sources\perl5\pod\perl5303delta.pod C:\sources\perl5\pod\perl5320delta.pod C:\sources\perl5\pod\perl5321delta.pod C:\sources\perl5\pod\perl5340delta.pod C:\sources\perl5\pod\perl5341delta.pod C:\sources\perl5\pod\perl5342delta.pod C:\sources\perl5\pod\perl5343delta.pod C:\sources\perl5\pod\perl5360delta.pod C:\sources\perl5\pod\perl5361delta.pod C:\sources\perl5\pod\perl5362delta.pod C:\sources\perl5\pod\perl5363delta.pod C:\sources\perl5\pod\perl5380delta.pod C:\sources\perl5\pod\perl5381delta.pod C:\sources\perl5\pod\perl5382delta.pod C:\sources\perl5\pod\perl5383delta.pod C:\sources\perl5\pod\perl5400delta.pod C:\sources\perl5\pod\perl5401delta.pod C:\sources\perl5\pod\perl5410delta.pod C:\sources\perl5\pod\perl5411delta.pod C:\sources\perl5\pod\perl5412delta.pod C:\sources\perl5\pod\perl5413delta.pod C:\sources\perl5\pod\perl5414delta.pod C:\sources\perl5\pod\perl5415delta.pod C:\sources\perl5\pod\perl5416delta.pod C:\sources\perl5\pod\perl5417delta.pod C:\sources\perl5\pod\perl5418delta.pod C:\sources\perl5\pod\perl5419delta.pod C:\sources\perl5\pod\perl561delta.pod C:\sources\perl5\pod\perl56delta.pod C:\sources\perl5\pod\perl581delta.pod C:\sources\perl5\pod\perl582delta.pod C:\sources\perl5\pod\perl583delta.pod C:\sources\perl5\pod\perl584delta.pod C:\sources\perl5\pod\perl585delta.pod C:\sources\perl5\pod\perl586delta.pod C:\sources\perl5\pod\perl587delta.pod C:\sources\perl5\pod\perl588delta.pod C:\sources\perl5\pod\perl589delta.pod C:\sources\perl5\pod\perl58delta.pod C:\sources\perl5\pod\perlapi.pod C:\sources\perl5\pod\perlapi.pod-new C:\sources\perl5\pod\perlapio.pod C:\sources\perl5\pod\perlartistic.pod C:\sources\perl5\pod\perlbook.pod C:\sources\perl5\pod\perlcall.pod C:\sources\perl5\pod\perlcheat.pod C:\sources\perl5\pod\perlclass.pod C:\sources\perl5\pod\perlclassguts.pod C:\sources\perl5\pod\perlclib.pod C:\sources\perl5\pod\perlcommunity.pod C:\sources\perl5\pod\perldata.pod C:\sources\perl5\pod\perldbmfilter.pod C:\sources\perl5\pod\perldebguts.pod C:\sources\perl5\pod\perldebtut.pod C:\sources\perl5\pod\perldebug.pod C:\sources\perl5\pod\perldelta.pod C:\sources\perl5\pod\perldeprecation.pod C:\sources\perl5\pod\perldiag.pod C:\sources\perl5\pod\perldocstyle.pod C:\sources\perl5\pod\perldsc.pod C:\sources\perl5\pod\perldtrace.pod C:\sources\perl5\pod\perlebcdic.pod C:\sources\perl5\pod\perlembed.pod C:\sources\perl5\pod\perlexperiment.pod C:\sources\perl5\pod\perlfilter.pod C:\sources\perl5\pod\perlfork.pod C:\sources\perl5\pod\perlform.pod C:\sources\perl5\pod\perlfunc.pod C:\sources\perl5\pod\perlgit.pod C:\sources\perl5\pod\perlgov.pod C:\sources\perl5\pod\perlgpl.pod C:\sources\perl5\pod\perlguts.pod C:\sources\perl5\pod\perlhack.pod C:\sources\perl5\pod\perlhacktips.pod C:\sources\perl5\pod\perlhacktut.pod C:\sources\perl5\pod\perlhist.pod C:\sources\perl5\pod\perlintern.pod C:\sources\perl5\pod\perlintern.pod-new C:\sources\perl5\pod\perlinterp.pod C:\sources\perl5\pod\perlintro.pod C:\sources\perl5\pod\perliol.pod C:\sources\perl5\pod\perlipc.pod C:\sources\perl5\pod\perllexwarn.pod C:\sources\perl5\pod\perllocale.pod C:\sources\perl5\pod\perllol.pod C:\sources\perl5\pod\perlmod.pod C:\sources\perl5\pod\perlmodinstall.pod C:\sources\perl5\pod\perlmodstyle.pod C:\sources\perl5\pod\perlmroapi.pod C:\sources\perl5\pod\perlnewmod.pod C:\sources\perl5\pod\perlnumber.pod C:\sources\perl5\pod\perlobj.pod C:\sources\perl5\pod\perlootut.pod C:\sources\perl5\pod\perlop.pod C:\sources\perl5\pod\perlopentut.pod C:\sources\perl5\pod\perlpacktut.pod C:\sources\perl5\pod\perlperf.pod C:\sources\perl5\pod\perlpod.pod C:\sources\perl5\pod\perlpodspec.pod C:\sources\perl5\pod\perlpodstyle.pod C:\sources\perl5\pod\perlpolicy.pod C:\sources\perl5\pod\perlport.pod C:\sources\perl5\pod\perlpragma.pod C:\sources\perl5\pod\perlre.pod C:\sources\perl5\pod\perlreapi.pod C:\sources\perl5\pod\perlrebackslash.pod C:\sources\perl5\pod\perlrecharclass.pod C:\sources\perl5\pod\perlref.pod C:\sources\perl5\pod\perlreftut.pod C:\sources\perl5\pod\perlreguts.pod C:\sources\perl5\pod\perlrequick.pod C:\sources\perl5\pod\perlreref.pod C:\sources\perl5\pod\perlretut.pod C:\sources\perl5\pod\perlrun.pod C:\sources\perl5\pod\perlsec.pod C:\sources\perl5\pod\perlsecpolicy.pod C:\sources\perl5\pod\perlsource.pod C:\sources\perl5\pod\perlstyle.pod C:\sources\perl5\pod\perlsub.pod C:\sources\perl5\pod\perlsyn.pod C:\sources\perl5\pod\perlthrtut.pod C:\sources\perl5\pod\perltie.pod C:\sources\perl5\pod\perltrap.pod C:\sources\perl5\pod\perlunicode.pod C:\sources\perl5\pod\perlunicook.pod C:\sources\perl5\pod\perlunifaq.pod C:\sources\perl5\pod\perluniintro.pod C:\sources\perl5\pod\perlunitut.pod C:\sources\perl5\pod\perlutil.pod C:\sources\perl5\pod\perlvar.pod C:\sources\perl5\pod\perlvms.pod C:\sources\perl5\Porting C:\sources\perl5\Porting\docs-team-charter.pod C:\sources\perl5\Porting\epigraphs.pod C:\sources\perl5\Porting\how_to_write_a_perldelta.pod C:\sources\perl5\Porting\perldelta_template.pod C:\sources\perl5\Porting\pumpkin.pod C:\sources\perl5\Porting\README.pod C:\sources\perl5\Porting\release_managers_guide.pod C:\sources\perl5\Porting\release_schedule.pod C:\sources\perl5\Porting\security_template.pod C:\sources\perl5\Porting\timecheck.c C:\sources\perl5\Porting\timecheck2.c C:\sources\perl5\Porting\todo.pod C:\sources\perl5\Porting\vote_admin_guide.pod C:\sources\perl5\pp.c C:\sources\perl5\pp.h C:\sources\perl5\pp_ctl.c C:\sources\perl5\pp_hot.c C:\sources\perl5\pp_pack.c C:\sources\perl5\pp_proto.h C:\sources\perl5\pp_sort.c C:\sources\perl5\pp_sys.c C:\sources\perl5\proto.h C:\sources\perl5\qnx C:\sources\perl5\qnx\qnx.c C:\sources\perl5\reentr.c C:\sources\perl5\reentr.h C:\sources\perl5\regcharclass.h C:\sources\perl5\regcomp.c C:\sources\perl5\regcomp.h C:\sources\perl5\regcomp_debug.c C:\sources\perl5\regcomp_internal.h C:\sources\perl5\regcomp_invlist.c C:\sources\perl5\regcomp_study.c C:\sources\perl5\regcomp_trie.c C:\sources\perl5\regen C:\sources\perl5\regen\embed_lib.pl C:\sources\perl5\regen\HeaderParser.pm C:\sources\perl5\regen\opcodes C:\sources\perl5\regen\regen_lib.pl C:\sources\perl5\regexec.c C:\sources\perl5\regexp.h C:\sources\perl5\regexp_constants.h C:\sources\perl5\reginline.h C:\sources\perl5\regnodes.h C:\sources\perl5\run.c C:\sources\perl5\sbox32_hash.h C:\sources\perl5\scope.c C:\sources\perl5\scope.h C:\sources\perl5\scope_types.h C:\sources\perl5\sv.c C:\sources\perl5\sv.h C:\sources\perl5\sv_inline.h C:\sources\perl5\t C:\sources\perl5\taint.c C:\sources\perl5\thread.h C:\sources\perl5\time64.c C:\sources\perl5\time64.h C:\sources\perl5\time64_config.h C:\sources\perl5\toke.c C:\sources\perl5\t\lib C:\sources\perl5\t\lib\h2ph.h C:\sources\perl5\unicode_constants.h C:\sources\perl5\universal.c C:\sources\perl5\unixish.h C:\sources\perl5\uni_keywords.h C:\sources\perl5\utf8.c C:\sources\perl5\utf8.h C:\sources\perl5\utfebcdic.h C:\sources\perl5\util.c C:\sources\perl5\util.h C:\sources\perl5\vms C:\sources\perl5\vms\munchconfig.c C:\sources\perl5\vms\vms.c C:\sources\perl5\vms\vmsish.h C:\sources\perl5\vos C:\sources\perl5\vos\vos.c C:\sources\perl5\vos\vosish.h C:\sources\perl5\vutil.c C:\sources\perl5\vutil.h C:\sources\perl5\warnings.h C:\sources\perl5\win32 C:\sources\perl5\win32\configure C:\sources\perl5\win32\configure\rt.c C:\sources\perl5\win32\fcrypt.c C:\sources\perl5\win32\full C:\sources\perl5\win32\full\config.h C:\sources\perl5\win32\include C:\sources\perl5\win32\include\arpa C:\sources\perl5\win32\include\arpa\inet.h C:\sources\perl5\win32\include\dirent.h C:\sources\perl5\win32\include\netdb.h C:\sources\perl5\win32\include\sys C:\sources\perl5\win32\include\sys\errno2.h C:\sources\perl5\win32\include\sys\socket.h C:\sources\perl5\win32\perlglob.c C:\sources\perl5\win32\perlhost.h C:\sources\perl5\win32\perllib.c C:\sources\perl5\win32\runperl.c C:\sources\perl5\win32\vdir.h C:\sources\perl5\win32\vmem.h C:\sources\perl5\win32\win32.c C:\sources\perl5\win32\win32.h C:\sources\perl5\win32\win32iop.h C:\sources\perl5\win32\win32sck.c C:\sources\perl5\win32\win32thread.c C:\sources\perl5\win32\win32thread.h C:\sources\perl5\XSUB.h C:\sources\perl5\zaphod32_hash.h ```

@bulk88 bulk88 force-pushed the const_av_sv_xsub_slim_mach_code branch from 8240f0a to a42385e Compare March 28, 2025 12:55
-don't use XSRETURN() macros, they use "unit of 1" relative offset "ax"
 and constantly reread global my_parl->Istack_base and constant rescale
 ax from unit of 1 to unit of 4/8
-don't use ST() macros for the same reason
-in const_sv_xsub() use XSTARG if its available, but just put our long
 life SV* right on the PL stack if we can't write directly into the
 caller lval SV*. Don't do "sv_setsv(sv_newmortal(), ssv);" on missing
 XSTARG branch. Don't use dXSTARG; 50% chance there will be a 2nd!!!
 secret "sv_setsv(sv_newmortal(),rval)" or "newSVsv(rval)" right after
 this XSUB anyways, so just pass our SV* on stack instead of TWO
 "sv_setsv(sv_newmortal(), ssv);" statements executing in a row.

const_av_xsub():
-if we will croak, do it ASAP once the minimum amount of data has been
 read from global memory, AV* is delivered through C function argument
 CV* cv, its not from the PL stack. So do the check and execute the
 no return before creating/reading/writing a ton of PL stack related
 global vars and C auto vars.
-GetXSTARG() and GIMME_V() both dig inside PL_op, keep them together w/o
 any func calls in between such as EXTEND() so the CC can read OP* stored
 in PL_op only once
-break apart Copy()'s overflow bounds checks so we can write a new "length"
 to global state before copying the large in bytes array, historically
 Perl has issues with letting PP end users code to keep running for severe
 overflows/heap corruption/CVE type stuff, eval{}, %SIG, tied, MG,
 sub END, etc. So do the asserts early before the actual memcpy or PUTBACK.
-handle an empty/0 elems long AV* better, don't EXTEND(0), don't call
 extern libc memcpy with 0 size
-don't keep re-reading the AV head and AV body and AvFILLp(av) over and
 over, func calls EXTEND() and memcpy() won't realloc the AV body ptr or
 modify the AvFILL member in the body struct

XSUB.h:

-add a version of dXSTARG where the user handles what to do, if parent
 frame didn't supply a SV* TARG for lval filling.  This gets rid of the
 inefficient sv_newmortal() that is forced on users when there almost
 always better faster recipie of how to create a 0, 1, or G_LIST PL
 stack retval. &PL_sv_undef, newSVpvn_flags(SVs_TEMP),
 sv_2mortal(newSViv()), return your hash key's value SV* directly, etc.
 Macro undocumented until further notice, so it can gather some unofficial
 usage/CORE usage and some opinions regarding is it good or flawed.
@bulk88 bulk88 force-pushed the const_av_sv_xsub_slim_mach_code branch from a42385e to 36beb19 Compare March 28, 2025 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants