aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--insns.def4
-rw-r--r--internal.h16
-rw-r--r--string.c20
-rw-r--r--vm_insnhelper.c9
4 files changed, 25 insertions, 24 deletions
diff --git a/insns.def b/insns.def
index 7c93af6e4d..e91382d6c6 100644
--- a/insns.def
+++ b/insns.def
@@ -1161,7 +1161,7 @@ opt_eq
/* This instruction can compare a string with non-string. This
* (somewhat) coerces the non-string into a string, via a method
* call. */
-// attr bool leaf = false; /* has rb_str_equal() */
+// attr bool leaf = true;
{
val = opt_eq_func(recv, obj, ci, cc);
@@ -1177,7 +1177,7 @@ opt_neq
(VALUE recv, VALUE obj)
(VALUE val)
/* Same discussion as opt_eq. */
-// attr bool leaf = false; /* has rb_str_equal() */
+// attr bool leaf = true;
{
val = vm_opt_neq(ci, cc, ci_eq, cc_eq, recv, obj);
diff --git a/internal.h b/internal.h
index 5ecb229413..d391597d54 100644
--- a/internal.h
+++ b/internal.h
@@ -2125,6 +2125,22 @@ VALUE rb_str_eql(VALUE str1, VALUE str2);
VALUE rb_obj_as_string_result(VALUE str, VALUE obj);
const char *ruby_escaped_char(int c);
+/* expect tail call optimization */
+static inline VALUE
+rb_str_eql_internal(const VALUE str1, const VALUE str2)
+{
+ const long len = RSTRING_LEN(str1);
+ const char *ptr1, *ptr2;
+
+ if (len != RSTRING_LEN(str2)) return Qfalse;
+ if (!rb_str_comparable(str1, str2)) return Qfalse;
+ if ((ptr1 = RSTRING_PTR(str1)) == (ptr2 = RSTRING_PTR(str2)))
+ return Qtrue;
+ if (memcmp(ptr1, ptr2, len) == 0)
+ return Qtrue;
+ return Qfalse;
+}
+
/* symbol.c */
#ifdef RUBY_ENCODING_H
VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc);
diff --git a/string.c b/string.c
index edcb6aad78..6cef5ab157 100644
--- a/string.c
+++ b/string.c
@@ -3258,22 +3258,6 @@ rb_str_cmp(VALUE str1, VALUE str2)
return -1;
}
-/* expect tail call optimization */
-static VALUE
-str_eql(const VALUE str1, const VALUE str2)
-{
- const long len = RSTRING_LEN(str1);
- const char *ptr1, *ptr2;
-
- if (len != RSTRING_LEN(str2)) return Qfalse;
- if (!rb_str_comparable(str1, str2)) return Qfalse;
- if ((ptr1 = RSTRING_PTR(str1)) == (ptr2 = RSTRING_PTR(str2)))
- return Qtrue;
- if (memcmp(ptr1, ptr2, len) == 0)
- return Qtrue;
- return Qfalse;
-}
-
/*
* call-seq:
* str == obj -> true or false
@@ -3297,7 +3281,7 @@ rb_str_equal(VALUE str1, VALUE str2)
}
return rb_equal(str2, str1);
}
- return str_eql(str1, str2);
+ return rb_str_eql_internal(str1, str2);
}
/*
@@ -3312,7 +3296,7 @@ rb_str_eql(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (!RB_TYPE_P(str2, T_STRING)) return Qfalse;
- return str_eql(str1, str2);
+ return rb_str_eql_internal(str1, str2);
}
/*
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 1875d35de1..e68ded7d15 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1506,10 +1506,11 @@ opt_eq_func(VALUE recv, VALUE obj, CALL_INFO ci, CALL_CACHE cc)
return rb_float_equal(recv, obj);
}
}
- else if (BUILTIN_CLASS_P(recv, rb_cString)) {
- if (EQ_UNREDEFINED_P(STRING)) {
- return rb_str_equal(recv, obj);
- }
+ 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);
+ }
}
fallback: