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

[doc] perlcall/perlguts encourage obsolete call_method() / call_pv() and deny most of call_sv()'s API #22804

Open
bulk88 opened this issue Dec 1, 2024 · 0 comments

Comments

@bulk88
Copy link
Contributor

bulk88 commented Dec 1, 2024

Where

blead perl 5.41.6's POD

Description

https://github.com/Perl/perl5/blob/342b57d68213add262954103c711be7d6ed0f128/pod/perlcall.pod

https://github.com/Perl/perl5/blob/342b57d68213add262954103c711be7d6ed0f128/pod/perlguts.pod

Encourage and promote inefficient and slower at runtime and already labeled as deprecated in perlapi.pod functions call_method(), call_pv(), and call_argv() (+ Perl_call_method() / etc). Its undocumented in perlcall/perlguts the max-perf func calls are call_sv(sv, 0); and call_sv(sv,G_METHOD_NAMED); and call_sv(sv,G_METHOD);. Every other variant a mathom, ancient CPAN XS compat, or handy shims for faster dev hacking/protoing but slower runtime. call_method() and call_pv() can be nuked/mathom doc tagged instantly as 1 line wrappers missing _pvs() _pvn() variants. call_argv() is a little different.

Also these 2 POD files are still living in Perl 5.001 era by denying call_sv() can suck in flags G_METHOD_NAMED (2012 added) / G_METHOD (2000 added 968b394 ). At 24 years old, macro G_METHOD is public API no matter what blead's docs say. Anyways ppport.h #defines macro G_METHOD if its missing so that implies its public forever. Perl < 5.6 has 0 advocates or users on WWW, including the tough critic typing this sentence right now. Note the crazy XS optree hack in fossil perl before 2000.

A troll could argue call_argv() might have legit handy functionality for private P5/XS embedders and can't be API DOC labeled as obsolete. Grepping metacpan.org shows 8 hits, and grepping all my .dll'es in strawberry 5.38 dir gives 0 hits for [Perl_] call_argv. Maybe nobody will miss func Perl_call_argv() if it disappears in stable Perl. P5P can easily copy Perl_call_argv() into ppport.h as a static fn that always disappears after the CC if a Perl user makes a complaint in a bug ticket.

In any case, the 2 POD files need fixing, "perfect" CPAN XS code, does not alloc and insta-free 100K or 1 million SVPV *s in a loop at runtime over 1 min/hr/day/months (FastCGI/PSGI/mod_perl). Or runtime call libc strlen() on RO mem C string literals.

Edit: I dont believe 5.000 alpha, 5.005, 5.6, 5.8-5.41, offer any API or tricks or JAPH tricks for PP subs or XSUBs to separate caller subs doing fake method calls with a SVRV in $_[0], from PP/XS callers doing formal method calls with G_METHOD flag. You can't prove a @isa lookup was really done 0.5 microseconds ago on your class or obj instance SVRV or not before you gained control in your method body.

Edit: Implement all 10/50/100 methods of your class inside sub AUTOLOAD {}, catch the amateur script kiddies finding your CPAN lib on a BBS and then calling your CPAN lib with fake method calls. This won't work in 1995, since after 2 weeks in 1995 your "users" have finished downloading the perl tarball and finally have access to POD files. Then they grow up and learn to make a SVRV to a CV in PP to your Acme:: module and you were defeated.

Edit: I believe if I do more research this was pulled off long ago on usenet or perlmonks. Sadly I think a GV* can't be tied with XS magic or TIEGLOB. But you can have you sub AUTOLOAD deleting its own package/HV stash each time during execution, and then rebless youro bj handle/the SVRV in $_[0] each time your, 1x executed ever and insta-deleted, sub AUTOLOAD, gains control.

Each sub AUTOLOAD will wipe its glob/stash/package from * main::, and immediately eval string a new instance itself (itself == sub AUTOLOAD), and rebless the SVRV in $_[0], into a new package containing a random GUID integer on the end. For ultimate protection against malicious callers, also monkey patch the caller's lexical with $_[0] = bless $self, 'MyClassIsMorePrivateThanAnyMilitarySrcCode';. Throw in a { my $i++}; somewhere, you will not win this war without breaking the laws of war, by whipping out padwalker or bespoke XS code. You will call my methroutine with PP hash deref operator or perish.

Update: this ticket was inspired by a SEGV yesterday, because I refcnt++ saved a CV* from get_cvn() in my XS mod's ::bootstrap() to my MY_CXT C global state, later on I crashed inside Perl_call_sv() by passing that CV* , that is still owned by me, inside my MY_CXT C struct. Somehow Perl_yylexer() or Perl_op_whatever() replaces "high level PP Perl 5 subroutines" on a GV * GP slot level, not a member by member struct cv_body level that is hanging off a CV* head. So I was left with a SEGVing "officially undef API state" or "uninit-byte filled UB API state" CV body struct. I fixed it by refcount bumping the GV*, and later optimized to lazy loading to MY_CXT global state in XS/C at runtime phase, post-use!!! post-BEGIN!!! phase. This way my <= .pm Line 15 statement require/use XSLoader -> myMod::bootstrap doesn't fight a war with yy_lexer/PP eval($string); filling in my class after myMod::bootstrap returns control.

Removed/optimized away quick-fix #1 of GV* refcnt bump and runtime GvCV() macro is unbenchmarkable fast/simple, since its 3x C lang -> struct deref operators, or 3 CPU machine ops with 3 fixed burned-into-mach-code const int offsets.

The runtime 1st use GV* lookup was safer than GV* refbump, since its a CPAN intended module and I have some features that integrate with other random other CPAN, and its upto the final end user if they want to use Some::Mod; or not. They don't even need to keep CPAN Some::Mod on their disk at all, I marked all downstream deps as BUILD_REQUIRES => {} for .t phase only. so 99% of users probably don't have Some::Mod on disk. Its user error to make a call to my module create and return a Some::Mod $obj, without the user previously loading Some::Mod themselves into the perl proc. What will they do with a Some::Mod $obj unless they read Some::Mod POD doc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant