Branch: refs/heads/blead Home: https://github.com/Perl/perl5 Commit: c949292055f73373ddef8037677075cfe1a78fc2 https://github.com/Perl/perl5/commit/c949292055f73373ddef8037677075cfe1a78fc2 Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 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: dbcd7f4a222753b4329ac1def41fc1048fbc438b https://github.com/Perl/perl5/commit/dbcd7f4a222753b4329ac1def41fc1048fbc438b Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 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: 547324acdb2344f04378d3c32330b611dc0bd519 https://github.com/Perl/perl5/commit/547324acdb2344f04378d3c32330b611dc0bd519 Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 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: c90e7ed39e5df8d5915422454fb76198801f3563 https://github.com/Perl/perl5/commit/c90e7ed39e5df8d5915422454fb76198801f3563 Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 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: 5c541f02dff4efb970dd14f3446c4eaa0da7e607 https://github.com/Perl/perl5/commit/5c541f02dff4efb970dd14f3446c4eaa0da7e607 Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 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: c7715606cac4a6202a182dc4ce08f0d2ef9e9838 https://github.com/Perl/perl5/commit/c7715606cac4a6202a182dc4ce08f0d2ef9e9838 Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 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: 52d6284a2f8c9bced06ba36d677757e8c7eed341 https://github.com/Perl/perl5/commit/52d6284a2f8c9bced06ba36d677757e8c7eed341 Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 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: 799e546082f2cb7155afc3241daf70c7ea539ac3 https://github.com/Perl/perl5/commit/799e546082f2cb7155afc3241daf70c7ea539ac3 Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 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: 5eebee26f170b4d0afaecaac50ac825530957a1e https://github.com/Perl/perl5/commit/5eebee26f170b4d0afaecaac50ac825530957a1e Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 Jan 2024) Changed paths: M pp.c Log Message: ----------- pp_push, pp_unshift: don't push TARG in void cxt Commit: b393d5be977d3ec6615ac3d0104ffbe34fc79a72 https://github.com/Perl/perl5/commit/b393d5be977d3ec6615ac3d0104ffbe34fc79a72 Author: David Mitchell <da...@iabyn.com> Date: 2024-01-09 (Tue, 09 Jan 2024) Changed paths: M ext/B/t/optree_varinit.t M gv.c M op.c M peep.c M pp.c M pp_hot.c M t/perf/opcount.t Log Message: ----------- [MERGE] handle/optimise some ops in void context This branch: Fixes a couple of ops which weren't getting their context set correctly. This doesn't make any change to the correct operation of those ops (they don't change their behaviour based on context), but could allow for future optimisations. Skips a couple of portmanteau OP optimisations ({padv,elemfast}_store) in non-void context. This allows those two be ops to be slightly faster in void context (which is overwhelmingly how they are likely to be used(*)), and falls back to the old separate padsv/sassign op pair otherwise. Updates a few other ops to handle void context slightly more efficiently. (*) Tony Cook profiled the test suite: 83.7% of calls to pp_padsv_store()s were in void context and 99.9% of aelemfastlex_store()s. Compare: https://github.com/Perl/perl5/compare/f064991f3df2...b393d5be977d