summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorRichard Leach <richardleach@users.noreply.github.com>2022-08-06 21:55:28 +0000
committerRichard Leach <richardleach@users.noreply.github.com>2022-09-07 20:27:27 +0100
commitaafefcb90183e1d6ef62d9e1ccc1fae7fcdf9c8e (patch)
treeb870aefc05d58e8daabe190802e82f35047d32c7 /pp_hot.c
parentec18fac0008c98267fc560f7023d1d11703ed66d (diff)
downloadperl-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.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/pp_hot.c b/pp_hot.c
index cb76dda568..e64dbd093d 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -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;