[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]