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

ruby-changes:61449

From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Tue, 2 Jun 2020 12:38:17 +0900 (JST)
Subject: [ruby-changes:61449] 40ced763b4 (master): vm_insnhelper.c: merge opt_eq_func / opt_eql_func

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

From 40ced763b4f97dd3bc3abfd4cb16580f7cf8e898 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?=
 <shyouhei@r...>
Date: Fri, 29 May 2020 17:42:23 +0900
Subject: vm_insnhelper.c: merge opt_eq_func / opt_eql_func

These two function were almost identical, except in case of
T_STRING/T_FLOAT. Why not merge them into one, and let the difference be
handled in normal method calls (slowpath).  This does not improve
runtime performance for me, but at least reduces for instance rb_eql_opt
from 653 bytes to 86 bytes on my machine, according to nm(1).

diff --git a/insns.def b/insns.def
index 58349b0..ba95655 100644
--- a/insns.def
+++ b/insns.def
@@ -1168,7 +1168,7 @@ opt_eq https://github.com/ruby/ruby/blob/trunk/insns.def#L1168
 (VALUE recv, VALUE obj)
 (VALUE val)
 {
-    val = opt_eq_func(GET_ISEQ(), recv, obj, cd);
+    val = opt_equality(GET_ISEQ(), recv, obj, cd);
 
     if (val == Qundef) {
         CALL_SIMPLE_METHOD();
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index cb55d0f..f6e3795 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1669,17 +1669,6 @@ vm_method_cfunc_is(const rb_iseq_t *iseq, CALL_DATA cd, VALUE recv, VALUE (*func https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1669
     return check_cfunc(vm_cc_cme(cd->cc), func);
 }
 
-static VALUE
-opt_equal_fallback(const rb_iseq_t *iseq, VALUE recv, VALUE obj, CALL_DATA cd)
-{
-    if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_equal)) {
-	return recv == obj ? Qtrue : Qfalse;
-    }
-
-    return Qundef;
-}
-
-#define BUILTIN_CLASS_P(x, k) (!SPECIAL_CONST_P(x) && RBASIC_CLASS(x) == k)
 #define EQ_UNREDEFINED_P(t) BASIC_OP_UNREDEFINED_P(BOP_EQ, t##_REDEFINED_OP_FLAG)
 
 static inline bool
@@ -1711,83 +1700,64 @@ FLONUM_2_P(VALUE a, VALUE b) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1700
 #endif
 }
 
