Branch: refs/heads/davem/rc4 Home: https://github.com/Perl/perl5 Commit: 5d65e37772d3d0285455a64121f02e0745ded5ea https://github.com/Perl/perl5/commit/5d65e37772d3d0285455a64121f02e0745ded5ea Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 64d8ebe65e8ce16c6075737d39c1a0ac6b4a1ecc https://github.com/Perl/perl5/commit/64d8ebe65e8ce16c6075737d39c1a0ac6b4a1ecc Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 8b7d699fcc0d311eae10ad3e79521231f5983501 https://github.com/Perl/perl5/commit/8b7d699fcc0d311eae10ad3e79521231f5983501 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 25d6d0ceb783c06f069ee01ea5bbc4731d08a3ca https://github.com/Perl/perl5/commit/25d6d0ceb783c06f069ee01ea5bbc4731d08a3ca Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 23ec0babb8eda05b5a30fcd4cea236d44bea2f51 https://github.com/Perl/perl5/commit/23ec0babb8eda05b5a30fcd4cea236d44bea2f51 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 3d9060fbb9a9b5e7f3cc95cb9c1ddded64049aef https://github.com/Perl/perl5/commit/3d9060fbb9a9b5e7f3cc95cb9c1ddded64049aef Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 2bca6db6dfdcf4111db10cbf5e99c52dc18cc8f0 https://github.com/Perl/perl5/commit/2bca6db6dfdcf4111db10cbf5e99c52dc18cc8f0 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 8f223c566b00a3ceef6446df9cbd945907a3e5f0 https://github.com/Perl/perl5/commit/8f223c566b00a3ceef6446df9cbd945907a3e5f0 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 2023) Changed paths: M pp.c Log Message: ----------- make RC-stack-aware: unwrap pp_undef() Remove the temporary wrapper from pp_undef() Commit: db6b1ef0d38f09bb3957abbdfb49e228f9f68e95 https://github.com/Perl/perl5/commit/db6b1ef0d38f09bb3957abbdfb49e228f9f68e95 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 14f6b133fc68264c74f8ba7141f1e107f64cf2b1 https://github.com/Perl/perl5/commit/14f6b133fc68264c74f8ba7141f1e107f64cf2b1 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 5e1f7ad915f1124245dd37a969e86b5fb537a40d https://github.com/Perl/perl5/commit/5e1f7ad915f1124245dd37a969e86b5fb537a40d Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: d899222a7f788a1f314d811096e4e44371905683 https://github.com/Perl/perl5/commit/d899222a7f788a1f314d811096e4e44371905683 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 33d9495c33c1c4462c91e23b45031b20a425f105 https://github.com/Perl/perl5/commit/33d9495c33c1c4462c91e23b45031b20a425f105 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: c0878a06733c09a57d81be695d4ea837471b03f0 https://github.com/Perl/perl5/commit/c0878a06733c09a57d81be695d4ea837471b03f0 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 2bb1814aaf54298bd43284896b018a5c7b70818b https://github.com/Perl/perl5/commit/2bb1814aaf54298bd43284896b018a5c7b70818b Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 4a7d95db5b569081c5e454f29ec65a6584110ff4 https://github.com/Perl/perl5/commit/4a7d95db5b569081c5e454f29ec65a6584110ff4 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: ab34135ad6f12c723d14d1f3f35f4158b5e55d3f https://github.com/Perl/perl5/commit/ab34135ad6f12c723d14d1f3f35f4158b5e55d3f Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: d6bfd35e0820b188958b6f17407f041a780c0c4f https://github.com/Perl/perl5/commit/d6bfd35e0820b188958b6f17407f041a780c0c4f Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: a555fda44d73c825d13c1035a5d25272f59ec66c https://github.com/Perl/perl5/commit/a555fda44d73c825d13c1035a5d25272f59ec66c Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 3eb2167b8a2f25d188ac6adae594bd482c0c93a4 https://github.com/Perl/perl5/commit/3eb2167b8a2f25d188ac6adae594bd482c0c93a4 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 53fb2f639c62aa6f2f8f46bade2cae2e2f6ff55d https://github.com/Perl/perl5/commit/53fb2f639c62aa6f2f8f46bade2cae2e2f6ff55d Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: a9c67a3fad72694bec3c5b282a43f39e961238e7 https://github.com/Perl/perl5/commit/a9c67a3fad72694bec3c5b282a43f39e961238e7 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: e5a34b5a3a12641a215f63d2403651990b0cefe4 https://github.com/Perl/perl5/commit/e5a34b5a3a12641a215f63d2403651990b0cefe4 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: c4e9fefe9206fe38342434f466b466791e1f9636 https://github.com/Perl/perl5/commit/c4e9fefe9206fe38342434f466b466791e1f9636 Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: ad706e07075da06944d04eebcfe036228dbe6b2b https://github.com/Perl/perl5/commit/ad706e07075da06944d04eebcfe036228dbe6b2b Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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: 0be1aeee97abce183b66d10dad352bdaae663c3e https://github.com/Perl/perl5/commit/0be1aeee97abce183b66d10dad352bdaae663c3e Author: David Mitchell <da...@iabyn.com> Date: 2023-11-16 (Thu, 16 Nov 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. Compare: https://github.com/Perl/perl5/compare/5d65e37772d3%5E...0be1aeee97ab