diff options
author | Jeremy Evans <code@jeremyevans.net> | 2023-11-30 15:30:30 -0800 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2023-12-07 11:27:55 -0800 |
commit | 7738b31d390e70b26e913d86c133a70c8e65a645 (patch) | |
tree | 0fa09623307fc30a98dcb4997f642b0a686e5c76 /compile.c | |
parent | f5a01b091673b81cf2e1efa149f84763bdadad98 (diff) | |
download | ruby-7738b31d390e70b26e913d86c133a70c8e65a645.tar.gz |
Eliminate array allocation for f(1, *a, &arg), f(*a, **kw, &arg), and f(*a, kw: 1, &arg)
These are similar to the f(1, *a, &lvar), f(*a, **kw, &lvar) and
f(*a, kw: 1, &lvar) optimizations, but they use getblockparamproxy
instruction instead of getlocal.
This also fixes the else style to be more similar to the surrounding
code.
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 41 |
1 files changed, 34 insertions, 7 deletions
@@ -3892,7 +3892,9 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal OPERAND_AT(iobj, 0) = Qfalse; } } - } else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) { + } + else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) || + IS_NEXT_INSN_ID(niobj, getblockparamproxy)) { niobj = niobj->next; /* @@ -3900,12 +3902,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * * splatarray true * getlocal / getinstancevariable - * getlocal / getinstancevariable + * getlocal / getinstancevariable / getblockparamproxy * send ARGS_SPLAT|KW_SPLAT|ARGS_BLOCKARG * => * splatarray false * getlocal / getinstancevariable - * getlocal / getinstancevariable + * getlocal / getinstancevariable / getblockparamproxy * send */ if (IS_NEXT_INSN_ID(niobj, send)) { @@ -3917,7 +3919,31 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } } - } else if (IS_NEXT_INSN_ID(niobj, duphash)) { + } + else if (IS_NEXT_INSN_ID(niobj, getblockparamproxy)) { + niobj = niobj->next; + + if (IS_NEXT_INSN_ID(niobj, send)) { + niobj = niobj->next; + unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0)); + + /* + * Eliminate array allocation for f(1, *a, &arg) + * + * splatarray true + * getblockparamproxy + * send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT + * => + * splatarray false + * getblockparamproxy + * send + */ + if ((flag & VM_CALL_ARGS_BLOCKARG) & (flag & VM_CALL_ARGS_SPLAT) && !(flag & VM_CALL_KW_SPLAT)) { + OPERAND_AT(iobj, 0) = Qfalse; + } + } + } + else if (IS_NEXT_INSN_ID(niobj, duphash)) { niobj = niobj->next; /* @@ -3940,7 +3966,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal OPERAND_AT(iobj, 0) = Qfalse; } } - else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) { + else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) || + IS_NEXT_INSN_ID(niobj, getblockparamproxy)) { niobj = niobj->next; /* @@ -3948,12 +3975,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * * splatarray true * duphash - * getlocal / getinstancevariable + * getlocal / getinstancevariable / getblockparamproxy * send ARGS_SPLAT|KW_SPLAT|KW_SPLAT_MUT|ARGS_BLOCKARG * => * splatarray false * duphash - * getlocal / getinstancevariable + * getlocal / getinstancevariable / getblockparamproxy * send */ if (IS_NEXT_INSN_ID(niobj, send)) { |