diff options
author | Richard Leach <richardleach@users.noreply.github.com> | 2022-08-06 21:55:28 +0000 |
---|---|---|
committer | Richard Leach <richardleach@users.noreply.github.com> | 2022-09-07 20:27:27 +0100 |
commit | aafefcb90183e1d6ef62d9e1ccc1fae7fcdf9c8e (patch) | |
tree | b870aefc05d58e8daabe190802e82f35047d32c7 /pp_hot.c | |
parent | ec18fac0008c98267fc560f7023d1d11703ed66d (diff) | |
download | perl-aafefcb90183e1d6ef62d9e1ccc1fae7fcdf9c8e.tar.gz |
OP_AELEMFASTLEX_STORE - combined sassign/aelemfast_lex
This commit introduces a new OP to replace simple cases of OP_SASSIGN
and OP_AELEMFAST_LEX. (Similar concept to GH #19943)
For example, `my @ary; $ary[0] = "boo"` is currently implemented as:
7 <2> sassign vKS/2 ->8
5 <$> const[PV "boo"] s ->6
- <1> ex-aelem sKRM*/2 ->7
6 <0> aelemfast_lex[@ary:1,2] sRM ->7
- <0> ex-const s ->-
But now will be turned into:
6 <1> aelemfastlex_store[@ary:1,2] vKS ->7
5 <$> const(PV "boo") s ->6
- <1> ex-aelem sKRM*/2 ->6
- <0> ex-aelemfast_lex sRM ->6
- <0> ex-const s ->-
This is intended to be a transparent performance optimization.
It should be applicable for RHS optrees of varying complexity.
Diffstat (limited to 'pp_hot.c')
-rw-r--r-- | pp_hot.c | 50 |
1 files changed, 50 insertions, 0 deletions
@@ -169,6 +169,56 @@ PP(pp_padsv_store) RETURN; } +/* A mashup of simplified AELEMFAST_LEX + SASSIGN OPs */ + +PP(pp_aelemfastlex_store) +{ + dSP; + OP * const op = PL_op; + SV* const val = TOPs; /* RHS value to assign */ + AV * const av = MUTABLE_AV(PAD_SV(op->op_targ)); + const I8 key = (I8)PL_op->op_private; + SV * targ = NULL; + + /* !OPf_STACKED is not handled by this OP */ + assert(op->op_flags & OPf_STACKED); + + /* Inlined, simplified pp_aelemfast here */ + assert(SvTYPE(av) == SVt_PVAV); + assert(key >= 0); + + /* inlined av_fetch() for simple cases ... */ + if (!SvRMAGICAL(av) && key <= AvFILLp(av)) { + targ = AvARRAY(av)[key]; + } + /* ... else do it the hard way */ + if (!targ) { + SV **svp = av_fetch(av, key, 1); + + if (svp) + targ = *svp; + else + DIE(aTHX_ PL_no_aelem, (int)key); + } + + /* Inlined, simplified pp_sassign from here */ + assert(TAINTING_get || !TAINT_get); + if (UNLIKELY(TAINT_get) && !SvTAINTED(val)) + TAINT_NOT; + + if ( + UNLIKELY(SvTEMP(targ)) && !SvSMAGICAL(targ) && SvREFCNT(targ) == 1 && + (!isGV_with_GP(targ) || SvFAKE(targ)) && ckWARN(WARN_MISC) + ) + Perl_warner(aTHX_ + packWARN(WARN_MISC), "Useless assignment to a temporary" + ); + SvSetMagicSV(targ, val); + + SETs(targ); + RETURN; +} + PP(pp_sassign) { dSP; |