From ead0c5d356dd84acf3ad8a7f41f6b5bf2fb363c5 Mon Sep 17 00:00:00 2001 From: glass Date: Mon, 2 Dec 2013 12:59:31 +0000 Subject: * hash.c (rb_hash_rehash): make temporary st_table under the control of GC. [Bug #9187] * test/ruby/test_hash.rb: add a test for above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43957 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- hash.c | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) (limited to 'hash.c') diff --git a/hash.c b/hash.c index 8ceae61..6b5fca7 100644 --- a/hash.c +++ b/hash.c @@ -590,14 +590,6 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg) return ST_CONTINUE; } -static VALUE -rehash_func(VALUE arg) -{ - struct rehash_arg *p = (struct rehash_arg *)arg; - rb_hash_foreach(p->hash, rb_hash_rehash_i, (VALUE)p->tbl); - return Qnil; -} - /* * call-seq: * hsh.rehash -> hsh @@ -621,30 +613,23 @@ rehash_func(VALUE arg) static VALUE rb_hash_rehash(VALUE hash) { - int state; - struct rehash_arg arg; - st_table *new_tbl, *old_tbl = RHASH(hash)->ntbl; + VALUE tmp; + st_table *tbl; if (RHASH_ITER_LEV(hash) > 0) { rb_raise(rb_eRuntimeError, "rehash during iteration"); } rb_hash_modify_check(hash); - if (!old_tbl) return hash; - - new_tbl = st_init_table_with_size(old_tbl->type, old_tbl->num_entries); - arg.hash = hash; - arg.tbl = new_tbl; - - rb_protect(rehash_func, (VALUE)&arg, &state); - - if (state) { - st_free_table(new_tbl); - rb_jump_tag(state); - } - else { - st_free_table(RHASH(hash)->ntbl); - RHASH(hash)->ntbl = new_tbl; - } + if (!RHASH(hash)->ntbl) + return hash; + tmp = rb_hash_new(); + tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries); + RHASH(tmp)->ntbl = tbl; + + rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl); + st_free_table(RHASH(hash)->ntbl); + RHASH(hash)->ntbl = tbl; + RHASH(tmp)->ntbl = 0; return hash; } -- cgit v1.1