summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorRichard Leach <richardleach@users.noreply.github.com>2022-08-02 21:48:26 +0000
committerRichard Leach <richardleach@users.noreply.github.com>2022-10-24 23:21:17 +0100
commit10a5c9138224597d018843f3b298a928555b67f0 (patch)
tree008b756c7b5f34777576c94ebca07c22ee4c271f /pp.c
parent71a3dd321d7fa8259a22a1ca1e87aa820a8deef2 (diff)
downloadperl-10a5c9138224597d018843f3b298a928555b67f0.tar.gz
OP_EMPTYAVHV - optimized empty ANONLIST/ANONHASH
This commit introduces a new OP to replace cases of OP_ANONLIST and OP_ANONHASH where there are zero elements, which is very common in Perl code. As an example, `my $x = {}` is currently implemented like this: ... 6 <2> sassign vKS/2 ->7 4 <@> anonhash sK* ->5 3 <0> pushmark s ->4 5 <0> padsv[$x:1,2] sRM*/LVINTRO ->6 The pushmark serves no meaningful purpose when there are zero elements and the anonhash, besides undoing the pushmark, performs work that is unnecessary for this special case. The peephole optimizer, which also checks for applicability of a related TARGMY optimization, transforms this example into: ... - <1> ex-sassign vKS/2 ->4 3 <@> emptyavhv[$x:1,2] vK*/LVINTRO,ANONHASH,TARGMY ->4 - <0> ex-pushmark s ->3 - <0> ex-padsv sRM*/LVINTRO ->-
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/pp.c b/pp.c
index f06f282de6..5b4c1efe64 100644
--- a/pp.c
+++ b/pp.c
@@ -5572,6 +5572,51 @@ PP(pp_anonlist)
RETURN;
}
+/* When an anonlist or anonhash will (1) be empty and (2) return an RV
+ * pointing to the new AV/HV, the peephole optimizer can swap in this
+ * simpler function and op_null the originally associated PUSHMARK. */
+PP(pp_emptyavhv)
+{
+ dSP;
+ OP * const op = PL_op;
+ SV * rv;
+ SV * const sv = MUTABLE_SV( newSV_type(
+ (op->op_private & OPpEMPTYAVHV_IS_HV) ?
+ SVt_PVHV :
+ SVt_PVAV ) );
+
+ /* Is it an assignment, just a stack push, or both?*/
+ if (op->op_private & OPpTARGET_MY) {
+ SV** const padentry = &PAD_SVl(op->op_targ);
+ rv = *padentry;
+ /* Since the op_targ is very likely to be an undef SVt_IV from
+ * a previous iteration, converting it to a live RV can
+ * typically be special-cased.*/
+ if (SvTYPE(rv) == SVt_IV && !SvOK(rv)) {
+ SvFLAGS(rv) = (SVt_IV | SVf_ROK);
+ SvRV_set(rv, sv);
+ } else {
+ sv_setrv_noinc_mg(rv, sv);
+ }
+ if ((op->op_private & (OPpLVAL_INTRO|OPpPAD_STATE)) == OPpLVAL_INTRO) {
+ save_clearsv(padentry);
+ }
+ if (GIMME_V == G_VOID) {
+ RETURN; /* skip extending and pushing */
+ }
+ } else {
+ /* Inlined newRV_noinc */
+ SV * refsv = newSV_type_mortal(SVt_IV);
+ SvRV_set(refsv, sv);
+ SvROK_on(refsv);
+
+ rv = refsv;
+ }
+
+ XPUSHs(rv);
+ RETURN;
+}
+
PP(pp_anonhash)
{
dSP; dMARK; dORIGMARK;