mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Optimize calls to Kernel#hash
(#3987)
This avoids recursive checks when the `hash` method of an object isn't specialized.
This commit is contained in:
parent
8981a63f12
commit
db2ebbd71b
Notes:
git
2020-12-25 02:08:37 +09:00
Merged-By: nurse <naruse@airemix.jp>
3 changed files with 34 additions and 1 deletions
6
hash.c
6
hash.c
|
@ -142,7 +142,11 @@ hash_recursive(VALUE obj, VALUE arg, int recurse)
|
|||
VALUE
|
||||
rb_hash(VALUE obj)
|
||||
{
|
||||
VALUE hval = rb_exec_recursive_outer(hash_recursive, obj, 0);
|
||||
VALUE hval = rb_check_funcall_basic_kw(obj, id_hash, rb_mKernel, 0, 0, 0);
|
||||
|
||||
if (hval == Qundef) {
|
||||
hval = rb_exec_recursive_outer(hash_recursive, obj, 0);
|
||||
}
|
||||
|
||||
while (!FIXNUM_P(hval)) {
|
||||
if (RB_TYPE_P(hval, T_BIGNUM)) {
|
||||
|
|
|
@ -74,6 +74,7 @@ VALUE rb_check_funcall_with_hook_kw(VALUE recv, ID mid, int argc, const VALUE *a
|
|||
rb_check_funcall_hook *hook, VALUE arg, int kw_splat);
|
||||
const char *rb_type_str(enum ruby_value_type type);
|
||||
VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE);
|
||||
VALUE rb_check_funcall_basic_kw(VALUE, ID, VALUE, int, const VALUE*, int);
|
||||
VALUE rb_yield_1(VALUE val);
|
||||
VALUE rb_yield_force_blockarg(VALUE values);
|
||||
VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
|
||||
|
|
28
vm_eval.c
28
vm_eval.c
|
@ -936,6 +936,34 @@ rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
|
|||
return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Calls a method only if it is the basic method of `ancestor`
|
||||
* otherwise returns Qundef;
|
||||
* \param recv receiver of the method
|
||||
* \param mid an ID that represents the name of the method
|
||||
* \param ancestor the Class that defined the basic method
|
||||
* \param argc the number of arguments
|
||||
* \param argv pointer to an array of method arguments
|
||||
* \param kw_splat bool
|
||||
*/
|
||||
VALUE
|
||||
rb_check_funcall_basic_kw(VALUE recv, ID mid, VALUE ancestor, int argc, const VALUE *argv, int kw_splat)
|
||||
{
|
||||
const rb_callable_method_entry_t *cme;
|
||||
rb_execution_context_t *ec;
|
||||
VALUE klass = CLASS_OF(recv);
|
||||
if (!klass) return Qundef; /* hidden object */
|
||||
|
||||
cme = rb_callable_method_entry(klass, mid);
|
||||
if (cme && METHOD_ENTRY_BASIC(cme) && RBASIC_CLASS(cme->defined_class) == ancestor) {
|
||||
ec = GET_EC();
|
||||
return rb_vm_call0(ec, recv, mid, argc, argv, cme, kw_splat);
|
||||
}
|
||||
|
||||
return Qundef;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Calls a method.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue