Branch: refs/heads/davem/rc7
  Home:   https://github.com/Perl/perl5
  Commit: 2280665a0c90f669febc20e2dec4ad96f11c9c7e
      
https://github.com/Perl/perl5/commit/2280665a0c90f669febc20e2dec4ad96f11c9c7e
  Author: David Mitchell <da...@iabyn.com>
  Date:   2024-01-03 (Wed, 03 Jan 2024)

  Changed paths:
    M ext/B/t/optree_varinit.t

  Log Message:
  -----------
  add Concise tests for state var assignment

Add tests for

    state $x = 1;
    my $y = state $x = 1;

to check what context is allocated to the various ops. At the moment it
is actually wrong in places, and this commit captures that wrongness.
The next commit will fix this, and those diffs to the tests added in this
commit will help make it clear what has changed.


  Commit: 6e575db0bff0341bdab5d7d5cba10f3496a34ea1
      
https://github.com/Perl/perl5/commit/6e575db0bff0341bdab5d7d5cba10f3496a34ea1
  Author: David Mitchell <da...@iabyn.com>
  Date:   2024-01-03 (Wed, 03 Jan 2024)

  Changed paths:
    M ext/B/t/optree_varinit.t
    M op.c

  Log Message:
  -----------
  set context in 'state' expressions

The ops associated with a state variable declaration and initial
assignment weren't getting their context (GIMME) assigned.

Background:

    state $x = ...;

gets compiled to something similar to

    if (first_time)
        $x = ...;
    else
        $x;

Except that the 'if' is performed by an OP_ONCE logop, which checks and
updates a flag in the pad, and branches to op_next or op_other as
appropriate.

During compilation, the context of the state expression wasn't being
passed on to the children of the OP_ONCE. So the assignment (optimised
into a padsv_store) and the padsv were left as UNKNOWN rather than VOID
or SCALAR as appropriate, as in these two examples:

    state $x = 1;         # should be void
    $y = (state $x = 1);  # should be scalar

This commit fixes that. Note that at the moment it makes no practical
difference, since the padsv/padsv_store ops  don't currently change
their behaviour based on context, but that might change.


  Commit: e498a32a9cb6a9c98e0c44b64241b51abe6435a1
      
https://github.com/Perl/perl5/commit/e498a32a9cb6a9c98e0c44b64241b51abe6435a1
  Author: David Mitchell <da...@iabyn.com>
  Date:   2024-01-03 (Wed, 03 Jan 2024)

  Changed paths:
    M gv.c
    M op.c
    M pp.c

  Log Message:
  -----------
  Give OPpTARGET_MY ops real context

Perl has an optimisation whereby an op which returns the RHS of a scalar
assignment to a lexical, and which would normally store its result in
a PADTMP, instead skips the following PADSV and SASSIGN ops and assigns
to the lexical directly, instead of to the PADTMP. For example in

    $lex = $a + $b;

