diff options
author | glass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-12-02 12:59:31 +0000 |
---|---|---|
committer | glass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-12-02 12:59:31 +0000 |
commit | ead0c5d356dd84acf3ad8a7f41f6b5bf2fb363c5 (patch) | |
tree | 5b65804464e28e99810adc0354872ec4d796708c /hash.c | |
parent | 39a8519a569bd2190422c4a340950ccd5bbc7f04 (diff) | |
download | ruby-ead0c5d356dd84acf3ad8a7f41f6b5bf2fb363c5.tar.gz |
* 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
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 39 |
1 files changed, 12 insertions, 27 deletions
@@ -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; } |