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

ruby-changes:22915

From: nobu <ko1@a...>
Date: Sat, 10 Mar 2012 23:52:42 +0900 (JST)
Subject: [ruby-changes:22915] nobu:r34964 (trunk): * st.c: pack tables also generic keys. patched by Sokolov Yura at

nobu	2012-03-10 23:52:30 +0900 (Sat, 10 Mar 2012)

  New Revision: 34964

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=34964

  Log:
    * st.c: pack tables also generic keys.  patched by Sokolov Yura at
      https://github.com/ruby/ruby/pull/84

  Modified files:
    trunk/ChangeLog
    trunk/st.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 34963)
+++ ChangeLog	(revision 34964)
@@ -1,5 +1,8 @@
-Sat Mar 10 23:52:16 2012  Nobuyoshi Nakada  <nobu@r...>
+Sat Mar 10 23:52:28 2012  Nobuyoshi Nakada  <nobu@r...>
 
+	* st.c: pack tables also generic keys.  patched by Sokolov Yura at
+	  https://github.com/ruby/ruby/pull/84
+
 	* st.c: add st_foreach_check for fixing iteration over packed table
 	  and st_delete_safe.  patched by Sokolov Yura at
 	  https://github.com/ruby/ruby/pull/84
Index: st.c
===================================================================
--- st.c	(revision 34963)
+++ st.c	(revision 34964)
@@ -26,6 +26,7 @@
 };
 
 typedef struct st_packed_entry {
+    st_index_t hash;
     st_data_t key, val;
 } st_packed_entry;
 
@@ -34,7 +35,7 @@
 #define ST_DEFAULT_MAX_DENSITY 5
 #define ST_DEFAULT_INIT_TABLE_SIZE 11
 #define ST_DEFAULT_SECOND_TABLE_SIZE 19
-#define ST_DEFAULT_PACKED_TABLE_SIZE ST_DEFAULT_INIT_TABLE_SIZE
+#define ST_DEFAULT_PACKED_TABLE_SIZE 18
 #define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*))
 #define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry))
 
@@ -112,9 +113,10 @@
 #define PACKED_ENT(table, i) PACKED_BINS(table)[i]
 #define PKEY(table, i) PACKED_ENT((table), (i)).key
 #define PVAL(table, i) PACKED_ENT((table), (i)).val
-#define PHASH(table, i) PKEY((table), (i))
+#define PHASH(table, i) PACKED_ENT((table), (i)).hash
 #define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v))
 #define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v))
+#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v))
 
 /* this function depends much on packed layout, so that it placed here */
 static inline void
@@ -232,12 +234,17 @@
     }
 #endif
 
-    size = new_size(size);	/* round up to prime number */
 
     tbl = st_alloc_table();
     tbl->type = type;
     tbl->num_entries = 0;
-    tbl->entries_packed = type == &type_numhash && size/PACKED_UNIT <= MAX_PACKED_HASH;
+    tbl->entries_packed = size <= MAX_PACKED_HASH;
+    if (tbl->entries_packed) {
+	size = ST_DEFAULT_PACKED_TABLE_SIZE;
+    }
+    else {
+	size = new_size(size);	/* round up to prime number */
+    }
     tbl->num_bins = size;
     tbl->bins = st_alloc_bins(size);
     tbl->head = 0;
@@ -377,10 +384,13 @@
 }
 
 static inline st_index_t
-find_packed_index(st_table *table, st_data_t key)
+find_packed_index(st_table *table, st_index_t hash_val, st_data_t key)
 {
     st_index_t i = 0;
-    while (i < table->real_entries && PKEY(table, i) != key) i++;
+    while (i < table->real_entries &&
+	   (PHASH(table, i) != hash_val || !EQUAL(table, key, PKEY(table, i)))) {
+	i++;
+    }
     return i;
 }
 
@@ -392,8 +402,10 @@
     st_index_t hash_val;
     register st_table_entry *ptr;
 
