summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-03-09 07:17:01 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-03-09 07:17:01 +0000
commit865a326da921f2f5ed0def0605aec3a54981612d (patch)
treef0fb0ec1d77f8da0a43b843847b284a78bbc02c1 /hash.c
parentf937d32f3f4de638ec8081085d31d6d95bfa8f0b (diff)
downloadruby-865a326da921f2f5ed0def0605aec3a54981612d.tar.gz
hash.c: make duplicated hash WB protected
* hash.c (hash_alloc_flags): allocate new hash with the flags and the default value. * hash.c (hash_dup): duplicate with the flags and the default value. * hash.c (rb_hash_dup): make the duplicated hash write-barrier protected. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54055 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/hash.c b/hash.c
index 7a4ed733d1..400c330743 100644
--- a/hash.c
+++ b/hash.c
@@ -369,16 +369,23 @@ rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
}
static VALUE
-hash_alloc(VALUE klass)
+hash_alloc_flags(VALUE klass, VALUE flags, VALUE ifnone)
{
- NEWOBJ_OF(hash, struct RHash, klass, T_HASH | (RGENGC_WB_PROTECTED_HASH ? FL_WB_PROTECTED : 0));
+ const VALUE wb = (RGENGC_WB_PROTECTED_HASH ? FL_WB_PROTECTED : 0);
+ NEWOBJ_OF(hash, struct RHash, klass, T_HASH | wb | flags);
- RHASH_SET_IFNONE((VALUE)hash, Qnil);
+ RHASH_SET_IFNONE((VALUE)hash, ifnone);
return (VALUE)hash;
}
static VALUE
+hash_alloc(VALUE klass)
+{
+ return hash_alloc_flags(klass, 0, Qnil);
+}
+
+static VALUE
empty_hash_alloc(VALUE klass)
{
RUBY_DTRACE_CREATE_HOOK(HASH, 0);
@@ -392,28 +399,24 @@ rb_hash_new(void)
return hash_alloc(rb_cHash);
}
-static inline VALUE
-rb_hash_dup_empty(VALUE hash)
+static VALUE
+hash_dup(VALUE hash, VALUE klass, VALUE flags)
{
- NEWOBJ_OF(ret, struct RHash,
- rb_obj_class(hash),
- (RBASIC(hash)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT));
- if (FL_TEST((hash), FL_EXIVAR))
- rb_copy_generic_ivar((VALUE)(ret),(VALUE)(hash));
-
- if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
- FL_SET(ret, HASH_PROC_DEFAULT);
- }
- RHASH_SET_IFNONE(ret, RHASH_IFNONE(hash));
- return (VALUE)ret;
+ VALUE ret = hash_alloc_flags(klass, flags,
+ RHASH_IFNONE(hash));
+ if (!RHASH_EMPTY_P(hash))
+ RHASH(ret)->ntbl = st_copy(RHASH(hash)->ntbl);
+ return ret;
}
VALUE
rb_hash_dup(VALUE hash)
{
- VALUE ret = rb_hash_dup_empty(hash);
- if (!RHASH_EMPTY_P(hash))
- RHASH(ret)->ntbl = st_copy(RHASH(hash)->ntbl);
+ const VALUE flags = RBASIC(hash)->flags;
+ VALUE ret = hash_dup(hash, rb_obj_class(hash),
+ flags & (FL_EXIVAR|FL_TAINT|HASH_PROC_DEFAULT));
+ if (flags & FL_EXIVAR)
+ rb_copy_generic_ivar(ret, hash);
return ret;
}