Repository navigation
Conversation
…ls and several more features:
1) Added hashmap.h - extremely fast low-level C hash to use for perl code needs (see below).
2) Speeding up stash cache, make gv_stash* use the cache and by this make all of perl core and XS modules use
this cache, not only S_method_common.
- Change PL_stashcache from HV* to SVMAP* (hashmap of SVMAP_ENT values)
- The lowest-level function is now gv_stashent which receives precomputed hash64 value for class name
and searches the cache. If nothing found, calls slow S_gv_stashpvn (former Perl_gv_stashpvn) and
fills the cache.
- gv_stashpvn is now a wrapper for gv_stashent, computing hash value.
- add API functions to clear stash cache locally (1 class) and globally. Make use of them.
- added one more flag to gv_stash* - GV_CACHE_ONLY which returns stash only if found in cache,
otherwise NULL. Required for correct behaviour of rule "IO globs take precedence over class names".
- use private hash function PERL_HASH64 for computing hash values for class names. This function is
much faster than PERL_HASH function (especially for long keys, which is likely for full class names)
and returns a 64bit value. It doesn't use randomization because stash cache is a private core data,
not a user data.
3) Speeding up method cache and super method cache, make gv_fetchmeth*/gv_fetchmethod* use the cache.
- store method cache in meta->mro_method instead of package stash's HV itself.
- rename meta->mro_super -> meta->mro_supermethod
- meta->mro_method & meta->mro_supermethod are both SVMAP*
- The lowest-level function for gv_fetchmeth* is now gv_fetchmeth_ent which receives precomputed
hash value for method name.
- gv_fetchmeth_pvn is now a wrapper for gv_fetchmeth_ent, computing hash64 value.
- The lowest-level function for gv_fetchmethod* is now gv_fetchmethod_ent which receives precomputed
hash value for method name. Method cannot contain '::', gv_fetchmethod_ent doesn't search for '::'.
- gv_fetchmethod_pvn is now a wrapper for gv_fetchmethod_ent, searching for '::', changing method name
(and possibly stash, flags) and computing hash64 value.
- new flag for gv_fetchmethod_pvn - GV_METHOD_SIMPLE, which means gv_fetchmethod_pvn doesn't need to scan
for '::' in method name.
4) Precomputing hash64 values for perl code.
- added 2 more op types:
- OP_METHOD_SUPER "$proto->SUPER::func()"
- OP_METHOD_REDIR "$proto->OtherClass::func()" or "$proto->OtherClass::SUPER::func()"
- added new op struct type - struct methop (typedef METHOP).
It actually behaves like UNOP for OP_METHOD and like SVOP for OP_METHOD_* and fully compatible with
them for backward compability. It contains additional fields:
- hash for method name (for OP_METHOD_*). Method name SV and targ are still in ->op_sv and ->op_targ
- hash, sv and targ for class name (for all types)
- hash, sv and targ for redirect class name (for OP_METHOD_REDIR)
- ck_method detects const method name, fills hash and sv, and creates OP_METHOD_NAMED
- ck_method detects const method name with SUPER keyword, fills hash and sv, and creates OP_METHOD_SUPER
- ck_method detects const method name with class redirect (possibly with SUPER keyword),
fills hash, sv, rclass hash and rclass sv and creates OP_METHOD_REDIR
- ck_subr now detects if left operand is a const (MyClass->method()), and stores the data (class hash and sv)
in underlying OP_METHOD* op.
- all of these infos are used in runtime to greatly speedup pp_method* calls
5) OOP context for XSUBs.
Calculated stash HV of left operand (object/class/IO/etc) is now saved in PL_methstash for later use by XSUBS.
This prevents double caclucation of stash's HV for such functions as UNIVERSAL::can and so on and speeds up them
a lot.
Moreover it has one more usage: pp_entersub sets PL_methstash to NULL if CV is called as function, and sets
PL_methstash to object/class/IO/etc stash's HV if CV is called as class/object/etc method.
This makes it possible for XS code to detect if it is called as funtion or method in case if user wants to implement
separate behaviour for those cases.
For example if (PL_methstash) { ... called as method, object/class/etc stash is in PL_methstash }
else { ... called as function }
Additionaly for XSUBs like UNIVERSAL::can which always want to interpret its calls as method calls (i.e. first arg is
object/class/etc), there is a macro dMETHSTASH which defines variable 'HV* stash' and either sets it to PL_methstash
(if called as method) or (if called as function) calculate stash in the same way as pp_method* would do in case of
real method call.
Note that PL_methstash is not stacked (to not introduce any overheat), that means you have to either use it
before you made a new perl CV call or save it to a variable.
6) Bring B, B::Deparse and B::Concise in consistency with new ops.
7) misc:
- bugfix in Opcode.xs: _safe_call_sv (and therefore module Safe) had critical vulnerability
which made it possible for code in $safe->reval("...") to hack your entire program.
- Remove "local's" unneccesary overheat. ("local GLOB = GLOB" - OK, "local GLOB = CODEREF" - OVERHEAT)
{
local *MyClass::func = sub {...}; # LINE A
...
} # LINE B
This example caused global method cache reset at both lines A and B because glob_assign_ref and leave_scope
thought that GV's GP refcnt was 2 (because of saving to Save Stack).
Issue has been fixed (added gp_flags and new GP flag LOCALIZED, if flag is set then 1 refcnt from save stack is
not counted in gv_method_changed calls).
- bugfix in dump.c : sv_dump(stash) (where stash is HV* - someone's stash) crashes if stash has cached destructor -
sv_dump thought that it was a stash and tried to dump CV* as HV*.
- UNIVERSAL::can (in universal.c) is rewritten to make use of PL_methstash and runs much faster now.
Contributor
|
hi @syberrus, The perl developers don't use pull requests. Patches should be sent as RT tickets. I'd also advise you to split up this huge patch into smaller, self-contained ones which will be easier to review and apply. |
Contributor
Author
|
Unfortunately i can't split. Because data types of caches have changed, this leaded to a lot of changes in a lot of files. |
p5p
pushed a commit
that referenced
this pull request
Feb 19, 2016
This has large memory savings, test prog, perl -MTest::More -e"system 'pause'" before 2196KB Private Bytes Win 7 32 bit to after 2092KB. -On a CHEK the refcount is a U32 for memory savings on 64 bit CPUs while SHEKs are Size_t for refcount because of HE struct, on 32 bit Size_t and U32 happen to be the same thing, if there is future integration the refcount members will have to be the same type, then duping a SHEK or a CHEK is the same code, except that HVhek_COMPILING controls whether to aquire OP_REFCNT_LOCK before touching the ref count, in the future with atomic operations, the refcount can be manipulated with atomic operations regardless if it is a SHEK or CHEK since OP_REFCNT_LOCK lines were removed -TODO figure out how to do static const CHEKs, hash member must be 0 since its process specific randomized (rurban's B stores HEKs in RW static memory and fixes up the hash #s at runtime), add test and branch so that refcount isn't read and written or passed to PerlMemShared_free if static flag is on inidicating static const CHEK -TODO Perl_newGP uses CHEKs not CopFILE, no memcpy and add _< that way -TODO optimize the former alloca to smallbuf or Safefree or savestack newx free
p5p
pushed a commit
that referenced
this pull request
Feb 14, 2017
At this maximal level of debugging output, it displays the top 3 state
stack entries each time it pushes, but with no obvious indication that
a push is occurring. This commit changes this output:
| 1| Setting an EVAL scope, savestack=9,
| 2| #4 WHILEM_A_max
| 2| #3 WHILEM_A_max
| 2| #2 CURLYX_end yes
0 <abcdef> <g> | 2| 4:POSIXD[\w](5)
to be this (which includes the word "push" and extra indentation for the
stack dump):
| 1| Setting an EVAL scope, savestack=9,
| 2| push #4 WHILEM_A_max
| 2| #3 WHILEM_A_max
| 2| #2 CURLYX_end yes
0 <abcdef> <g> | 2| 4:POSIXD[\w](5)
Also, replace curd (current depth) var with a positive integer offset
(i) var, to avoid signed/unsigned mixing problems.
This was referenced Oct 18, 2019
Closed
Closed
Closed
Closed
Closed
Closed
atoomic
pushed a commit
that referenced
this pull request
Sep 16, 2020
[DELTA] 1.854 16 September 2020 * Prefer direct notation over indirect (#4) * Make hint/BS snippets strict compliant. * trim whitespace
demerphq
added a commit
that referenced
this pull request
Sep 9, 2022
demerphq
added a commit
that referenced
this pull request
Sep 9, 2022
demerphq
added a commit
that referenced
this pull request
Sep 12, 2022
demerphq
added a commit
that referenced
this pull request
Oct 25, 2022
demerphq
added a commit
that referenced
this pull request
Nov 5, 2022
demerphq
added a commit
that referenced
this pull request
Nov 5, 2022
demerphq
added a commit
that referenced
this pull request
Nov 5, 2022
demerphq
added a commit
that referenced
this pull request
Nov 5, 2022
demerphq
added a commit
that referenced
this pull request
Dec 31, 2022
khwilliamson
pushed a commit
to khwilliamson/perl5
that referenced
this pull request
Jan 30, 2023
export only necessary from POSIX (RT#99970)
demerphq
added a commit
that referenced
this pull request
Feb 8, 2023
demerphq
added a commit
that referenced
this pull request
Feb 19, 2023
demerphq
added a commit
that referenced
this pull request
Feb 20, 2023
This was referenced Dec 14, 2024
bulk88
added a commit
to bulk88/perl5
that referenced
this pull request
Apr 22, 2025
CC is MSVC 2022 x64 -O1. Before, 0x67 bytes long. After, 0x5E bytes long. This savings obtained by not digging inside PL_op AKA my_perl->Iop->op_*** twice, and the CC not having save a C auto var around a function call. I profiled Perl_pp_const() to be between Perl#2 to Perl#4 most executed pp_*() function, per process on any workload. For extra details about this commit see the GH PR associated with this commit. There is an alternative I privately prototyped but I decided not to finish 3/4s of the way which is creating pre/post arg eval variants of function/macro rpp_xpush_1(). It was getting too invasive and complex by lines of src code modified to finish, so that conceptual fix isn't done here, and something best left for the future.
iabyn
added a commit
that referenced
this pull request
Apr 24, 2025
This is #4 of a small series of commits to refactor the INPUT_handler() method and turn it into a Node subclass method. This commit reindents INPUT_handler() and INPUT_handler_line() from 2-indent to 4-indent to match the policy of the file they were moved to in the previous commit. Whitespace-only change
iabyn
added a commit
that referenced
this pull request
Apr 24, 2025
This is #4 of a small series of commits to refactor the OUTPUT_handler() method and turn it into a Node subclass method. This commit reindents OUTPUT_handler() and OUTPUT_handler_line() from 2-indent to 4-indent to match the policy of the file they were moved to in the previous commit. Whitespace-only change
iabyn
added a commit
that referenced
this pull request
May 26, 2025
This is #4 of a small series of commits to refactor the INPUT_handler() method and turn it into a Node subclass method. This commit reindents INPUT_handler() and INPUT_handler_line() from 2-indent to 4-indent to match the policy of the file they were moved to in the previous commit. Whitespace-only change
iabyn
added a commit
that referenced
this pull request
May 26, 2025
This is #4 of a small series of commits to refactor the OUTPUT_handler() method and turn it into a Node subclass method. This commit reindents OUTPUT_handler() and OUTPUT_handler_line() from 2-indent to 4-indent to match the policy of the file they were moved to in the previous commit. Whitespace-only change
iabyn
added a commit
that referenced
this pull request
Jul 6, 2025
This is #4 of a small series of commits to refactor the INPUT_handler() method and turn it into a Node subclass method. This commit reindents INPUT_handler() and INPUT_handler_line() from 2-indent to 4-indent to match the policy of the file they were moved to in the previous commit. Whitespace-only change
iabyn
added a commit
that referenced
this pull request
Jul 6, 2025
This is #4 of a small series of commits to refactor the OUTPUT_handler() method and turn it into a Node subclass method. This commit reindents OUTPUT_handler() and OUTPUT_handler_line() from 2-indent to 4-indent to match the policy of the file they were moved to in the previous commit. Whitespace-only change
mauke
pushed a commit
that referenced
this pull request
Oct 18, 2025
CC is MSVC 2022 x64 -O1. Before, 0x67 bytes long. After, 0x5E bytes long. This savings obtained by not digging inside PL_op AKA my_perl->Iop->op_*** twice, and the CC not having save a C auto var around a function call. I profiled Perl_pp_const() to be between #2 to #4 most executed pp_*() function, per process on any workload. For extra details about this commit see the GH PR associated with this commit. There is an alternative I privately prototyped but I decided not to finish 3/4s of the way which is creating pre/post arg eval variants of function/macro rpp_xpush_1(). It was getting too invasive and complex by lines of src code modified to finish, so that conceptual fix isn't done here, and something best left for the future.
tonycoz
added a commit
that referenced
this pull request
Sep 16, 2026
WARNING: ThreadSanitizer: thread leak (pid=59894)
Thread T1 (tid=6697764, finished) created by main thread at:
#0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x33834)
#1 XS_threads_create threads.xs:1292 (threads.bundle:arm64+0x2078)
#2 Perl_pp_goto pp_ctl.c:3691 (perl:arm64+0x1001764a4)
#3 Perl_runops_debug dump.c:3486 (perl:arm64+0x10009cf70)
#4 S_run_body perl.c (perl:arm64+0x10004ec6c)
#5 perl_run perl.c:2819 (perl:arm64+0x10004e964)
#6 main perlmain.c:127 (perl:arm64+0x100000910)
SUMMARY: ThreadSanitizer: thread leak threads.xs:1292 in XS_threads_create
tonycoz
added a commit
that referenced
this pull request
Sep 16, 2026
dist/threads/t/free.t was complaining:
WARNING: ThreadSanitizer: data race (pid=42840)
Read of size 8 at 0x00010d30dec0 by thread T5:
#0 S_ithread_dec_free threads.xs:333 (threads.bundle:arm64+0x95ac)
#1 ithread_mg_free threads.xs:474 (threads.bundle:arm64+0xa620)
#2 Perl_mg_free_struct mg.c:1089 (perl:arm64+0x1000da594)
#3 S_sv_unmagicext_flags sv.c:7034 (perl:arm64+0x1002aeae0)
#4 Perl_sv_unmagic sv.c:7061 (perl:arm64+0x1002aa540)
#5 XS_threads_DESTROY threads.xs:1664 (threads.bundle:arm64+0x4e20)
#6 Perl_pp_entersub pp_hot.c:6706 (perl:arm64+0x1001a7bcc)
#7 Perl_runops_debug dump.c:3486 (perl:arm64+0x10009d438)
#8 Perl_call_sv perl.c:3274 (perl:arm64+0x1000509a0)
#9 S_curse sv.c:8233 (perl:arm64+0x1002b33fc)
#10 Perl_sv_clear sv.c:7767 (perl:arm64+0x1002b15e8)
#11 Perl_sv_free2 sv.c:8337 (perl:arm64+0x1002b3bf8)
#12 Perl_leave_adjust_stacks pp_hot.c:6290 (perl:arm64+0x1001a4d84)
#13 Perl_pp_leavesub pp_hot.c:6321 (perl:arm64+0x1001a5528)
#14 Perl_runops_debug dump.c:3486 (perl:arm64+0x10009d438)
#15 Perl_call_sv perl.c:3274 (perl:arm64+0x1000509a0)
#16 S_jmpenv_run threads.xs:578 (threads.bundle:arm64+0x9a5c)
#17 S_ithread_run threads.xs:688 (threads.bundle:arm64+0x8b10)
Previous write of size 8 at 0x00010d30dec0 by thread T4 (mutexes: write M0):
#0 XS_threads_create threads.xs:1292 (threads.bundle:arm64+0x209c)
#1 Perl_pp_entersub pp_hot.c:6706 (perl:arm64+0x1001a7bcc)
#2 Perl_runops_debug dump.c:3486 (perl:arm64+0x10009d438)
#3 Perl_call_sv perl.c:3274 (perl:arm64+0x1000509a0)
#4 S_jmpenv_run threads.xs:578 (threads.bundle:arm64+0x9a5c)
#5 S_ithread_run threads.xs:688 (threads.bundle:arm64+0x8b10)
Location is heap block of size 176 at 0x00010d30dec0 allocated by thread T5:
#0 malloc <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x679b4)
#1 XS_threads_create threads.xs:1292 (threads.bundle:arm64+0x1a6c)
#2 Perl_pp_entersub pp_hot.c:6706 (perl:arm64+0x1001a7bcc)
#3 Perl_runops_debug dump.c:3486 (perl:arm64+0x10009d438)
#4 Perl_call_sv perl.c:3274 (perl:arm64+0x1000509a0)
#5 S_jmpenv_run threads.xs:578 (threads.bundle:arm64+0x9a5c)
#6 S_ithread_run threads.xs:688 (threads.bundle:arm64+0x8b10)
All other accesses to thread->next are protected by the
create_destruct_mutex, so this one should be too.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
...and several more features:
Added hashmap.h - extremely fast low-level C hash to use for perl code needs (see below).
Speeding up stash cache, make gv_stash* use the cache and by this make all of perl core and XS modules use
this cache, not only S_method_common.
and searches the cache. If nothing found, calls slow S_gv_stashpvn (former Perl_gv_stashpvn) and
fills the cache.
otherwise NULL. Required for correct behaviour of rule "IO globs take precedence over class names".
much faster than PERL_HASH function (especially for long keys, which is likely for full class names)
and returns a 64bit value. It doesn't use randomization because stash cache is a private core data,
not a user data.
Speeding up method cache and super method cache, make gv_fetchmeth_/gv_fetchmethod_ use the cache.
hash value for method name.
hash value for method name. Method cannot contain '::', gv_fetchmethod_ent doesn't search for '::'.
(and possibly stash, flags) and computing hash64 value.
for '::' in method name.
Precomputing hash64 values for perl code.
It actually behaves like UNOP for OP_METHOD and like SVOP for OP_METHOD_* and fully compatible with
them for backward compability. It contains additional fields:
fills hash, sv, rclass hash and rclass sv and creates OP_METHOD_REDIR
in underlying OP_METHOD_ op.
OOP context for XSUBs.
Calculated stash HV of left operand (object/class/IO/etc) is now saved in PL_methstash for later use by XSUBS.
This prevents double caclucation of stash's HV for such functions as UNIVERSAL::can and so on and speeds up them
a lot.
Moreover it has one more usage: pp_entersub sets PL_methstash to NULL if CV is called as function, and sets
PL_methstash to object/class/IO/etc stash's HV if CV is called as class/object/etc method.
This makes it possible for XS code to detect if it is called as funtion or method in case if user wants to implement
separate behaviour for those cases.
For example if (PL_methstash) { ... called as method, object/class/etc stash is in PL_methstash }
else { ... called as function }
Additionaly for XSUBs like UNIVERSAL::can which always want to interpret its calls as method calls (i.e. first arg is
object/class/etc), there is a macro dMETHSTASH which defines variable 'HV* stash' and either sets it to PL_methstash
(if called as method) or (if called as function) calculate stash in the same way as pp_method* would do in case of
real method call.
Note that PL_methstash is not stacked (to not introduce any overheat), that means you have to either use it
before you made a new perl CV call or save it to a variable.
Bring B, B::Deparse and B::Concise in consistency with new ops.
misc:
which made it possible for code in $safe->reval("...") to hack your entire program.
{
local *MyClass::func = sub {...}; # LINE A
...
} # LINE B
This example caused global method cache reset at both lines A and B because glob_assign_ref and leave_scope
thought that GV's GP refcnt was 2 (because of saving to Save Stack).
Issue has been fixed (added gp_flags and new GP flag LOCALIZED, if flag is set then 1 refcnt from save stack is
not counted in gv_method_changed calls).
sv_dump thought that it was a stash and tried to dump CV* as HV*.