[Python-checkins] cpython: Simplify implementation of hashtable.c

victor.stinner python-checkins at python.org
Tue Mar 22 07:25:16 EDT 2016


https://hg.python.org/cpython/rev/7c894911eb59
changeset:   100651:7c894911eb59
parent:      100649:322d30816d36
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Tue Mar 22 12:13:01 2016 +0100
summary:
  Simplify implementation of hashtable.c

Issue #26588: Remove copy_data, free_data and get_data_size callbacks from
hashtable.h. These callbacks are not used in Python and makes the code more
complex.

Remove also the _Py_HASHTABLE_ENTRY_DATA_AS_VOID_P() macro which uses an unsafe
pointer dereference (can cause memory alignment issue). Replace the macro usage
with _Py_HASHTABLE_ENTRY_READ_DATA() which is implemented with the safe
memcpy() function.

files:
  Modules/_tracemalloc.c |  14 ++++---
  Modules/hashtable.c    |  55 ++++-------------------------
  Modules/hashtable.h    |  14 +-------
  3 files changed, 17 insertions(+), 66 deletions(-)


diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c
--- a/Modules/_tracemalloc.c
+++ b/Modules/_tracemalloc.c
@@ -220,16 +220,15 @@
         return key == entry_key;
 }
 
-static _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
-
 static _Py_hashtable_t *
 hashtable_new(size_t key_size, size_t data_size,
               _Py_hashtable_hash_func hash_func,
               _Py_hashtable_compare_func compare_func)
 {
+    _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
     return _Py_hashtable_new_full(key_size, data_size, 0,
                                   hash_func, compare_func,
-                                  NULL, NULL, NULL, &hashtable_alloc);
+                                  &hashtable_alloc);
 }
 
 static void*
@@ -1120,7 +1119,8 @@
                                _Py_hashtable_entry_t *entry,
                                void *user_data)
 {
-    PyObject *obj = (PyObject *)_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(tracebacks, entry);
+    PyObject *obj;
+    _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, sizeof(obj), &obj);
     Py_DECREF(obj);
     return 0;
 }
@@ -1151,7 +1151,8 @@
 
     /* the traceback hash table is used temporarily to intern traceback tuple
        of (filename, lineno) tuples */
-    get_traces.tracebacks = hashtable_new(sizeof(traceback_t *), sizeof(PyObject *),
+    get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
+                                          sizeof(PyObject *),
                                           _Py_hashtable_hash_ptr,
                                           _Py_hashtable_compare_direct);
     if (get_traces.tracebacks == NULL) {
@@ -1186,8 +1187,9 @@
                               tracemalloc_pyobject_decref_cb, NULL);
         _Py_hashtable_destroy(get_traces.tracebacks);
     }
-    if (get_traces.traces != NULL)
+    if (get_traces.traces != NULL) {
         _Py_hashtable_destroy(get_traces.traces);
+    }
 
     return get_traces.list;
 }
diff --git a/Modules/hashtable.c b/Modules/hashtable.c
--- a/Modules/hashtable.c
+++ b/Modules/hashtable.c
@@ -128,9 +128,6 @@
                        size_t init_size,
                        _Py_hashtable_hash_func hash_func,
                        _Py_hashtable_compare_func compare_func,
-                       _Py_hashtable_copy_data_func copy_data_func,
-                       _Py_hashtable_free_data_func free_data_func,
-                       _Py_hashtable_get_data_size_func get_data_size_func,
                        _Py_hashtable_allocator_t *allocator)
 {
     _Py_hashtable_t *ht;
@@ -163,9 +160,6 @@
 
     ht->hash_func = hash_func;
     ht->compare_func = compare_func;
-    ht->copy_data_func = copy_data_func;
-    ht->free_data_func = free_data_func;
-    ht->get_data_size_func = get_data_size_func;
     ht->alloc = alloc;
     return ht;
 }
@@ -179,7 +173,7 @@
     return _Py_hashtable_new_full(key_size, data_size,
                                   HASHTABLE_MIN_SIZE,
                                   hash_func, compare_func,
-                                  NULL, NULL, NULL, NULL);
+                                  NULL);
 }
 
 
@@ -187,7 +181,6 @@
 _Py_hashtable_size(_Py_hashtable_t *ht)
 {
     size_t size;
-    size_t hv;
 
     size = sizeof(_Py_hashtable_t);
 
@@ -197,19 +190,6 @@
     /* entries */
     size += ht->entries * HASHTABLE_ITEM_SIZE(ht);
 
-    /* data linked from entries */
-    if (ht->get_data_size_func) {
-        for (hv = 0; hv < ht->num_buckets; hv++) {
-            _Py_hashtable_entry_t *entry;
-
-            for (entry = TABLE_HEAD(ht, hv); entry; entry = ENTRY_NEXT(entry)) {
-                void *data;
-
-                data = _Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(ht, entry);
-                size += ht->get_data_size_func(data);
-            }
-        }
-    }
     return size;
 }
 
@@ -318,7 +298,7 @@
 
 int
 _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey,
