diff options
author | Richard Leach <richardleach@users.noreply.github.com> | 2022-08-07 23:34:42 +0000 |
---|---|---|
committer | Richard Leach <richardleach@users.noreply.github.com> | 2022-08-25 14:04:29 +0100 |
commit | c74a928a43322c574522f122a3f3a29262f90613 (patch) | |
tree | fbf0febd21ecd8e20663ca8a400030bc74176121 /pp.c | |
parent | be552ced7556db8582622a745067e1b266e8ca91 (diff) | |
download | perl-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.c | 24 |
1 files changed, 18 insertions, 6 deletions
@@ -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); |