diff options
author | David Mitchell <davem@iabyn.com> | 2017-07-23 16:31:38 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2017-07-27 11:30:25 +0100 |
commit | 6f2dc9a6b978e866e22c46235932d018da8262ba (patch) | |
tree | aaea4ac92d8aa676e597ecbf13aff28c3a58f65d /lib | |
parent | 8dc9003ff3914e78971f561eaece965e9ceeb49e (diff) | |
download | perl-6f2dc9a6b978e866e22c46235932d018da8262ba.tar.gz |
make scalar(keys(%lexical)) less slow.
A recent commit in this branch made OP_PADHV / OP_RV2HV in void/scalar
context, followed by OP_KEYS, optimise away the OP_KEYS op and set the
OPpPADHV_ISKEYS or OPpRV2HV_ISKEYS flag on the OP_PADHV / OP_RV2HV op.
However, in scalar but non-boolean context with OP_PADHV, this actually
makes it slower, because the OP_KEYS op has a target, while the OP_PADHV
op doesn't, thus it has to create a new mortal each time to return the
integer value.
This commit fixes that by, in the case of scalar padhv, retaining the
OP_KEYS node (although still not keeping it in the execution path), then
at runtime using that op's otherwise unused target.
This only works on PERL_OP_PARENT builds (now the default) as the OP_KEYS
is the parent of the OP_PADHV, so would be hard to find at runtime
otherwise.
This commit also fixes pp_padhv/pp_rv2hv in void context - formerly it
was needlessly pushing a scalar-valued count like scalar context.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/B/Deparse.pm | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index f214081a7b..fe4e24960d 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -4115,7 +4115,13 @@ sub pp_padav { pp_padsv(@_) } sub pp_padhv { my $op = $_[1]; - (($op->private & OPpPADHV_ISKEYS) ? 'keys ' : '') . pp_padsv(@_); + my $keys = ''; + # with OPpPADHV_ISKEYS the keys op is optimised away, except + # in scalar context the old op is kept (but not executed) so its targ + # can be used. + $keys = 'keys ' if ( ($op->private & OPpPADHV_ISKEYS) + && !(($op->flags & OPf_WANT) == OPf_WANT_SCALAR)); + $keys . pp_padsv(@_); } sub gv_or_padgv { |