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

ruby-changes:71423

From: John <ko1@a...>
Date: Wed, 16 Mar 2022 00:50:15 +0900 (JST)
Subject: [ruby-changes:71423] d76ba1c219 (master): Fast rb_class_inherited_p

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

From d76ba1c219d9ab2cb74b4b1de2e467e085150c1b Mon Sep 17 00:00:00 2001
From: John Hawthorn <john@h...>
Date: Sat, 5 Mar 2022 13:03:33 -0800
Subject: Fast rb_class_inherited_p

This uses the superclass table recently introduced to implement fast
inheritance checking between classes (ex. Foo < Bar).

This is almost identical to what we do in class_search_class_ancestor
(as called by rb_obj_is_kind_of) except that we are checking both
directions: ie. both whether Foo < Bar and whether Bar < Foo.
---
 object.c | 41 +++++++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/object.c b/object.c
index a1093463c4..f6736fbe8b 100644
--- a/object.c
+++ b/object.c
@@ -1633,17 +1633,38 @@ VALUE https://github.com/ruby/ruby/blob/trunk/object.c#L1633
 rb_class_inherited_p(VALUE mod, VALUE arg)
 {
     if (mod == arg) return Qtrue;
-    if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) {
-	rb_raise(rb_eTypeError, "compared with non class/module");
-    }
-    if (class_search_ancestor(mod, RCLASS_ORIGIN(arg))) {
-	return Qtrue;
-    }
-    /* not mod < arg; check if mod > arg */
-    if (class_search_ancestor(arg, mod)) {
-	return Qfalse;
+
+    if (RB_TYPE_P(arg, T_CLASS) && RB_TYPE_P(mod, T_CLASS)) {
+        // comparison between classes
+        size_t mod_depth = RCLASS_SUPERCLASS_DEPTH(mod);
+        size_t arg_depth = RCLASS_SUPERCLASS_DEPTH(arg);
+        if (arg_depth < mod_depth) {
+            // check if mod < arg
+            return RCLASS_SUPERCLASSES(mod)[arg_depth] == arg ?
+                Qtrue :
+                Qnil;
+        } else if (arg_depth > mod_depth) {
+            // check if mod > arg
+            return RCLASS_SUPERCLASSES(arg)[mod_depth] == mod ?
+                Qfalse :
+                Qnil;
+        } else {
+            // Depths match, and we know they aren't equal: no relation
+            return Qnil;
+        }
+    } else {
+        if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) {
+            rb_raise(rb_eTypeError, "compared with non class/module");
+        }
+        if (class_search_ancestor(mod, RCLASS_ORIGIN(arg))) {
+            return Qtrue;
+        }
+        /* not mod < arg; check if mod > arg */
+        if (class_search_ancestor(arg, mod)) {
+            return Qfalse;
+        }
+        return Qnil;
     }
-    return Qnil;
 }
 
 /*
-- 
cgit v1.2.1


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

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