diff options
author | David Mitchell <davem@iabyn.com> | 2017-07-10 15:48:02 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2017-07-27 11:30:22 +0100 |
commit | 748f2c65599942147442f443949449a965f6d608 (patch) | |
tree | e0ccd923e221f95c7ddb80fc5c6c4c42c85c5a8f /t/perf | |
parent | 4fa080dbc664ee90dd374a9a49ac0a4932421bd7 (diff) | |
download | perl-748f2c65599942147442f443949449a965f6d608.tar.gz |
optimise away OP_KEYS op in scalar/void context
In something like
if (keys %h) { ... }
the 'keys %h' is implemented as the op sequences
gv[*h] s
rv2hv lKRM/1
keys[t2] sK/1
or
padhv[%h:1,6] lRM
keys[t2] sK/1
It turns out that (%h) in scalar and void context now behaves very
similarly to (keys %h) (except that it reset the iterator), so in these
cases, convert the two ops
rv2hv/padhv, keys
into the single op
rv2hv/padhv
with a private flag indicating that the op is handling the 'keys' action
by itself.
As well as one less op to execute, this brings the boolean-context
optimisation already present in padhv/rv2sv to keys. So
if (keys %h) { ... }
is no longer slower than
if (%h) { ... }
Diffstat (limited to 't/perf')
-rw-r--r-- | t/perf/benchmarks | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/t/perf/benchmarks b/t/perf/benchmarks index d09f51b401..76d0d74bc9 100644 --- a/t/perf/benchmarks +++ b/t/perf/benchmarks @@ -306,6 +306,11 @@ setup => 'my %h;', code => '!%h', }, + 'expr::hash::bool_empty_keys' => { + desc => 'empty lexical hash in boolean keys context', + setup => 'my %h;', + code => '!keys %h', + }, 'expr::hash::bool_empty_unknown' => { desc => 'empty lexical hash in unknown context', setup => 'my ($i, %h); sub f { if (%h) { $i++ }}', @@ -316,6 +321,11 @@ setup => 'my %h = 1..10;', code => '!%h', }, + 'expr::hash::bool_full_keys' => { + desc => 'non-empty lexical hash in keys boolean context', + setup => 'my %h = 1..10;', + code => '!keys %h', + }, ( |