summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2022-06-06 17:27:56 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2023-04-18 17:16:22 -0700
commitc5fc1ce975ecdf1c6818714e47579c5d3531c4ca (patch)
tree77a0f348d00a99281f826dac90e1d288c3139051 /compile.c
parent3016f30c956413268655dcb25dbe5041684f9528 (diff)
downloadruby-c5fc1ce975ecdf1c6818714e47579c5d3531c4ca.tar.gz
Emit special instruction for array literal + .(hash|min|max)
This commit introduces a new instruction `opt_newarray_send` which is used when there is an array literal followed by either the `hash`, `min`, or `max` method. ``` [a, b, c].hash ``` Will emit an `opt_newarray_send` instruction. This instruction falls back to a method call if the "interested" method has been monkey patched. Here are some examples of the instructions generated: ``` $ ./miniruby --dump=insns -e '[@a, @b].max' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,12)> (catch: FALSE) 0000 getinstancevariable :@a, <is:0> ( 1)[Li] 0003 getinstancevariable :@b, <is:1> 0006 opt_newarray_send 2, :max 0009 leave $ ./miniruby --dump=insns -e '[@a, @b].min' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,12)> (catch: FALSE) 0000 getinstancevariable :@a, <is:0> ( 1)[Li] 0003 getinstancevariable :@b, <is:1> 0006 opt_newarray_send 2, :min 0009 leave $ ./miniruby --dump=insns -e '[@a, @b].hash' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,13)> (catch: FALSE) 0000 getinstancevariable :@a, <is:0> ( 1)[Li] 0003 getinstancevariable :@b, <is:1> 0006 opt_newarray_send 2, :hash 0009 leave ``` [Feature #18897] [ruby-core:109147] Co-authored-by: John Hawthorn <jhawthorn@github.com>
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/compile.c b/compile.c
index 819137006c..be5fd9c345 100644
--- a/compile.c
+++ b/compile.c
@@ -3706,18 +3706,23 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
if (IS_INSN_ID(niobj, send)) {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(niobj, 0);
if ((vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) && vm_ci_argc(ci) == 0) {
- switch (vm_ci_mid(ci)) {
- case idMax:
- iobj->insn_id = BIN(opt_newarray_max);
- ELEM_REMOVE(&niobj->link);
- return COMPILE_OK;
- case idMin:
- iobj->insn_id = BIN(opt_newarray_min);
- ELEM_REMOVE(&niobj->link);
- return COMPILE_OK;
- }
- }
- }
+ switch (vm_ci_mid(ci)) {
+ case idMax:
+ case idMin:
+ case idHash:
+ {
+ rb_num_t num = (rb_num_t)iobj->operands[0];
+ iobj->insn_id = BIN(opt_newarray_send);
+ iobj->operands = compile_data_calloc2(iseq, insn_len(iobj->insn_id) - 1, sizeof(VALUE));
+ iobj->operands[0] = (VALUE)num;
+ iobj->operands[1] = (VALUE)rb_id2sym(vm_ci_mid(ci));
+ iobj->operand_size = insn_len(iobj->insn_id) - 1;
+ ELEM_REMOVE(&niobj->link);
+ return COMPILE_OK;
+ }
+ }
+ }
+ }
}
if (IS_INSN_ID(iobj, send)) {