diff options
author | Richard Leach <richardleach@users.noreply.github.com> | 2022-07-08 14:52:19 +0000 |
---|---|---|
committer | Richard Leach <richardleach@users.noreply.github.com> | 2022-08-17 11:19:10 +0100 |
commit | 9fdd7fc4796d89d16dceea42f2af91e4fde296ed (patch) | |
tree | 9f113c432769e4dd1e8628fe2500059a588cce52 /peep.c | |
parent | 434ccf36bb90d7dfe527c3ecd775983821669b4a (diff) | |
download | perl-9fdd7fc4796d89d16dceea42f2af91e4fde296ed.tar.gz |
Implement OP_PADSV_STORE - combined sassign/padsv OP
This commit introduces a new OP to replace simple cases
of OP_SASSIGN and OP_PADSV.
For example, 'my $x = 1' is currently implemented as:
1 <;> nextstate(main 1 -e:1) v:{
2 <$> const(IV 1) s
3 <0> padsv[$x:1,2] sRM*/LVINTRO
4 <2> sassign vKS/2
But now will be turned into:
1 <;> nextstate(main 1 -e:1) v:{
2 <$> const(IV 1) s
3 <1> padsv_store[$x:1,2] vKMS/LVINTRO
This intended to be a transparent performance optimization.
It should be applicable for RHS optrees of varying complexity.
Diffstat (limited to 'peep.c')
-rw-r--r-- | peep.c | 52 |
1 files changed, 52 insertions, 0 deletions
@@ -3840,6 +3840,58 @@ Perl_rpeep(pTHX_ OP *o) } } } + OP* rhs = cBINOPx(o)->op_first; + OP* lval = cBINOPx(o)->op_last; + + /* Combine a simple SASSIGN OP with a PADSV lvalue child OP + * into a single OP. */ + + /* This optimization covers arbitrarily complicated RHS OP + * trees. Separate optimizations may exist for specific, + * single RHS OPs, such as: + * "my $foo = undef;" or "my $bar = $other_padsv;" */ + + if (!(o->op_private & (OPpASSIGN_BACKWARDS|OPpASSIGN_CV_TO_GV)) + && lval && (lval->op_type == OP_PADSV) && + !(lval->op_private & OPpDEREF) + ) { + + /* SASSIGN's bitfield flags, such as op_moresib and + * op_slabbed, will be carried over unchanged. */ + OpTYPE_set(o, OP_PADSV_STORE); + + /* Explicitly craft the new OP's op_flags, carrying + * some bits over from the SASSIGN */ + o->op_flags = ( + OPf_KIDS | OPf_STACKED | + (o->op_flags & (OPf_WANT|OPf_PARENS)) + ); + + /* Reset op_private flags, taking relevant private flags + * from the PADSV */ + o->op_private = (lval->op_private & + (OPpLVAL_INTRO|OPpPAD_STATE|OPpDEREF)); + + /* Steal the targ from the PADSV */ + o->op_targ = lval->op_targ; lval->op_targ = 0; + + /* Fixup op_next ptrs */ + /* oldoldop can be arbitrarily deep in the RHS OP tree */ + oldoldop->op_next = o; + + /* Even when (rhs != oldoldop), rhs might still have a + * relevant op_next ptr to lval. This is definitely true + * when rhs is OP_NULL with a LOGOP kid (e.g. orassign). + * There may be other cases. */ + if (rhs->op_next == lval) + rhs->op_next = o; + + /* Now null-out the PADSV */ + op_null(lval); + + /* NULL the previous op ptrs, so rpeep can continue */ + oldoldop = NULL; oldop = NULL; + } break; case OP_AASSIGN: { |