ruby-changes:40340
From: ko1 <ko1@a...>
Date: Sun, 1 Nov 2015 17:17:42 +0900 (JST)
Subject: [ruby-changes:40340] ko1:r52421 (trunk): * id_table.c (mix_id_table_insert): do not touch list during
ko1 2015-11-01 17:17:25 +0900 (Sun, 01 Nov 2015) New Revision: 52421 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=52421 Log: * id_table.c (mix_id_table_insert): do not touch list during list->hash transition because GC can run during transition. Modified files: trunk/ChangeLog trunk/id_table.c Index: id_table.c =================================================================== --- id_table.c (revision 52420) +++ id_table.c (revision 52421) @@ -1427,7 +1427,8 @@ struct mix_id_table { https://github.com/ruby/ruby/blob/trunk/id_table.c#L1427 } 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 https://github.com/ruby/ruby/blob/trunk/id_table.c#L1469 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 Index: ChangeLog =================================================================== --- ChangeLog (revision 52420) +++ ChangeLog (revision 52421) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun Nov 1 17:14:36 2015 Koichi Sasada <ko1@a...> + + * 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 <e@8...> * iseq.c (iseq_memsize): account for rb_call_cache entries -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/