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>
This commit is contained in:
Aaron Patterson 2022-06-06 17:27:56 -07:00 committed by Aaron Patterson
parent 3016f30c95
commit c5fc1ce975
Notes: git 2023-04-19 00:16:56 +00:00
9 changed files with 75 additions and 45 deletions

View file

@ -899,8 +899,8 @@ opt_str_uminus
}
DEFINE_INSN
opt_newarray_max
(rb_num_t num)
opt_newarray_send
(rb_num_t num, ID method)
(...)
(VALUE val)
/* This instruction typically has no funcalls. But it compares array
@ -909,20 +909,21 @@ opt_newarray_max
* cannot but mark it being not leaf. */
// attr bool leaf = false; /* has rb_funcall() */
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
// attr rb_snum_t comptime_sp_inc = 1 - (rb_snum_t)num;
{
val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num));
}
DEFINE_INSN
opt_newarray_min
(rb_num_t num)
(...)
(VALUE val)
/* Same discussion as opt_newarray_max. */
// attr bool leaf = false; /* has rb_funcall() */
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
{
val = vm_opt_newarray_min(ec, num, STACK_ADDR_FROM_TOP(num));
switch(method) {
case idHash:
val = vm_opt_newarray_hash(ec, num, STACK_ADDR_FROM_TOP(num));
break;
case idMin:
val = vm_opt_newarray_min(ec, num, STACK_ADDR_FROM_TOP(num));
break;
case idMax:
val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num));
break;
default:
rb_bug("unreachable");
}
}
/* super(args) # args.size => num */