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]
This commit is contained in:
John Hawthorn 2022-08-25 15:01:27 -07:00
Родитель 3401e58f23
Коммит fc2d9fedc2
1 изменённых файлов: 6 добавлений и 0 удалений

Просмотреть файл

@ -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;
}