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 /peep.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 'peep.c')
-rw-r--r-- | peep.c | 52 |
1 files changed, 52 insertions, 0 deletions
@@ -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)) { |