summaryrefslogtreecommitdiff
path: root/peep.c
diff options
context:
space:
mode:
authorRichard Leach <richardleach@users.noreply.github.com>2022-08-07 23:34:42 +0000
committerRichard Leach <richardleach@users.noreply.github.com>2022-08-25 14:04:29 +0100
commitc74a928a43322c574522f122a3f3a29262f90613 (patch)
treefbf0febd21ecd8e20663ca8a400030bc74176121 /peep.c
parentbe552ced7556db8582622a745067e1b266e8ca91 (diff)
downloadperl-c74a928a43322c574522f122a3f3a29262f90613.tar.gz
Add OPpTARGET_MY optimization to OP_UNDEF
This allows the existing `undef` OP to act on a pad SV. The following two cases are optimized: `undef my $x`, currently implemented as: 4 <1> undef vK/1 ->5 3 <0> padsv[$x:1,2] sRM/LVINTRO ->4 `my $a = undef`, currently implemented as: 5 <2> sassign vKS/2 ->6 3 <0> undef s ->4 4 <0> padsv[$x:1,2] sRM*/LVINTRO ->5 These are now just represented as: 3 <1> undef[$x:1,2] vK/SOMEFLAGS ->4 Note: The two cases are not quite functionally identical, as `$x = undef` clears the SV flags but preserves any PV allocation for later reuse, whereas `undef $x` does free any PV allocation. This behaviour difference is preserved through use of the OPpUNDEF_KEEP_PV flag.
Diffstat (limited to 'peep.c')
-rw-r--r--peep.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/peep.c b/peep.c
index d7e618d0c0..41bb46d7e7 100644
--- a/peep.c
+++ b/peep.c
@@ -3775,6 +3775,58 @@ Perl_rpeep(pTHX_ OP *o)
break;
}
+ case OP_UNDEF:
+ if ((o->op_flags & OPf_KIDS) &&
+ (cUNOPx(o)->op_first->op_type == OP_PADSV)) {
+
+ /* Convert:
+ * undef
+ * padsv[$x]
+ * to:
+ * undef[$x]
+ */
+
+ OP * padsv = cUNOPx(o)->op_first;
+ o->op_private = OPpTARGET_MY |
+ (padsv->op_private & (OPpLVAL_INTRO|OPpPAD_STATE));
+ o->op_targ = padsv->op_targ; padsv->op_targ = 0;
+ op_null(padsv);
+ /* Optimizer does NOT seem to fix up the padsv op_next ptr */
+ if (oldoldop)
+ oldoldop->op_next = o;
+ oldop = oldoldop;
+ oldoldop = NULL;
+
+ } else if (o->op_next->op_type == OP_PADSV) {
+ OP * padsv = o->op_next;
+ OP * sassign = (padsv->op_next &&
+ padsv->op_next->op_type == OP_SASSIGN) ?
+ padsv->op_next : NULL;
+ if (sassign && cBINOPx(sassign)->op_first == o) {
+ /* Convert:
+ * sassign
+ * undef
+ * padsv[$x]
+ * to:
+ * undef[$x]
+ * NOTE: undef does not have the "T" flag set in
+ * regen/opcodes, as this would cause
+ * S_maybe_targlex to do the optimization.
+ * Seems easier to keep it all here, rather
+ * than have an undef-specific branch in
+ * S_maybe_targlex just to add the
+ * OPpUNDEF_KEEP_PV flag.
+ */
+ o->op_private = OPpTARGET_MY | OPpUNDEF_KEEP_PV |
+ (padsv->op_private & (OPpLVAL_INTRO|OPpPAD_STATE));
+ o->op_targ = padsv->op_targ; padsv->op_targ = 0;
+ op_null(padsv);
+ op_null(sassign);
+ /* Optimizer DOES seems to fix up the op_next ptrs */
+ }
+ }
+ break;
+
case OP_QR:
case OP_MATCH:
if (!(cPMOP->op_pmflags & PMf_ONCE)) {