diff options
author | John Hawthorn <john@hawthorn.email> | 2022-08-25 15:01:27 -0700 |
---|---|---|
committer | John Hawthorn <john@hawthorn.email> | 2022-09-01 17:36:20 -0700 |
commit | fc2d9fedc2cc21f25608034518d75a8337301e9a (patch) | |
tree | fe45fd92072f05d8954fddb329568eb3265334cb /compile.c | |
parent | 3401e58f23eb05e40cda67e111a1bb4c382619f5 (diff) | |
download | ruby-fc2d9fedc2cc21f25608034518d75a8337301e9a.tar.gz |
Use getblockparamproxy with branch
A common pattern when the block is an explicit parameter is to branch
based on the block parameter instead of using `block_given?`, for
example `block.call if block`.
This commit checks in the peephole optimizer for that case and uses the
getblockparamproxy optimization, which avoids allocating a proc for
simple cases, whenever a getblockparam instruction is followed
immediately by branchif or branchunless.
./miniruby --dump=insns -e 'def foo(&block); 123 if block; end'
== disasm: #<ISeq:foo@-e:1 (1,0)-(1,34)> (catch: FALSE)
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: 0, kw: -1@-1, kwrest: -1])
[ 1] block@0<Block>
0000 getblockparamproxy block@0, 0 ( 1)[LiCa]
0003 branchunless 8
0005 putobject 123
0007 leave [Re]
0008 putnil
0009 leave [Re]
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 6 |
1 files changed, 6 insertions, 0 deletions
@@ -3614,6 +3614,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } + if (IS_INSN_ID(iobj, getblockparam)) { + if (IS_NEXT_INSN_ID(&iobj->link, branchif) || IS_NEXT_INSN_ID(&iobj->link, branchunless)) { + iobj->insn_id = BIN(getblockparamproxy); + } + } + return COMPILE_OK; } |