From 6f2efe84fb6169a03ed191606935a40640d6764c Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 3 Dec 2013 13:18:30 +0000 Subject: hash.c: detect recursion for all * hash.c (rb_hash): detect recursion for all `hash' methods. each `hash' methods no longer need to use rb_exec_recursive(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43980 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ array.c | 33 +++++++++++---------------------- hash.c | 28 +++++++++++----------------- range.c | 32 ++++++++++++-------------------- struct.c | 34 +++++++++++++--------------------- test/ruby/test_array.rb | 1 + 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 + + * 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 * 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 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 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 -- cgit v1.2.3