Branch: refs/heads/blead Home: https://github.com/Perl/perl5 Commit: 08368a773f179335566e09096be6e015368237d1 https://github.com/Perl/perl5/commit/08368a773f179335566e09096be6e015368237d1 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023)
Changed paths: M pod/perlref.pod Log Message: ----------- document ref assignment in list context The 'refaliasing' feature, whereby assigning to a literal reference causes an aliasing operation (e.g. \$x = \...) didn't document what was returned if the assignment was done in list context. This commit adds a basic summary to the docs. See the thread http://nntp.perl.org/group/perl.perl5.porters/267074 for the discussion. Commit: 823fcbfd95001ebd591a4b9c0c19b0e126f22d76 https://github.com/Perl/perl5/commit/823fcbfd95001ebd591a4b9c0c19b0e126f22d76 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M t/op/lvref.t Log Message: ----------- add list context tests to t/op/lvref.t Codify the existing behaviour of alias list assignment in list context, e.g. .... = ( (\$x, \$y, \(@a)) = (....) ); and ( (\$x, \$y, \(@a)) = (....) ) = ....; Whether the existing behaviour is sane is up for debate, but if if we change it, it should be a deliberate choice, not an accidental change not spotted by the existing tests. Commit: b98a30fe2d2891321ee60dcd6b44ce6498a1f211 https://github.com/Perl/perl5/commit/b98a30fe2d2891321ee60dcd6b44ce6498a1f211 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M t/op/lvref.t Log Message: ----------- add lvalue scalar alias tests to lvref.t This is a compile-time error: (\$x = \1) = \2; However, the following is legal code, but is untested (the 'OPf_MOD' branch in pp_refassign() is not triggered by the test suite): f(\$x = \1); So this commit adds some tests. It assumes that the above code is equivalent to: \$x = \1; f(\$x); Whether the existing behaviour is sane is up for debate, but if if we change it, it should be a deliberate choice, not an accidental change not spotted by the existing tests. Commit: 313c8957d30780156be85d76909da6b1bfdbce27 https://github.com/Perl/perl5/commit/313c8957d30780156be85d76909da6b1bfdbce27 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M ext/Hash-Util-FieldHash/t/02_function.t Log Message: ----------- Hash-Util-FieldHash: fixup test on PERL_RC_STACK Hash::Util::FieldHash is an implementation of "inside out" objects, where field values are stored in per-field hashes whose keys are the numeric addresses of the objects, and whose values represent the value of that field for a particular object. The hashes are magic, in that they don't hold a reference to each object, but automatically delete the relevant entry from the hash when the object is freed. This is achieved internally with weak references and a bunch of user magic attached to the hash and the object. A test in 02_function.t checks that such a link in the magic hash to an object is removed after the real object is freed. This test looked something like: $h{[]} = 123; is(keys %h, 0); which relied on the temp anon array being freed almost immediately and triggering the hash delete. Now it turns out that OP_ANONLIST (and its later optimisation, OP_EMPTYAVHV) return an SvTEMP RV. In the code above, this means that [] gets freed at the start of the next statement (by the freetmps() in pp_nextstate()), and all works as expected. However, when pp_emptyavhv() is unwrapped in the next commit, on PERL_RC_STACK builds it will skip mortalising the return result, and just rely on the ref count from the stack to keep the RV alive as long as needed. By "needed", this is only while the helem op is being executed, and the temp array is thus freed at the end of the helem, rather than at the end of the statement. This triggers the entry in the hash being auto-deleted earlier, so when the next op, the scalar assign, executes, it triggers a warning: Useless assignment to a temporary at t/02_function.t line 121. After a lot of faffing about trying to work out what was going on, I concluded that the intent of the test could just as well be done by creating a real array reference variable and to just undef it directly after the hash assign. (I.e. it took some time to convince myself that there wasn't a bug in pp_emptyavhv, pp_sassign nor FieldHash.xs, and that just the test needed fixing.) Commit: 14403447b7488675c7d043c7d7325011727b3e45 https://github.com/Perl/perl5/commit/14403447b7488675c7d043c7d7325011727b3e45 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp.c M t/op/array.t Log Message: ----------- make RC-stack-aware: unwrap pp_emptyavhv() Remove the temporary wrapper from pp_emptyavhv() Also fix some tests in array.t, which were expecting a temp empty array ref to be prematurely freed. With PERL_RC_STACK, it's no longer prematurely freed. Commit: a98ee9eadd3d547a367869acc3edfa73006f5615 https://github.com/Perl/perl5/commit/a98ee9eadd3d547a367869acc3edfa73006f5615 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M t/op/array.t Log Message: ----------- op/array.t: skip \$#{[]} test under PERL_RC_STACK PERL_RC_STACK builds fixes a bug whereby the [] was being prematurely freed. So the test, which was testing that perl didn't crash when trying to set the length of a freed array, was now trying to set the size of the array to some large number, and was failing under ASAN. Commit: 604c0355d21cd2bdfa4adbc4cc6e2014acb8760a https://github.com/Perl/perl5/commit/604c0355d21cd2bdfa4adbc4cc6e2014acb8760a Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp.c Log Message: ----------- make RC-stack-aware: unwrap pp_refassign() Remove the temporary wrapper from pp_refassign() Also move a couple of variable declarations into the smallest scope possible: mg and stash are used only by (and implicitly by) SvCANEXISTDELETE(). Commit: b5e6ad2a94d4362c397ec8bc0931e744534d7b4b https://github.com/Perl/perl5/commit/b5e6ad2a94d4362c397ec8bc0931e744534d7b4b Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp.c Log Message: ----------- make RC-stack-aware: unwrap pp_undef() Remove the temporary wrapper from pp_undef() Commit: eb535a3b7c3f7f88348b1e46fc5ad4b7ac140cb1 https://github.com/Perl/perl5/commit/eb535a3b7c3f7f88348b1e46fc5ad4b7ac140cb1 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- make RC-stack-aware: unwrap pp_aassign() Remove the temporary wrapper from pp_aassign() Note that this is a very basic unwrapping: in particular, pp_aassign() still heavily uses the temps stack, but now mostly unnecessarily. The next few commits will start optimising things. Commit: dba1d971bd26e7a07385b61a52522f8418c4c2bf https://github.com/Perl/perl5/commit/dba1d971bd26e7a07385b61a52522f8418c4c2bf Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: optimise AV branch under PERL_RC_STACK The block of code that handles (..., @a) = (...); used to temporarily store on the temps stack, pointers to all the RH elements, in order to avoid things being prematurely freed, such as in @a = ($a[0], ...). Under PERL_RC_STACK builds this is no longer necessary, so simplify the code. All changes are wrapped in '#ifdef PERL_RC_STACK' etc. Aliasing needs special handling. When in list context, we return refs to SVs, but store the SVs themselves in the AV. In the traditional approach, the stack keeps the RVs while the temps stack has the SvRV() values - this makes it easy to block copy the SVs to the array while leaving the stack untouched. When the temps stack is no longer being used, we have to manually dereference each RV as we assign values to the stack. Do this using the slow av_store() loop rather than the optimised Copy(AvARRAY(),...) branch. Commit: 39a2e63986dff01f0f22286bbed307a7efddd38f https://github.com/Perl/perl5/commit/39a2e63986dff01f0f22286bbed307a7efddd38f Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: optimise HV branch under PERL_RC_STACK The block of code that handles (..., %a) = (...); used to temporarily store on the temps stack, pointers to all the RH value elements (and sometimes the keys too), in order to avoid things being prematurely freed, such as in %h = ($h{a}, ...). Under PERL_RC_STACK builds this is no longer necessary, so simplify the code. All changes are wrapped in '#ifdef PERL_RC_STACK' etc. Commit: 5a8fb493e89e0884ef3f3dab320700c106665871 https://github.com/Perl/perl5/commit/5a8fb493e89e0884ef3f3dab320700c106665871 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: optimise SV branch under PERL_RC_STACK The block of code that handles ($scalar, ...) = (...); used to handle things specially if $scalar was currently a ref, in case assigning to $scalar freed the referent which was later used on the RHS. With a ref-counted stack that is no longer a problem. All changes are wrapped in '#ifdef PERL_RC_STACK' etc. Commit: 12e444f71226b83247db089c2c3683cb2c42dfce https://github.com/Perl/perl5/commit/12e444f71226b83247db089c2c3683cb2c42dfce Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c M t/op/sort.t Log Message: ----------- pp_aassign: remove panic check under PERL_RC_STACK There is some code in S_aassign_copy_common() (helper function for pp_aassign()) which checks for SvIS_FREED() of the current arg. The comments imply that the check is there specifically to help a TODO test in t/op/sort.t not randomly crash. That test does stuff which triggers a premature free of args on the stack. This test was later disabled entirely, as whatever panics or crashes were being triggered weren't being caught by the eval {} it was wrapped in. This commit, only on PERL_RC_STACK builds, skips the SvIS_FREED check, and re-enables the test in sort.t (as a real test, not a TODO). Commit: 8915a2954e1e7a90f4eb871083e3319f024f676d https://github.com/Perl/perl5/commit/8915a2954e1e7a90f4eb871083e3319f024f676d Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: fix "RC==1" optimisation checks The code sometimes skips a copying step if the ref count of the SV is 1. Under PERL_RC_STACK, the ref count can now be 2, with the optimisation still being valid. Commit: f11efeed3a5b76aaa7931900446768fc0d194c31 https://github.com/Perl/perl5/commit/f11efeed3a5b76aaa7931900446768fc0d194c31 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M embed.fnc M embed.h M inline.h M pod/perlguts.pod M proto.h Log Message: ----------- add rpp_replace_at_norc() to API It's like rpp_replace_at(), but it assumes that the SV has already had its refcount bumped. It replaces ugly code like SV *nsv = newSVsv(*svp); #ifdef PERL_RC_STACK rpp_replace(svp, nsv); SvREFCNT_dec(nsv); #else rpp_replace(svp, sv_2mortal(nsv)); #endif with a simple rpp_replace_at_norc(svp, newSvsv(*svp)); On PERL_RC_STACK builds it's more efficient than before as it's not unnecessarily bumping and then immediately unbumping nsv's refcount. Commit: 0cf81d166744bf23d9c941a5179b74613b9ab090 https://github.com/Perl/perl5/commit/0cf81d166744bf23d9c941a5179b74613b9ab090 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp.c M pp_hot.c Log Message: ----------- use rpp_replace_at_norc in refassign, aassign Use the just-added function rpp_replace_at_norc() to simplify some blocks of code recently added to pp_refassign() and pp_aassign() Commit: cc49ed3d254ee6016cad82e723241fcebef70d9a https://github.com/Perl/perl5/commit/cc49ed3d254ee6016cad82e723241fcebef70d9a Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M embed.fnc M embed.h M inline.h M pod/perlguts.pod M proto.h Log Message: ----------- Add some _NN variants of rpp_() functions. Namely: rpp_popfree_1_NN() rpp_popfree_2_NN() rpp_popfree_to_NN(svp) rpp_replace_1_1_NN(sv) rpp_replace_2_1_NN(sv) rpp_replace_at_NN(sp, sv) rpp_replace_at_norc_NN(sp, sv) These are more efficient, as they can skip checking that the existing pointers on the stack are non-NULL before attempting to decrement their reference count. Note that the *args* of the original (non-variant) functions (as opposed the values on the stack) were already assumed to be non-NULL. Commit: 4d8fbc55082bc8481f72cb39f5a4ca05c1318b29 https://github.com/Perl/perl5/commit/4d8fbc55082bc8481f72cb39f5a4ca05c1318b29 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- use rpp_foo_NN() variants in pp_aassign, pp_rv2av These make the code slightly faster. This commit is kind of a proof of concept: only pp_aassign (and the related op pp_rv2av) have been updated to use these new variants for now. Making the rest of code use them will be done later. Commit: a2515f4c681acde6541dd7f66757e0b20828a670 https://github.com/Perl/perl5/commit/a2515f4c681acde6541dd7f66757e0b20828a670 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: add is_list local variable It may be slightly more efficient than testing for (gimme == G_LIST) in hot loops. Commit: 443b64a02939b4e80b4f676b46c9659efe4f1f9f https://github.com/Perl/perl5/commit/443b64a02939b4e80b4f676b46c9659efe4f1f9f Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: skip copying scalars back to stack Consider a list assignment where there are scalars on the LHS, such as: ($x,$y,$z) = ($a,$b,$c); Except in the rare cases where the list assignment is itself in list context, such as @a = ( ($x,$y,$z) = ($a,$b,$c) ) then there is no need to copy $x to the $a stack position, $y to $b and $z to $c in order to return ($x,$y,$z). Instead leave the stack as-is, containing ($a,$b,$c,$x,$y,$z), with all six SV pointers on the stack untouched. When pp_assign() is about to return, it will just pop the 6 elements off the stack. Less messing with the stack becomes more important on PERL_RC_STACK builds, because needlessly putting things on and off the stack requires more ref count manipulation and testing. Commit: 295ebb578ae1ffef86799b72468419cd3d5d8881 https://github.com/Perl/perl5/commit/295ebb578ae1ffef86799b72468419cd3d5d8881 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: optimise: store NULLs in L elem slots (This commit only affects code within PERL_RC_STACK ifdefs) In a list assignment such as (L1, L2, ...) = (R1, R2, ...), pp_assign is called with the stack looking like: * R1 R2 ... * L1 L2 ... Previously, all elements on the stack were popped at the end. This commit changes it so that after each L element is processed, it is freed and a NULL (or sometimes &PL_sv_undef) is stored at that slot in the stack. Then at the end, PL_stack_sp can just be set to one slot below the ex-L1, without having to run a loop popping each element off the stack. This reduces the number of memory reads and branches, at the cost of more writes. (All the R elems will still need to be freed, though). Commit: 971e9b5a17aced68110b4145d2c49bbf08fc5377 https://github.com/Perl/perl5/commit/971e9b5a17aced68110b4145d2c49bbf08fc5377 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: optimise: lelem++ at end of loop There are a couple of loops along the lines of while (...) { SV *lsv = *lelem++; .... do stuff with lelem[-1] } change them to while (...) { SV *lsv = *lelem; .... do stuff with *lelem lelem++ } Commit: 2a2c64dd01fc7424aea74c5d352932ea964da2fd https://github.com/Perl/perl5/commit/2a2c64dd01fc7424aea74c5d352932ea964da2fd Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: optimise: just zero array stack elems In PERL_RC_STACK builds, When passing ownership of a bunch of SVs on the stack to an array they've just been stored in, just zero out that section of the stack and shift first_discard downwards, rather than storing &PL_sv_undef in all the stack slots. This means that at the end, PL_stack_sp can be reset directly to the base of those elements rather than decrementing the ref count of &PL_sv_undef N times. Commit: a2677daf97ded4a33bba5f9ff373c93de730d72a https://github.com/Perl/perl5/commit/a2677daf97ded4a33bba5f9ff373c93de730d72a Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: optimise: just zero hash stack elems Similar to the previous commit but for hashes rather than arrays, in PERL_RC_STACK builds, When passing ownership of a bunch of SVs on the stack to a hash they've just been stored in, just zero out that section of the stack and shift first_discard downwards, rather than storing &PL_sv_undef in all the stack slots. This means that at the end, PL_stack_sp can be reset directly to the base of those elements rather than decrementing the ref count of &PL_sv_undef N times. Commit: f54903ed18841195b413582d1b798bb5bc7ddbb9 https://github.com/Perl/perl5/commit/f54903ed18841195b413582d1b798bb5bc7ddbb9 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M pp_hot.c Log Message: ----------- pp_aassign: move UID/GID code into separate fn There is a big chunk of code near the end of pp_aassign() which is responsible for updating the OS's UIDs and/or GIDs after something like ($<,$>) = ($>,$<); has been executed. This code is long and has little to with list assignment generally, so move it out into a separate static function. This commit makes no changes to that chunk of code apart from indentation (hopefully). Commit: efc99d519efd522724a3d41fd5caa591f7e8d2b6 https://github.com/Perl/perl5/commit/efc99d519efd522724a3d41fd5caa591f7e8d2b6 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M inline.h M sv.h M t/op/hash.t Log Message: ----------- fix Perl_rpp_is_lone() for immortals. Perl_rpp_is_lone() checks whether an SV is kept alive only by the args and/or temps stack, and thus can in various circumstances be used directly rather than copying - such as a return value from a function, or assigning a value to an array or hash. However, this assumption fails on immortal SVs like PL_sv_undef. Their refcount can reach 1 but they should still be copied rather than stolen. This showed itself as an extremely intermittent failure in cpan/Test-Harness/t/compat/test-harness-compat.t It only showed up when both these conditions were met: - on DEBUGGING builds, because that sets the initial ref count of the immortals to 1000 rather than I32_MAX, making such problems easier to reproduce; *and* - under PERL_RC_STACK, because only on that build do you have SVs on the args stack (but not temps stack) with RC==1 which are stealable. Also under the RC build, as an optimisation, &PL_sv_undef is often pushed on the stack without incrementing its RC. Thus it is more liklely to reach RC==1. I don't know why the failure on that test was intermittent, even after setting PERL_HASH_SEED=0. Perhaps it was timing related. Certainly anything which made it slower, such as strace, valgrind or ASAN, made the problem go away or fail only after days rather than minutes. This commit also decreases the value of SvREFCNT_IMMORTAL on debugging builds from 1000 to 10 under PERL_RC_STACK, to make such issues/bugs more likely to be triggered. Commit: 7fbd97b4e807873b45e6847052d923bab2986229 https://github.com/Perl/perl5/commit/7fbd97b4e807873b45e6847052d923bab2986229 Author: David Mitchell <da...@iabyn.com> Date: 2023-12-04 (Mon, 04 Dec 2023) Changed paths: M embed.fnc M embed.h M ext/Hash-Util-FieldHash/t/02_function.t M inline.h M pod/perlguts.pod M pod/perlref.pod M pp.c M pp_hot.c M proto.h M sv.h M t/op/array.t M t/op/hash.t M t/op/lvref.t M t/op/sort.t Log Message: ----------- [MERGE] unwrap, optimise pp_aassign() and friends This branch: - makes pp_aassign() RC-stack-aware - optimises pp_aassign() on PERL_RC_STACK builds. - also unwraps pp_emptyavhv() pp_refassign() and pp_undef(), chiefly to avoid skewing list assignment benchmark results. - documents and adds tests for ref alias assignment in list context - adds rpp_replace_at_norc() and several rpp_foo_NN() variants to the API The main intent of this branch is to unwrap and optimise pp_aassign; all the other commits came about as side-effects of that work. The main optimisation work on pp_aassign() consists of: firstly, skipping all the temps stack juggling that it used to do to avoid prematurely freeing SVs, in such cases as @a = ($_a[0], ...). With an RC stack this is no longer necessary. Secondly, trying to avoid manipulating the stack as much as possible, now that every rpp_replace_1_1() or similar requires two ref count adjustments, one of which requires a conditional. The Porting/bench.pl results on the expr::aassign:: subset of the benchmarks gave an averages of around 96% on Ir, COND etc compared with a non-PERL_RC_STACK blead build. The work in this branch turned out to be a lot harder than I expected, and took around two calendar months to get fully working. Compare: https://github.com/Perl/perl5/compare/cf76a266bc68...7fbd97b4e807