summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-05-29 01:38:52 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-05-29 01:38:52 +0000
commit68f96f6c3c05385a5b47395b82e619f9c06b0437 (patch)
tree452bc8b75a29b2bc5741cf183af37ea46cb02307 /hash.c
parent1999571e60d301e01dc4ff041f31ac58ae89fa38 (diff)
* hash.c: fix WB bug.
(1) Hash's key also needs WB. (2) callback parameter *key and *value of st_update() is not a storage of st_table itself (only local variable). So that OBJ_WRITE() is not suitable, especially for `!exsinting'. OBJ_WRITTEN() is used instead of OBJ_WRITE(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/hash.c b/hash.c
index 67759b61cd..a8950efdce 100644
--- a/hash.c
+++ b/hash.c
@@ -1193,14 +1193,23 @@ rb_hash_clear(VALUE hash)
static int
hash_aset(VALUE hash, st_data_t *key, st_data_t *val, st_data_t arg, int existing)
{
- OBJ_WRITE(hash, (VALUE *)val, arg);
+ if (existing) {
+ OBJ_WRITTEN(hash, *val, arg);
+ }
+ else {
+ OBJ_WRITTEN(hash, Qundef, *key);
+ OBJ_WRITTEN(hash, Qundef, arg);
+ }
+ *val = arg;
return ST_CONTINUE;
}
static int
hash_aset_str(VALUE hash, st_data_t *key, st_data_t *val, st_data_t arg, int existing)
{
- OBJ_WRITE(hash, (VALUE *)key, rb_str_new_frozen((VALUE)*key));
+ if (!existing) {
+ *key = rb_str_new_frozen((VALUE)*key);
+ }
return hash_aset(hash, key, val, arg, existing);
}
@@ -1879,7 +1888,14 @@ rb_hash_invert(VALUE hash)
static int
rb_hash_update_callback(VALUE hash, st_data_t *key, st_data_t *value, st_data_t arg, int existing)
{
- OBJ_WRITE(hash, (VALUE *)value, (VALUE)arg);
+ if (existing) {
+ OBJ_WRITTEN(hash, *value, arg);
+ }
+ else {
+ OBJ_WRITTEN(hash, Qundef, *key);
+ OBJ_WRITTEN(hash, Qundef, arg);
+ }
+ *value = arg;
return ST_CONTINUE;
}
@@ -1896,10 +1912,16 @@ static int
rb_hash_update_block_callback(VALUE hash, st_data_t *key, st_data_t *value, st_data_t arg, int existing)
{
VALUE newvalue = (VALUE)arg;
+
if (existing) {
newvalue = rb_yield_values(3, (VALUE)*key, (VALUE)*value, newvalue);
+ OBJ_WRITTEN(hash, *value, newvalue);
}
- OBJ_WRITE(hash, (VALUE *)value, newvalue);
+ else {
+ OBJ_WRITTEN(hash, Qundef, *key);
+ OBJ_WRITTEN(hash, Qundef, newvalue);
+ }
+ *value = newvalue;
return ST_CONTINUE;
}
@@ -1962,8 +1984,13 @@ rb_hash_update_func_callback(VALUE hash, st_data_t *key, st_data_t *value, st_da
VALUE newvalue = arg->value;
if (existing) {
newvalue = (*arg->func)((VALUE)*key, (VALUE)*value, newvalue);
+ OBJ_WRITTEN(hash, *value, newvalue);
+ }
+ else {
+ OBJ_WRITTEN(hash, Qundef, *key);
+ OBJ_WRITTEN(hash, Qundef, newvalue);
}
- OBJ_WRITE(hash, (VALUE *)value, (VALUE)newvalue);
+ *value = newvalue;
return ST_CONTINUE;
}