summaryrefslogtreecommitdiff
path: root/pp.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 /pp.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 'pp.c')
-rw-r--r--pp.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/pp.c b/pp.c
index 185d7b7b34..6605d38279 100644
--- a/pp.c
+++ b/pp.c
@@ -879,11 +879,21 @@ PP(pp_undef)
RETPUSHUNDEF;
}
- sv = TOPs;
- if (!sv)
- {
- SETs(&PL_sv_undef);
- return NORMAL;
+ if (PL_op->op_private & OPpTARGET_MY) {
+ SV** const padentry = &PAD_SVl(PL_op->op_targ);
+ sv = *padentry;
+ EXTEND(SP,1);sp++;PUTBACK;
+ if ((PL_op->op_private & (OPpLVAL_INTRO|OPpPAD_STATE)) == OPpLVAL_INTRO) {
+ save_clearsv(padentry);
+ }
+ } else {
+ sv = TOPs;
+
+ if (!sv)
+ {
+ SETs(&PL_sv_undef);
+ return NORMAL;
+ }
}
if (SvTHINKFIRST(sv))
@@ -960,7 +970,9 @@ PP(pp_undef)
break;
}
default:
- if (SvTYPE(sv) >= SVt_PV && SvPVX_const(sv) && SvLEN(sv)) {
+ if (SvTYPE(sv) >= SVt_PV && SvPVX_const(sv) && SvLEN(sv)
+ && !(PL_op->op_private & OPpUNDEF_KEEP_PV)
+ ) {
SvPV_free(sv);
SvPV_set(sv, NULL);
SvLEN_set(sv, 0);