diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-03-22 11:13:01 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-03-22 11:13:01 (GMT) |
commit | c9553876ae88b7f1494cff826c8f7a08c2ac5614 (patch) | |
tree | 63f4ec83ec78ca95db74b03bd033a4953d27d653 | |
parent | 0b2d71bc70c32560853fa91f58dc37af8f08090c (diff) | |
download | cpython-c9553876ae88b7f1494cff826c8f7a08c2ac5614.zip cpython-c9553876ae88b7f1494cff826c8f7a08c2ac5614.tar.gz cpython-c9553876ae88b7f1494cff826c8f7a08c2ac5614.tar.bz2 |
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.
-rw-r--r-- | Modules/_tracemalloc.c | 14 | ||||
-rw-r--r-- | Modules/hashtable.c | 55 | ||||
-rw-r--r-- | Modules/hashtable.h | 14 |
3 files changed, 17 insertions, 66 deletions
diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index 3c5319b..c48dd08 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -220,16 +220,15 @@ hashtable_compare_unicode(size_t key_size, const void *pkey, 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 @@ tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks, _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 @@ py_tracemalloc_get_traces(PyObject *self, PyObject *obj) /* 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 @@ finally: 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 index d33f0d7..7094b95 100644 --- a/Modules/hashtable.c +++ b/Modules/hashtable.c @@ -128,9 +128,6 @@ _Py_hashtable_new_full(size_t key_size, size_t data_size, 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 @@ _Py_hashtable_new_full(size_t key_size, size_t data_size, 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 @@ _Py_hashtable_new(size_t key_size, size_t data_size, 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 @@ size_t _Py_hashtable_size(_Py_hashtable_t *ht) { size_t size; - size_t hv; size = sizeof(_Py_hashtable_t); @@ -197,19 +190,6 @@ _Py_hashtable_size(_Py_hashtable_t *ht) /* 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 @@ _Py_hashtable_pop_entry(_Py_hashtable_t *ht, size_t key_size, const void *pkey, 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 @@ _Py_hashtable_pop(_Py_hashtable_t *ht, size_t key_size, const void *pkey, 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 @@ _Py_hashtable_clear(_Py_hashtable_t *ht) 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_hashtable_destroy(_Py_hashtable_t *ht) _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_copy(_Py_hashtable_t *src) _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 index 6eb5737..eede038 100644 --- a/Modules/hashtable.h +++ b/Modules/hashtable.h @@ -35,9 +35,6 @@ typedef struct { #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 Py_uhash_t (*_Py_hashtable_hash_func) (size_t key_size, 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 @@ typedef struct { _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 @@ PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new_full( 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 @@ PyAPI_FUNC(int) _Py_hashtable_set( 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)) |