From 840e6b63077347be513037f083056886eaf90732 Mon Sep 17 00:00:00 2001 From: ko1 Date: Sun, 1 Nov 2015 08:17:25 +0000 Subject: [PATCH] * 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 --- ChangeLog | 5 +++++ id_table.c | 30 ++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b88dcb567..b0645b4f03 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sun Nov 1 17:14:36 2015 Koichi Sasada + + * id_table.c (mix_id_table_insert): do not touch list during + list->hash transition because GC can run during transition. + Sun Nov 1 11:07:31 2015 Eric Wong * iseq.c (iseq_memsize): account for rb_call_cache entries diff --git a/id_table.c b/id_table.c index cbfdef382f..ce00237832 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; iaux.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