changeset: 100651:7c894911eb59 parent: 100649:322d30816d36 user: Victor Stinner date: Tue Mar 22 12:13:01 2016 +0100 files: Modules/_tracemalloc.c Modules/hashtable.c Modules/hashtable.h description: 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. diff -r 322d30816d36 -r 7c894911eb59 Modules/_tracemalloc.c --- a/Modules/_tracemalloc.c Tue Mar 22 09:28:58 2016 +0000 +++ b/Modules/_tracemalloc.c Tue Mar 22 12:13:01 2016 +0100 @@ -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 -r 322d30816d36 -r 7c894911eb59 Modules/hashtable.c --- a/Modules/hashtable.c Tue Mar 22 09:28:58 2016 +0000 +++ b/Modules/hashtable.c Tue Mar 22 12:13:01 2016 +0100 @@ -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 -r 322d30816d36 -r 7c894911eb59 Modules/hashtable.h --- a/Modules/hashtable.h Tue Mar 22 09:28:58 2016 +0000 +++ b/Modules/hashtable.h Tue Mar 22 12:13:01 2016 +0100 @@ -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))