+    hash_val = do_hash(key, table);
+
     if (table->entries_packed) {
-        st_index_t i = find_packed_index(table, key);
+	st_index_t i = find_packed_index(table, hash_val, key);
 	if (i < table->real_entries) {
 	    if (value != 0) *value = PVAL(table, i);
 	    return 1;
@@ -401,7 +413,6 @@
         return 0;
     }
 
-    hash_val = do_hash(key, table);
     ptr = find_entry(table, key, hash_val, hash_val % table->num_bins);
 
     if (ptr == 0) {
@@ -419,8 +430,10 @@
     st_index_t hash_val;
     register st_table_entry *ptr;
 
+    hash_val = do_hash(key, table);
+
     if (table->entries_packed) {
-        st_index_t i = find_packed_index(table, key);
+	st_index_t i = find_packed_index(table, hash_val, key);
 	if (i < table->real_entries) {
 	    if (result != 0) *result = PKEY(table, i);
 	    return 1;
@@ -428,7 +441,6 @@
         return 0;
     }
 
-    hash_val = do_hash(key, table);
     ptr = find_entry(table, key, hash_val, hash_val % table->num_bins);
 
     if (ptr == 0) {
@@ -504,8 +516,7 @@
     do {
 	st_data_t key = packed_bins[i].key;
 	st_data_t val = packed_bins[i].val;
-	/* packed table should be numhash */
-	st_index_t hash = st_numhash(key);
+	st_index_t hash = packed_bins[i].hash;
 	entry = new_entry(&tmp_table, key, val, hash,
 			  hash % ST_DEFAULT_INIT_TABLE_SIZE);
 	*chain = entry;
@@ -519,17 +530,18 @@
 }
 
 static void
-add_packed_direct(st_table *table, st_data_t key, st_data_t value)
+add_packed_direct(st_table *table, st_data_t key, st_data_t value, st_index_t hash_val)
 {
     if (table->real_entries < MAX_PACKED_HASH) {
 	st_index_t i = table->real_entries++;
 	PKEY_SET(table, i, key);
 	PVAL_SET(table, i, value);
+	PHASH_SET(table, i, hash_val);
 	table->num_entries++;
     }
     else {
 	unpack_entries(table);
-	add_direct(table, key, value, key, key % table->num_bins);
+	add_direct(table, key, value, hash_val, hash_val % table->num_bins);
     }
 }
 
@@ -541,17 +553,18 @@
     register st_index_t bin_pos;
     register st_table_entry *ptr;
 
+    hash_val = do_hash(key, table);
+
     if (table->entries_packed) {
-        st_index_t i = find_packed_index(table, key);
+	st_index_t i = find_packed_index(table, hash_val, key);
 	if (i < table->real_entries) {
 	    PVAL_SET(table, i, value);
 	    return 1;
         }
-	add_packed_direct(table, key, value);
+	add_packed_direct(table, key, value, hash_val);
 	return 0;
     }
 
-    hash_val = do_hash(key, table);
     FIND_ENTRY(table, ptr, hash_val, bin_pos);
 
     if (ptr == 0) {
@@ -572,17 +585,19 @@
     register st_index_t bin_pos;
     register st_table_entry *ptr;
 
+    hash_val = do_hash(key, table);
+
     if (table->entries_packed) {
-        st_index_t i = find_packed_index(table, key);
+	st_index_t i = find_packed_index(table, hash_val, key);
 	if (i < table->real_entries) {
 	    PVAL_SET(table, i, value);
 	    return 1;
-        }
-	add_packed_direct(table, key, value);
+	}
+	key = (*func)(key);
+	add_packed_direct(table, key, value, hash_val);
 	return 0;
     }
 
-    hash_val = do_hash(key, table);
     FIND_ENTRY(table, ptr, hash_val, bin_pos);
 
     if (ptr == 0) {
@@ -601,12 +616,12 @@
 {
     st_index_t hash_val;
 
+    hash_val = do_hash(key, table);
     if (table->entries_packed) {
-	add_packed_direct(table, key, value);
+	add_packed_direct(table, key, value, hash_val);
 	return;
     }
 
-    hash_val = do_hash(key, table);
     add_direct(table, key, value, hash_val, hash_val % table->num_bins);
 }
 
@@ -703,10 +718,13 @@
     st_table_entry **prev;
     register st_table_entry *ptr;
 
+    hash_val = do_hash(*key, table);
+
     if (table->entries_packed) {
-        st_index_t i = find_packed_index(table, *key);
+	st_index_t i = find_packed_index(table, hash_val, *key);
 	if (i < table->num_entries) {
 	    if (value != 0) *value = PVAL(table, i);
+	    *key = PKEY(table, i);
 	    remove_packed_entry(table, i);
 	    return 1;
         }
@@ -714,9 +732,8 @@
         return 0;
     }
 
-    hash_val = do_hash_bin(*key, table);
-
-    for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) {
+    prev = &table->bins[hash_val % table->num_bins];
+    for (;(ptr = *prev) != 0; prev = &ptr->next) {
 	if (EQUAL(table, *key, ptr->key)) {
 	    *prev = ptr->next;
 	    remove_entry(table, ptr);
@@ -737,11 +754,16 @@
     st_index_t hash_val;
     register st_table_entry *ptr;
 
+    hash_val = do_hash(*key, table);
+
     if (table->entries_packed) {
-        st_index_t i = find_packed_index(table, *key);
+	st_index_t i = find_packed_index(table, hash_val, *key);
 	if (i < table->real_entries) {
 	    if (value != 0) *value = PVAL(table, i);
+	    *key = PKEY(table, i);
 	    PKEY_SET(table, i, never);
+	    PVAL_SET(table, i, never);
+	    PHASH_SET(table, i, 0);
 	    table->num_entries--;
 	    return 1;
 	}
@@ -749,8 +771,7 @@
 	return 0;
     }
 
-    hash_val = do_hash_bin(*key, table);
-    ptr = table->bins[hash_val];
+    ptr = table->bins[hash_val % table->num_bins];
 
     for (; ptr != 0; ptr = ptr->next) {
 	if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) {
@@ -811,13 +832,14 @@
     st_data_t value;
     int retval;
 
+    hash_val = do_hash(key, table);
+
     if (table->entries_packed) {
-	st_index_t i = find_packed_index(table, key);
+	st_index_t i = find_packed_index(table, hash_val, key);
 	if (i < table->real_entries) {
 	    value = PVAL(table, i);
 	    retval = (*func)(key, &value, arg);
 	    if (!table->entries_packed) {
-		hash_val = do_hash(key, table);
 		FIND_ENTRY(table, ptr, hash_val, bin_pos);
 		if (ptr == 0) return 0;
 		goto unpacked;
@@ -834,7 +856,6 @@
 	return 0;
     }
 
-    hash_val = do_hash(key, table);
     FIND_ENTRY(table, ptr, hash_val, bin_pos);
 
     if (ptr == 0) {
@@ -875,12 +896,14 @@
     if (table->entries_packed) {
 	for (i = 0; i < table->real_entries; i++) {
 	    st_data_t key, val;
+	    st_index_t hash;
 	    key = PKEY(table, i);
 	    val = PVAL(table, i);
+	    hash = PHASH(table, i);
 	    if (key == never) continue;
 	    retval = (*func)(key, val, arg);
 	    if (!table->entries_packed) {
-		FIND_ENTRY(table, ptr, key, i);
+		FIND_ENTRY(table, ptr, hash, i);
 		if (retval == ST_CHECK) {
 		    if (!ptr) goto deleted;
 		    goto unpacked_continue;
@@ -889,10 +912,11 @@
 	    }
 	    switch (retval) {
 	      case ST_CHECK:	/* check if hash is modified during iteration */
-		if (PKEY(table, i) == never) {
+		if (PHASH(table, i) == 0 && PKEY(table, i) == never) {
 		    break;
 		}
-		if (i != find_packed_index(table, key)) {
+		i = find_packed_index(table, hash, key);
+		if (i == table->real_entries) {
 		    goto deleted;
 		}
 		/* fall through */
@@ -964,12 +988,13 @@
 
     if (table->entries_packed) {
 	for (i = 0; i < table->real_entries; i++) {
-	    st_data_t key, val;
+	    st_data_t key, val, hash;
 	    key = PKEY(table, i);
 	    val = PVAL(table, i);
+	    hash = PHASH(table, i);
 	    retval = (*func)(key, val, arg);
 	    if (!table->entries_packed) {
-		FIND_ENTRY(table, ptr, key, i);
+		FIND_ENTRY(table, ptr, hash, i);
 		if (!ptr) return 0;
 		goto unpacked;
 	    }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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