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

Reply via email to