Optimise %hash in sub { %hash || ... }
authorFather Chrysostomos <sprout@cpan.org>
Sat, 25 Aug 2012 20:22:46 +0000 (13:22 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 25 Aug 2012 21:44:01 +0000 (14:44 -0700)
commit6ea72b3a1069e5b7ba4f03a9fb27f685d3ac4733
tree688252f6052dfe90b2b7d5db98d00e95b8ad9439
parenta43e79016be2ee77667099f1868307f7788bd811
Optimise %hash in sub { %hash || ... }

In %hash || $foo, the %hash is in scalar context, so it has to iterate
through the buckets to produce statistics on bucket usage.

If the || is in void context, the value returned by hash is only ever
used as a boolean (as || doesn’t have to return it).  We already opti-
mise it by adding a boolkeys op when it is known at compile time that
|| will be in void context.

In sub { %hash || $foo } it is not known at compile time that it will
be in void context, so it wasn’t optimised.

This commit optimises it by flagging the %hash at compile time as
being possibly in ‘true boolean’ context.  When that flag is set,
the rv2hv and padhv ops call block_gimme() to see whether || is in
void context.

This speeds things up signficantly.  Here is what I got after optimis-
ing rv2hv but before doing padhv:

$ time ./miniperl -e '%hash = 1..10000; sub { %hash || 1 }->() for 1..100000'

real 0m0.179s
user 0m0.101s
sys 0m0.005s
$ time ./miniperl -e 'my %hash = 1..10000; sub { %hash || 1 }->() for 1..100000'

real 0m5.446s
user 0m2.419s
sys 0m0.015s

(That example is slightly misleading because of the closure, but the
closure version takes 1 sec. when optimised.)
dump.c
ext/B/B/Concise.pm
op.c
op.h
pp.c
pp_hot.c