Optimize Hash methods with Kernel#hash (#10160)
This commit is contained in:
parent
6f31dd495c
commit
70de3b170b
5
benchmark/hash_key.yml
Normal file
5
benchmark/hash_key.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
prelude: |
|
||||||
|
obj = Object.new
|
||||||
|
hash = { obj => true }
|
||||||
|
benchmark: hash.key?(obj)
|
||||||
|
loop_count: 30000000
|
18
hash.c
18
hash.c
@ -210,10 +210,26 @@ any_hash(VALUE a, st_index_t (*other_func)(VALUE))
|
|||||||
return (long)hnum;
|
return (long)hnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE rb_obj_hash(VALUE obj);
|
||||||
|
VALUE rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *cme, int kw_splat);
|
||||||
|
|
||||||
static st_index_t
|
static st_index_t
|
||||||
obj_any_hash(VALUE obj)
|
obj_any_hash(VALUE obj)
|
||||||
{
|
{
|
||||||
VALUE hval = rb_check_funcall_basic_kw(obj, id_hash, rb_mKernel, 0, 0, 0);
|
VALUE hval = Qundef;
|
||||||
|
VALUE klass = CLASS_OF(obj);
|
||||||
|
if (klass) {
|
||||||
|
const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, id_hash);
|
||||||
|
if (cme && METHOD_ENTRY_BASIC(cme) && RBASIC_CLASS(cme->defined_class) == rb_mKernel) {
|
||||||
|
// Optimize away the frame push overhead if it's the default Kernel#hash
|
||||||
|
if (cme->def->type == VM_METHOD_TYPE_CFUNC && cme->def->body.cfunc.func == (VALUE (*)(ANYARGS))rb_obj_hash) {
|
||||||
|
hval = rb_obj_hash(obj);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hval = rb_vm_call0(GET_EC(), obj, id_hash, 0, 0, cme, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (UNDEF_P(hval)) {
|
if (UNDEF_P(hval)) {
|
||||||
hval = rb_exec_recursive_outer_mid(hash_recursive, obj, 0, id_hash);
|
hval = rb_exec_recursive_outer_mid(hash_recursive, obj, 0, id_hash);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user