summaryrefslogtreecommitdiff
path: root/id_table.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-01 08:17:25 (GMT)
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-01 08:17:25 (GMT)
commit840e6b63077347be513037f083056886eaf90732 (patch)
tree837ac9def56d9f9c991bace21178dbbbc40fe7cc /id_table.c
parent9f37449f176d8943b765fc65c1adc5290e0f72ac (diff)
* id_table.c (mix_id_table_insert): do not touch list during
list->hash transition because GC can run during transition. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52421 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'id_table.c')
-rw-r--r--id_table.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/id_table.c b/id_table.c
index cbfdef3..ce00237 100644
--- a/id_table.c
+++ b/id_table.c
@@ -1427,7 +1427,8 @@ struct mix_id_table {
} aux;
};
-#define LIST_P(mix) ((mix)->aux.size.capa <= ID_TABLE_USE_MIX_LIST_MAX_CAPA)
+#define LIST_LIMIT_P(mix) ((mix)->aux.size.num == ID_TABLE_USE_MIX_LIST_MAX_CAPA)
+#define LIST_P(mix) ((mix)->aux.size.capa <= ID_TABLE_USE_MIX_LIST_MAX_CAPA)
static struct mix_id_table *
mix_id_table_create(size_t size)
@@ -1468,36 +1469,45 @@ mix_id_table_memsize(struct mix_id_table *tbl)
static int
mix_id_table_insert(struct mix_id_table *tbl, ID id, VALUE val)
{
- if (LIST_P(tbl)) {
- int r = list_id_table_insert(&tbl->aux.list, id, val);
+ int r;
- if (!LIST_P(tbl)) {
+ if (LIST_P(tbl)) {
+ if (!LIST_LIMIT_P(tbl)) {
+ r = list_id_table_insert(&tbl->aux.list, id, val);
+ }
+ else {
+ /* convert to hash */
/* overflow. TODO: this promotion should be done in list_extend_table */
struct list_id_table *list = &tbl->aux.list;
- struct hash_id_table *hash = &tbl->aux.hash;
+ struct hash_id_table hash_body;
id_key_t *keys = list->keys;
VALUE *values = TABLE_VALUES(list);
const int num = list->num;
int i;
- hash_id_table_init(hash, 0);
+ hash_id_table_init(&hash_body, 0);
for (i=0; i<num; i++) {
- hash_id_table_insert_key(hash, keys[i], values[i]);
+ /* note that GC can run */
+ hash_id_table_insert_key(&hash_body, keys[i], values[i]);
}
+ tbl->aux.hash = hash_body;
+
/* free list keys/values */
xfree(keys);
#if ID_TABLE_USE_CALC_VALUES == 0
xfree(values);
#endif
- assert(LIST_P(tbl) == 0);
+ goto hash_insert;
}
- return r;
}
else {
- return hash_id_table_insert(&tbl->aux.hash, id, val);
+ hash_insert:
+ r = hash_id_table_insert(&tbl->aux.hash, id, val);
+ assert(!LIST_P(tbl));
}
+ return r;
}
static int