the ops (in execution-order) would be changed from

    add[t5] sK/2
    gvsv[*lex] s
    sassign vKS/2
    nextstate(main 2 -e:1) v:{

to

    add[$lex:1,2] sK/TARGMY,2
    nextstate(main 2 -e:1) v:{

However, note that although that the add op is now essentially called in
void context, it is still marked as being in scalar context. This commit
changes it to be be marked as void, i.e.

    add[$lex:1,2] vK/TARGMY,2

The main reason for this is to allow for future optimisations in
functions like pp_add(), which will be able to skip pushing the result
onto the stack in in void context. It just so happens that scalar
assignments to lexical vars are typically in void context.

However, since this is a visible change from the perspective of modules
which examine ops or optrees, I'll leave doing any optimisations until
later, in case this commit needs to be reverted.

The main things this commit had to fix up following the change were:
- still call overload methods in scalar context, even though the op is
  now marked as void;
- not issuing "useless use of add in void context" style warnings on
  such ops;
- making pp_push and pp_unshift still set TARG in void context

No matter whether the op's context is marked as scalar or as void, some
parts of perl will misunderstand, and will need to be special-cased
(since the op is really both, depending on your perspective). So this
commit changes the burden of the special-casing code to be in the
non-hot code paths, like during complication or when calling out to an
overload method.


  Commit: eb5569f01a08008eaa45bbc5978da9607199046a
      
https://github.com/Perl/perl5/commit/eb5569f01a08008eaa45bbc5978da9607199046a
  Author: David Mitchell <da...@iabyn.com>
  Date:   2024-01-03 (Wed, 03 Jan 2024)

  Changed paths:
    M ext/B/t/optree_varinit.t
    M peep.c
    M pp_hot.c
    M t/perf/opcount.t

  Log Message:
  -----------
  OP_PADSV_STORE: only in void context

For the optimisation which converts $lex  = expr into an OP_PADSV_STORE
op, only optimise if the scalar assign is in VOID context.

This allows us to stop pp_padsv_store() from uselessly pushing the
result onto the stack, only to be immediately popped again by the
following nextstate or unstack op. This becomes more important on
PERL_RC_STACK builds, as each push or pop involves manipulating the SV's
reference count.

I'm working on the assumption that scalar/list/unknown cxt lexical
assigns are rare enough that not optimising them is less of a loss than
optimising the void case. So:

    $lex = ....;             # void:    now even faster
    $other = $lex = ...;     # scalar:  now slow again
    foo($lex = ..., ....);   # list:    now slow again

    sub {
        ....
        $lex = ...;          # unknown: now slow again
    }


  Commit: 62f4a0ef33d3cb18c1bb5ca8f3180b58b8a92c47
      
https://github.com/Perl/perl5/commit/62f4a0ef33d3cb18c1bb5ca8f3180b58b8a92c47
  Author: David Mitchell <da...@iabyn.com>
  Date:   2024-01-03 (Wed, 03 Jan 2024)

  Changed paths:
    M peep.c
    M pp_hot.c
    M t/perf/opcount.t

  Log Message:
  -----------
  OP_AELEMFASTLEX_STORE: only in void context

For the optimisation which converts $lex[N] = expr into an
OP_AELEMFASTLEX_STORE op, only optimise if the scalar assign is in VOID
context.

(See the previous commit for a very similar change to OP_PADSV_STORE.)

This allows us to stop pp_aelemfastlex_store() from uselessly pushing the
result onto the stack, only to be immediately popped again by the
following nextstate or unstack op. This becomes more important on
PERL_RC_STACK builds, as each push or pop involves manipulating the SV's
reference count.

I'm working on the assumption that scalar/list/unknown cxt lexical
array element assigns are rare enough that not optimising them is less
of a loss than optimising the void case. So:

    $lex[0] = ....;             # void:    now even faster
    $other = $lex[0] = ...;     # scalar:  now slow again
    foo($lex[0] = ..., ....);   # list:    now slow again

    sub {
        ....
        $lex[0] = ...;          # unknown: now slow again
    }


  Commit: 9a2ed30472b47e6c6ebd1c7b555b33598c5d9e3b
      
https://github.com/Perl/perl5/commit/9a2ed30472b47e6c6ebd1c7b555b33598c5d9e3b
  Author: David Mitchell <da...@iabyn.com>
  Date:   2024-01-03 (Wed, 03 Jan 2024)

  Changed paths:
    M pp_hot.c

  Log Message:
  -----------
  pp_sassign: make return more efficient.

Currently scalar assign effectively always pops the original two
arguments, then pushes the result.

This commit makes it so that

1) in void context (the most usual), it just pops 2 and skips pushing 1.

2) In scalar context, it still logically pops 2 and pushes 1, but since
the return value is also the original left arg, just shuffle that
argument around on the stack rather than messing around with its
reference count in the meantime. The right arg is still freed.

To make it so that *PL_stack_sp remains equal to left, a couple of
non-hot codepaths which break this rule now update the stack to keep
things consistent.


  Commit: 1e0c1884f45b0abed0c394a57735dc760449f770
      
https://github.com/Perl/perl5/commit/1e0c1884f45b0abed0c394a57735dc760449f770
  Author: David Mitchell <da...@iabyn.com>
  Date:   2024-01-03 (Wed, 03 Jan 2024)

  Changed paths:
    M pp_hot.c

  Log Message:
  -----------
  pp_print() optimise for void return

This function is often called in void context; don't push a result
in void context which will will only be immediately popped again by the
following nextstate or unstack op. On PERL_RC_STACK builds, this
also avoids ++ing and --ing the return value's ref count.

In unknown context it just assumes non-void, rather than incurring the
cost of determining the caller's context.


  Commit: 42c45cea429e6b4b6478fe48f0d6325bd0823255
      
https://github.com/Perl/perl5/commit/42c45cea429e6b4b6478fe48f0d6325bd0823255
  Author: David Mitchell <da...@iabyn.com>
  Date:   2024-01-03 (Wed, 03 Jan 2024)

  Changed paths:
    M pp.c

  Log Message:
  -----------
  pp_undef(): optimise for void return

This function is typically called in void context; don't push a result
in void context which will will only be immediately popped again by the
following nextstate or unstack op. On PERL_RC_STACK builds, this
also avoids ++ing and --ing the return value's ref count.

In unknown context it just assumes non-void, rather than incurring the
cost of determining the caller's context.


  Commit: 44c9f9522cd0767fb5e767ee849a0666c9356c54
      
https://github.com/Perl/perl5/commit/44c9f9522cd0767fb5e767ee849a0666c9356c54
  Author: David Mitchell <da...@iabyn.com>
  Date:   2024-01-03 (Wed, 03 Jan 2024)

  Changed paths:
    M pp.c

  Log Message:
  -----------
  pp_push, pp_unshift: don't push TARG in void cxt


Compare: https://github.com/Perl/perl5/compare/2280665a0c90%5E...44c9f9522cd0

Reply via email to