summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--array.c33
-rw-r--r--hash.c28
-rw-r--r--range.c32
-rw-r--r--struct.c34
-rw-r--r--test/ruby/test_array.rb1
6 files changed, 53 insertions, 80 deletions
diff --git a/ChangeLog b/ChangeLog
index cc01861a29..92e929ab8a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Tue Dec 3 22:18:27 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_hash): detect recursion for all `hash' methods. each
+ `hash' methods no longer need to use rb_exec_recursive().
+
Tue Dec 3 21:53:15 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* vm_eval.c (rb_catch_protect): new function similar to
diff --git a/array.c b/array.c
index 7417a7c449..39144b25f4 100644
--- a/array.c
+++ b/array.c
@@ -3774,27 +3774,6 @@ rb_ary_eql(VALUE ary1, VALUE ary2)
return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
}
-static VALUE
-recursive_hash(VALUE ary, VALUE dummy, int recur)
-{
- long i;
- st_index_t h;
- VALUE n;
-
- h = rb_hash_start(RARRAY_LEN(ary));
- if (recur) {
- h = rb_hash_uint(h, NUM2LONG(rb_hash(rb_cArray)));
- }
- else {
- for (i=0; i<RARRAY_LEN(ary); i++) {
- n = rb_hash(RARRAY_AREF(ary, i));
- h = rb_hash_uint(h, NUM2LONG(n));
- }
- }
- h = rb_hash_end(h);
- return LONG2FIX(h);
-}
-
/*
* call-seq:
* ary.hash -> fixnum
@@ -3808,7 +3787,17 @@ recursive_hash(VALUE ary, VALUE dummy, int recur)
static VALUE
rb_ary_hash(VALUE ary)
{
- return rb_exec_recursive_paired(recursive_hash, ary, ary, 0);
+ long i;
+ st_index_t h;
+ VALUE n;
+
+ h = rb_hash_start(RARRAY_LEN(ary));
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ n = rb_hash(RARRAY_AREF(ary, i));
+ h = rb_hash_uint(h, NUM2LONG(n));
+ }
+ h = rb_hash_end(h);
+ return LONG2FIX(h);
}
/*
diff --git a/hash.c b/hash.c
index 6b24c61ce7..7d27c543d7 100644
--- a/hash.c
+++ b/hash.c
@@ -79,14 +79,17 @@ rb_any_cmp(VALUE a, VALUE b)
static VALUE
hash_recursive(VALUE obj, VALUE arg, int recurse)
{
- if (recurse) return INT2FIX(0);
+ if (recurse) {
+ /* TODO: break to call with the object which eql? to obj */
+ return INT2FIX(0);
+ }
return rb_funcallv(obj, id_hash, 0, 0);
}
VALUE
rb_hash(VALUE obj)
{
- VALUE hval = rb_exec_recursive(hash_recursive, obj, 0);
+ VALUE hval = rb_exec_recursive_paired(hash_recursive, obj, obj, 0);
retry:
switch (TYPE(hval)) {
case T_FIXNUM:
@@ -1959,20 +1962,6 @@ hash_i(VALUE key, VALUE val, VALUE arg)
return ST_CONTINUE;
}
-static VALUE
-recursive_hash(VALUE hash, VALUE dummy, int recur)
-{
- st_index_t hval = RHASH_SIZE(hash);
-
- if (!hval) return INT2FIX(0);
- if (recur)
- hval = rb_hash_uint(rb_hash_start(rb_hash(rb_cHash)), hval);
- else
- rb_hash_foreach(hash, hash_i, (VALUE)&hval);
- hval = rb_hash_end(hval);
- return INT2FIX(hval);
-}
-
/*
* call-seq:
* hsh.hash -> fixnum
@@ -1984,7 +1973,12 @@ recursive_hash(VALUE hash, VALUE dummy, int recur)
static VALUE
rb_hash_hash(VALUE hash)
{
- return rb_exec_recursive_paired(recursive_hash, hash, hash, 0);
+ st_index_t hval = RHASH_SIZE(hash);
+
+ if (!hval) return INT2FIX(0);
+ rb_hash_foreach(hash, hash_i, (VALUE)&hval);
+ hval = rb_hash_end(hval);
+ return INT2FIX(hval);
}
static int
diff --git a/range.c b/range.c
index ff40b52d93..4526dcba89 100644
--- a/range.c
+++ b/range.c
@@ -243,25 +243,6 @@ range_eql(VALUE range, VALUE obj)
return rb_exec_recursive_paired(recursive_eql, range, obj, obj);
}
-static VALUE
-recursive_hash(VALUE range, VALUE dummy, int recur)
-{
- st_index_t hash = EXCL(range);
- VALUE v;
-
- hash = rb_hash_start(hash);
- if (!recur) {
- v = rb_hash(RANGE_BEG(range));
- hash = rb_hash_uint(hash, NUM2LONG(v));
- v = rb_hash(RANGE_END(range));
- hash = rb_hash_uint(hash, NUM2LONG(v));
- }
- hash = rb_hash_uint(hash, EXCL(range) << 24);
- hash = rb_hash_end(hash);
-
- return LONG2FIX(hash);
-}
-
/*
* call-seq:
* rng.hash -> fixnum
@@ -274,7 +255,18 @@ recursive_hash(VALUE range, VALUE dummy, int recur)
static VALUE
range_hash(VALUE range)
{
- return rb_exec_recursive_paired(recursive_hash, range, range, 0);
+ st_index_t hash = EXCL(range);
+ VALUE v;
+
+ hash = rb_hash_start(hash);
+ v = rb_hash(RANGE_BEG(range));
+ hash = rb_hash_uint(hash, NUM2LONG(v));
+ v = rb_hash(RANGE_END(range));
+ hash = rb_hash_uint(hash, NUM2LONG(v));
+ hash = rb_hash_uint(hash, EXCL(range) << 24);
+ hash = rb_hash_end(hash);
+
+ return LONG2FIX(hash);
}
static void
diff --git a/struct.c b/struct.c
index bad339ffbb..6be512eaee 100644
--- a/struct.c
+++ b/struct.c
@@ -949,8 +949,15 @@ rb_struct_equal(VALUE s, VALUE s2)
return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
}
+/*
+ * call-seq:
+ * struct.hash -> fixnum
+ *
+ * Returns a hash value based on this struct's contents (see Object#hash).
+ */
+
static VALUE
-recursive_hash(VALUE s, VALUE dummy, int recur)
+rb_struct_hash(VALUE s)
{
long i, len;
st_index_t h;
@@ -958,31 +965,16 @@ recursive_hash(VALUE s, VALUE dummy, int recur)
const VALUE *ptr;
h = rb_hash_start(rb_hash(rb_obj_class(s)));
- if (!recur) {
- ptr = RSTRUCT_CONST_PTR(s);
- len = RSTRUCT_LEN(s);
- for (i = 0; i < len; i++) {
- n = rb_hash(ptr[i]);
- h = rb_hash_uint(h, NUM2LONG(n));
- }
+ ptr = RSTRUCT_CONST_PTR(s);
+ len = RSTRUCT_LEN(s);
+ for (i = 0; i < len; i++) {
+ n = rb_hash(ptr[i]);
+ h = rb_hash_uint(h, NUM2LONG(n));
}
h = rb_hash_end(h);
return INT2FIX(h);
}
-/*
- * call-seq:
- * struct.hash -> fixnum
- *
- * Returns a hash value based on this struct's contents (see Object#hash).
- */
-
-static VALUE
-rb_struct_hash(VALUE s)
-{
- return rb_exec_recursive_paired(recursive_hash, s, s, 0);
-}
-
static VALUE
recursive_eql(VALUE s, VALUE s2, int recur)
{
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 45013df412..d53b345898 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -2053,6 +2053,7 @@ class TestArray < Test::Unit::TestCase
assert_not_equal([[1]].hash, [[2]].hash)
a = []
a << a
+ assert_not_equal([a, 1].hash, [a, 2].hash)
assert_not_equal([a, a].hash, a.hash) # Implementation dependent
end