summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorglass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-02 12:59:31 +0000
committerglass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-02 12:59:31 +0000
commitead0c5d356dd84acf3ad8a7f41f6b5bf2fb363c5 (patch)
tree5b65804464e28e99810adc0354872ec4d796708c /hash.c
parent39a8519a569bd2190422c4a340950ccd5bbc7f04 (diff)
* 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.c39
1 files changed, 12 insertions, 27 deletions
diff --git a/hash.c b/hash.c
index 8ceae61d29..6b5fca7e41 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;
}