[前][次][番号順一覧][スレッド一覧]

ruby-changes:64578

From: Marc-Andr=C3=A9 <ko1@a...>
Date: Fri, 25 Dec 2020 02:08:29 +0900 (JST)
Subject: [ruby-changes:64578] db2ebbd71b (master): Optimize calls to `Kernel#hash` (#3987)

https://git.ruby-lang.org/ruby.git/commit/?id=db2ebbd71b

From db2ebbd71b746734b88832b1e70db8afed3d68ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lafortune?= <github@m...>
Date: Thu, 24 Dec 2020 12:08:12 -0500
Subject: Optimize calls to `Kernel#hash` (#3987)

This avoids recursive checks when the `hash` method of an object
isn't specialized.

diff --git a/hash.c b/hash.c
index 9b4c315..c3a512b 100644
--- a/hash.c
+++ b/hash.c
@@ -142,7 +142,11 @@ hash_recursive(VALUE obj, VALUE arg, int recurse) https://github.com/ruby/ruby/blob/trunk/hash.c#L142
 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)) {
diff --git a/internal/vm.h b/internal/vm.h
index eb193a2..d36ed3d 100644
--- a/internal/vm.h
+++ b/internal/vm.h
@@ -74,6 +74,7 @@ VALUE rb_check_funcall_with_hook_kw(VALUE recv, ID mid, int argc, const VALUE *a https://github.com/ruby/ruby/blob/trunk/internal/vm.h#L74
                                  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,
diff --git a/vm_eval.c b/vm_eval.c
index b5ee1d2..94f3bac 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -937,6 +937,34 @@ rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat) https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L937
 }
 
 /*!
+ * 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.
  *
  * Same as rb_funcallv but this function can call only public methods.
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]