diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-03-09 07:17:01 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-03-09 07:17:01 +0000 |
commit | 865a326da921f2f5ed0def0605aec3a54981612d (patch) | |
tree | f0fb0ec1d77f8da0a43b843847b284a78bbc02c1 /hash.c | |
parent | f937d32f3f4de638ec8081085d31d6d95bfa8f0b (diff) | |
download | ruby-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.c | 41 |
1 files changed, 22 insertions, 19 deletions
@@ -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; } |