-                  size_t data_size, void *data)
+                  size_t data_size, const void *data)
 {
     Py_uhash_t key_hash;
     size_t index;
@@ -380,7 +360,6 @@
                   size_t data_size, void *data)
 {
     assert(data != NULL);
-    assert(ht->free_data_func == NULL);
     return _Py_hashtable_pop_entry(ht, key_size, pkey, data, data_size);
 }
 
@@ -470,8 +449,6 @@
     for (i=0; i < ht->num_buckets; i++) {
         for (entry = TABLE_HEAD(ht, i); entry != NULL; entry = next) {
             next = ENTRY_NEXT(entry);
-            if (ht->free_data_func)
-                ht->free_data_func(_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(ht, entry));
             ht->alloc.free(entry);
         }
         _Py_slist_init(&ht->buckets[i]);
@@ -490,8 +467,6 @@
         _Py_slist_item_t *entry = ht->buckets[i].head;
         while (entry) {
             _Py_slist_item_t *entry_next = entry->next;
-            if (ht->free_data_func)
-                ht->free_data_func(_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(ht, entry));
             ht->alloc.free(entry);
             entry = entry_next;
         }
@@ -511,35 +486,21 @@
     _Py_hashtable_entry_t *entry;
     size_t bucket;
     int err;
-    void *data, *new_data;
 
     dst = _Py_hashtable_new_full(key_size, data_size,
                                  src->num_buckets,
-                                 src->hash_func, src->compare_func,
-                                 src->copy_data_func, src->free_data_func,
-                                 src->get_data_size_func, &src->alloc);
+                                 src->hash_func,
+                                 src->compare_func,
+                                 &src->alloc);
     if (dst == NULL)
         return NULL;
 
     for (bucket=0; bucket < src->num_buckets; bucket++) {
         entry = TABLE_HEAD(src, bucket);
         for (; entry; entry = ENTRY_NEXT(entry)) {
-            if (src->copy_data_func) {
-                data = _Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(src, entry);
-                new_data = src->copy_data_func(data);
-                if (new_data != NULL)
-                    err = _Py_hashtable_set(dst, key_size,
-                                            _Py_HASHTABLE_ENTRY_KEY(entry),
-                                            data_size, &new_data);
-                else
-                    err = 1;
-            }
-            else {
-                data = _Py_HASHTABLE_ENTRY_DATA(src, entry);
-                err = _Py_hashtable_set(dst, key_size,
-                                        _Py_HASHTABLE_ENTRY_KEY(entry),
-                                        data_size, data);
-            }
+            const void *pkey = _Py_HASHTABLE_ENTRY_KEY(entry);
+            const void *data = _Py_HASHTABLE_ENTRY_DATA(src, entry);
+            err = _Py_hashtable_set(dst, key_size, pkey, data_size, data);
             if (err) {
                 _Py_hashtable_destroy(dst);
                 return NULL;
diff --git a/Modules/hashtable.h b/Modules/hashtable.h
--- a/Modules/hashtable.h
+++ b/Modules/hashtable.h
@@ -35,9 +35,6 @@
 #define _Py_HASHTABLE_ENTRY_DATA(TABLE, ENTRY) \
         ((char *)(ENTRY) + sizeof(_Py_hashtable_entry_t) + (TABLE)->key_size)
 
-#define _Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(TABLE, ENTRY) \
-        (*(void **)_Py_HASHTABLE_ENTRY_DATA(TABLE, ENTRY))
-
 /* Get a key value from pkey: use memcpy() rather than a pointer dereference
    to avoid memory alignment issues. */
 #define _Py_HASHTABLE_READ_KEY(KEY_SIZE, PKEY, DST_KEY) \
@@ -66,9 +63,6 @@
 typedef int (*_Py_hashtable_compare_func) (size_t key_size,
                                            const void *pkey,
                                            const _Py_hashtable_entry_t *he);
-typedef void* (*_Py_hashtable_copy_data_func)(void *data);
-typedef void (*_Py_hashtable_free_data_func)(void *data);
-typedef size_t (*_Py_hashtable_get_data_size_func)(void *data);
 
 typedef struct {
     /* allocate a memory block */
@@ -90,9 +84,6 @@
 
     _Py_hashtable_hash_func hash_func;
     _Py_hashtable_compare_func compare_func;
-    _Py_hashtable_copy_data_func copy_data_func;
-    _Py_hashtable_free_data_func free_data_func;
-    _Py_hashtable_get_data_size_func get_data_size_func;
     _Py_hashtable_allocator_t alloc;
 } _Py_hashtable_t;
 
@@ -119,9 +110,6 @@
     size_t init_size,
     _Py_hashtable_hash_func hash_func,
     _Py_hashtable_compare_func compare_func,
-    _Py_hashtable_copy_data_func copy_data_func,
-    _Py_hashtable_free_data_func free_data_func,
-    _Py_hashtable_get_data_size_func get_data_size_func,
     _Py_hashtable_allocator_t *allocator);
 
 PyAPI_FUNC(void) _Py_hashtable_destroy(_Py_hashtable_t *ht);
@@ -155,7 +143,7 @@
     size_t key_size,
     const void *pkey,
     size_t data_size,
-    void *data);
+    const void *data);
 
 #define _Py_HASHTABLE_SET(TABLE, KEY, DATA) \
     _Py_hashtable_set(TABLE, sizeof(KEY), &KEY, sizeof(DATA), &(DATA))

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list