-/* 1: compare by identity, 0: not applicable, -1: redefined */
-static inline int
-comparable_by_identity(VALUE recv, VALUE obj)
+static VALUE
+opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd)
 {
-    if (FIXNUM_2_P(recv, obj)) {
-	return (EQ_UNREDEFINED_P(INTEGER) != 0) * 2 - 1;
+    if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) {
+        goto compare_by_identity;
     }
-    if (FLONUM_2_P(recv, obj)) {
-	return (EQ_UNREDEFINED_P(FLOAT) != 0) * 2 - 1;
+    else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) {
+        goto compare_by_identity;
     }
-    if (SYMBOL_P(recv) && SYMBOL_P(obj)) {
-	return (EQ_UNREDEFINED_P(SYMBOL) != 0) * 2 - 1;
+    else if (STATIC_SYM_P(recv) && STATIC_SYM_P(obj) && EQ_UNREDEFINED_P(SYMBOL)) {
+        goto compare_by_identity;
     }
-    return 0;
-}
+    else if (SPECIAL_CONST_P(recv)) {
+        goto compare_by_funcall;
+    }
+    else if (RBASIC_CLASS(recv) == rb_cFloat && RB_FLOAT_TYPE_P(obj) && EQ_UNREDEFINED_P(FLOAT)) {
+        double a = RFLOAT_VALUE(recv);
+        double b = RFLOAT_VALUE(obj);
 
-static
-#ifndef NO_BIG_INLINE
-inline
+#if MSC_VERSION_BEFORE(1300)
+        if (isnan(a)) {
+            return Qfalse;
+        }
+        else if (isnan(b)) {
+            return Qfalse;
+        }
+        else
 #endif
-VALUE
-opt_eq_func(const rb_iseq_t *iseq, VALUE recv, VALUE obj, CALL_DATA cd)
-{
-    switch (comparable_by_identity(recv, obj)) {
-      case 1:
-	return (recv == obj) ? Qtrue : Qfalse;
-      case -1:
-	goto fallback;
-    }
-    if (0) {
-    }
-    else if (BUILTIN_CLASS_P(recv, rb_cFloat)) {
-	if (EQ_UNREDEFINED_P(FLOAT)) {
-	    return rb_float_equal(recv, obj);
-	}
+        if (a == b) {
+            return Qtrue;
+        }
+        else {
+            return Qfalse;
+        }
     }
-    else if (BUILTIN_CLASS_P(recv, rb_cString) && EQ_UNREDEFINED_P(STRING)) {
-        if (recv == obj) return Qtrue;
-        if (RB_TYPE_P(obj, T_STRING)) {
-            return rb_str_eql_internal(recv, obj);
+    else if (RBASIC_CLASS(recv) == rb_cString && EQ_UNREDEFINED_P(STRING)) {
+        if (recv == obj) {
+            return Qtrue;
+        }
+        else if (RB_TYPE_P(obj, T_STRING)) {
+            return rb_str_eql_internal(obj, recv);
         }
     }
 
-  fallback:
-    return opt_equal_fallback(iseq, recv, obj, cd);
-}
-
-static
-#ifndef NO_BIG_INLINE
-inline
-#endif
-VALUE
-opt_eql_func(VALUE recv, VALUE obj, CALL_DATA cd)
-{
-    switch (comparable_by_identity(recv, obj)) {
-      case 1:
-	return (recv == obj) ? Qtrue : Qfalse;
-      case -1:
-	goto fallback;
-    }
-    if (0) {
+  compare_by_funcall:
+    if (! vm_method_cfunc_is(cd_owner, cd, recv, rb_obj_equal)) {
+        return Qundef;
     }
-    else if (BUILTIN_CLASS_P(recv, rb_cFloat)) {
-	if (EQ_UNREDEFINED_P(FLOAT)) {
-	    return rb_float_eql(recv, obj);
-	}
+
+  compare_by_identity:
+    if (recv == obj) {
+        return Qtrue;
     }
-    else if (BUILTIN_CLASS_P(recv, rb_cString)) {
-	if (EQ_UNREDEFINED_P(STRING)) {
-	    return rb_str_eql(recv, obj);
-	}
+    else {
+        return Qfalse;
     }
-
-  fallback:
-    return opt_equal_fallback(NULL, recv, obj, cd);
 }
-#undef BUILTIN_CLASS_P
+
 #undef EQ_UNREDEFINED_P
 
 #define vm_ci_new_id(mid) vm_ci_new_runtime(mid, 0, 0, NULL)
@@ -1802,14 +1772,14 @@ rb_equal_opt(VALUE obj1, VALUE obj2) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1772
     }
 
     struct rb_call_data cd = { .ci = ci, .cc = vm_cc_empty() };
-    return opt_eq_func(NULL, obj1, obj2, &cd);
+    return opt_equality(NULL, obj1, obj2, &cd);
 }
 
 VALUE
 rb_eql_opt(VALUE obj1, VALUE obj2)
 {
     struct rb_call_data cd = { .ci = vm_ci_new_id(idEqlP), .cc = vm_cc_empty() };
-    return opt_eql_func(obj1, obj2, &cd);
+    return opt_equality(NULL, obj1, obj2, &cd);
 }
 
 extern VALUE rb_vm_call0(rb_execution_context_t *ec, VALUE, ID, int, const VALUE*, const rb_callable_method_entry_t *, int kw_splat);
@@ -4448,7 +4418,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L4418
 vm_opt_neq(const rb_iseq_t *iseq, CALL_DATA cd, CALL_DATA cd_eq, VALUE recv, VALUE obj)
 {
     if (vm_method_cfunc_is(iseq, cd, recv, rb_obj_not_equal)) {
-        VALUE val = opt_eq_func(iseq, recv, obj, cd_eq);
+        VALUE val = opt_equality(iseq, recv, obj, cd_eq);
 
 	if (val != Qundef) {
 	    return RTEST(val) ? Qfalse : Qtrue;
-- 
cgit v0.10.2


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

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