diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-12-03 13:18:30 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-12-03 13:18:30 +0000 |
commit | 6f2efe84fb6169a03ed191606935a40640d6764c (patch) | |
tree | c32c3b4d48daeafb526c4e8d37fe0e9870956129 | |
parent | c7159e81fc0d70b67358deaa39d21babbc3d89e7 (diff) |
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
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | array.c | 33 | ||||
-rw-r--r-- | hash.c | 28 | ||||
-rw-r--r-- | range.c | 32 | ||||
-rw-r--r-- | struct.c | 34 | ||||
-rw-r--r-- | test/ruby/test_array.rb | 1 |
6 files changed, 53 insertions, 80 deletions
@@ -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 @@ -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); } /* @@ -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 @@ -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 @@ -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 |