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

30
array.c
View file

@ -5350,6 +5350,23 @@ rb_ary_eql(VALUE ary1, VALUE ary2)
return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
}
VALUE
rb_ary_hash_values(long len, const VALUE *elements)
{
long i;
st_index_t h;
VALUE n;
h = rb_hash_start(len);
h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
for (i=0; i<len; i++) {
n = rb_hash(elements[i]);
h = rb_hash_uint(h, NUM2LONG(n));
}
h = rb_hash_end(h);
return ST2FIX(h);
}
/*
* call-seq:
* array.hash -> integer
@ -5366,18 +5383,7 @@ rb_ary_eql(VALUE ary1, VALUE ary2)
static VALUE
rb_ary_hash(VALUE ary)
{
long i;
st_index_t h;
VALUE n;
h = rb_hash_start(RARRAY_LEN(ary));
h = rb_hash_uint(h, (st_index_t)rb_ary_hash);
for (i=0; i<RARRAY_LEN(ary); i++) {
n = rb_hash(RARRAY_AREF(ary, i));
h = rb_hash_uint(h, NUM2LONG(n));
}
h = rb_hash_end(h);
return ST2FIX(h);
return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
}
/*