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
This commit is contained in:
nobu 2016-03-09 07:17:01 +00:00
Родитель f937d32f3f
Коммит 865a326da9
1 изменённых файлов: 22 добавлений и 19 удалений

41
hash.c
Просмотреть файл

@ -369,15 +369,22 @@ 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)
{
@ -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;
}