From f9b3b582b86b9cce8d69ec7d03d716ec81c8264a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 13 May 2020 02:26:02 +0200 Subject: [PATCH] bpo-40609: Remove _Py_hashtable_t.key_size (GH-20060) Rewrite _Py_hashtable_t type to always store the key as a "const void *" pointer. Add an explicit "key" member to _Py_hashtable_entry_t. Remove _Py_hashtable_t.key_size member. hash and compare functions drop their hash table parameter, and their 'key' parameter type becomes "const void *". --- Include/internal/pycore_hashtable.h | 74 +++++------------- Modules/_tracemalloc.c | 117 ++++++++++++---------------- Python/hashtable.c | 111 +++++++++++--------------- Python/marshal.c | 6 +- 4 files changed, 120 insertions(+), 188 deletions(-) diff --git a/Include/internal/pycore_hashtable.h b/Include/internal/pycore_hashtable.h index 6e094e94376..965a4e7f2b4 100644 --- a/Include/internal/pycore_hashtable.h +++ b/Include/internal/pycore_hashtable.h @@ -30,32 +30,13 @@ typedef struct { _Py_slist_item_t _Py_slist_item; Py_uhash_t key_hash; - - /* key (key_size bytes) and then data (data_size bytes) follows */ + void *key; + /* data (data_size bytes) follows */ } _Py_hashtable_entry_t; -#define _Py_HASHTABLE_ENTRY_PKEY(ENTRY) \ - ((const void *)((char *)(ENTRY) \ - + sizeof(_Py_hashtable_entry_t))) - #define _Py_HASHTABLE_ENTRY_PDATA(TABLE, ENTRY) \ ((const void *)((char *)(ENTRY) \ - + sizeof(_Py_hashtable_entry_t) \ - + (TABLE)->key_size)) - -/* Get a key value from pkey: use memcpy() rather than a pointer dereference - to avoid memory alignment issues. */ -#define _Py_HASHTABLE_READ_KEY(TABLE, PKEY, DST_KEY) \ - do { \ - assert(sizeof(DST_KEY) == (TABLE)->key_size); \ - memcpy(&(DST_KEY), (PKEY), sizeof(DST_KEY)); \ - } while (0) - -#define _Py_HASHTABLE_ENTRY_READ_KEY(TABLE, ENTRY, KEY) \ - do { \ - assert(sizeof(KEY) == (TABLE)->key_size); \ - memcpy(&(KEY), _Py_HASHTABLE_ENTRY_PKEY(ENTRY), sizeof(KEY)); \ - } while (0) + + sizeof(_Py_hashtable_entry_t))) #define _Py_HASHTABLE_ENTRY_READ_DATA(TABLE, ENTRY, DATA) \ do { \ @@ -78,15 +59,12 @@ typedef struct { struct _Py_hashtable_t; typedef struct _Py_hashtable_t _Py_hashtable_t; -typedef Py_uhash_t (*_Py_hashtable_hash_func) (_Py_hashtable_t *ht, - const void *pkey); -typedef int (*_Py_hashtable_compare_func) (_Py_hashtable_t *ht, - const void *pkey, - const _Py_hashtable_entry_t *he); +typedef Py_uhash_t (*_Py_hashtable_hash_func) (const void *key); +typedef int (*_Py_hashtable_compare_func) (const void *key1, const void *key2); typedef _Py_hashtable_entry_t* (*_Py_hashtable_get_entry_func)(_Py_hashtable_t *ht, - const void *pkey); + const void *key); typedef int (*_Py_hashtable_get_func) (_Py_hashtable_t *ht, - const void *pkey, void *data); + const void *key, void *data); typedef struct { /* allocate a memory block */ @@ -102,7 +80,6 @@ struct _Py_hashtable_t { size_t num_buckets; size_t entries; /* Total number of entries in the table. */ _Py_slist_t *buckets; - size_t key_size; size_t data_size; _Py_hashtable_get_func get_func; @@ -113,24 +90,19 @@ struct _Py_hashtable_t { }; /* hash a pointer (void*) */ -PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr( - struct _Py_hashtable_t *ht, - const void *pkey); +PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr(const void *key); /* comparison using memcmp() */ PyAPI_FUNC(int) _Py_hashtable_compare_direct( - _Py_hashtable_t *ht, - const void *pkey, - const _Py_hashtable_entry_t *entry); + const void *key1, + const void *key2); PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new( - size_t key_size, size_t data_size, _Py_hashtable_hash_func hash_func, _Py_hashtable_compare_func compare_func); PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new_full( - size_t key_size, size_t data_size, size_t init_size, _Py_hashtable_hash_func hash_func, @@ -165,16 +137,15 @@ PyAPI_FUNC(size_t) _Py_hashtable_size(_Py_hashtable_t *ht); but use _Py_HASHTABLE_SET() and _Py_HASHTABLE_SET_NODATA() macros */ PyAPI_FUNC(int) _Py_hashtable_set( _Py_hashtable_t *ht, - size_t key_size, - const void *pkey, + const void *key, size_t data_size, const void *data); #define _Py_HASHTABLE_SET(TABLE, KEY, DATA) \ - _Py_hashtable_set(TABLE, sizeof(KEY), &(KEY), sizeof(DATA), &(DATA)) + _Py_hashtable_set(TABLE, (KEY), sizeof(DATA), &(DATA)) #define _Py_HASHTABLE_SET_NODATA(TABLE, KEY) \ - _Py_hashtable_set(TABLE, sizeof(KEY), &(KEY), 0, NULL) + _Py_hashtable_set(TABLE, (KEY), 0, NULL) /* Get an entry. @@ -183,14 +154,13 @@ PyAPI_FUNC(int) _Py_hashtable_set( Don't call directly this function, but use _Py_HASHTABLE_GET_ENTRY() macro */ static inline _Py_hashtable_entry_t * -_Py_hashtable_get_entry(_Py_hashtable_t *ht, size_t key_size, const void *pkey) +_Py_hashtable_get_entry(_Py_hashtable_t *ht, const void *key) { - assert(key_size == ht->key_size); - return ht->get_entry_func(ht, pkey); + return ht->get_entry_func(ht, key); } #define _Py_HASHTABLE_GET_ENTRY(TABLE, KEY) \ - _Py_hashtable_get_entry(TABLE, sizeof(KEY), &(KEY)) + _Py_hashtable_get_entry(TABLE, (const void *)(KEY)) /* Get data from an entry. Copy entry data into data and return 1 if the entry @@ -198,28 +168,26 @@ _Py_hashtable_get_entry(_Py_hashtable_t *ht, size_t key_size, const void *pkey) Don't call directly this function, but use _Py_HASHTABLE_GET() macro */ static inline int -_Py_hashtable_get(_Py_hashtable_t *ht, size_t key_size, const void *pkey, +_Py_hashtable_get(_Py_hashtable_t *ht, const void *key, size_t data_size, void *data) { - assert(key_size == ht->key_size); assert(data_size == ht->data_size); - return ht->get_func(ht, pkey, data); + return ht->get_func(ht, key, data); } #define _Py_HASHTABLE_GET(TABLE, KEY, DATA) \ - _Py_hashtable_get(TABLE, sizeof(KEY), &(KEY), sizeof(DATA), &(DATA)) + _Py_hashtable_get(TABLE, (KEY), sizeof(DATA), &(DATA)) /* Don't call directly this function, but use _Py_HASHTABLE_POP() macro */ PyAPI_FUNC(int) _Py_hashtable_pop( _Py_hashtable_t *ht, - size_t key_size, - const void *pkey, + const void *key, size_t data_size, void *data); #define _Py_HASHTABLE_POP(TABLE, KEY, DATA) \ - _Py_hashtable_pop(TABLE, sizeof(KEY), &(KEY), sizeof(DATA), &(DATA)) + _Py_hashtable_pop(TABLE, (KEY), sizeof(DATA), &(DATA)) #ifdef __cplusplus diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index 7e31abe05fb..050fe03bba8 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -23,6 +23,9 @@ static void raw_free(void *ptr); # define TRACE_DEBUG #endif +#define TO_PTR(key) ((const void *)(uintptr_t)key) +#define FROM_PTR(key) ((uintptr_t)key) + /* Protected by the GIL */ static struct { PyMemAllocatorEx mem; @@ -203,47 +206,42 @@ set_reentrant(int reentrant) static Py_uhash_t -hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey) +hashtable_hash_pyobject(const void *key) { - PyObject *obj; - - _Py_HASHTABLE_READ_KEY(ht, pkey, obj); + PyObject *obj = (PyObject *)key; return PyObject_Hash(obj); } static int -hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey, - const _Py_hashtable_entry_t *entry) +hashtable_compare_unicode(const void *key1, const void *key2) { - PyObject *key1, *key2; - - _Py_HASHTABLE_READ_KEY(ht, pkey, key1); - _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2); - - if (key1 != NULL && key2 != NULL) - return (PyUnicode_Compare(key1, key2) == 0); - else - return key1 == key2; + PyObject *obj1 = (PyObject *)key1; + PyObject *obj2 = (PyObject *)key2; + if (obj1 != NULL && obj2 != NULL) { + return (PyUnicode_Compare(obj1, obj2) == 0); + } + else { + return obj1 == obj2; + } } static Py_uhash_t -hashtable_hash_uint(_Py_hashtable_t *ht, const void *pkey) +hashtable_hash_uint(const void *key_raw) { - unsigned int key; - _Py_HASHTABLE_READ_KEY(ht, pkey, key); + unsigned int key = (unsigned int)FROM_PTR(key_raw); return (Py_uhash_t)key; } static _Py_hashtable_t * -hashtable_new(size_t key_size, size_t data_size, +hashtable_new(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, + return _Py_hashtable_new_full(data_size, 0, hash_func, compare_func, &hashtable_alloc); } @@ -263,39 +261,33 @@ raw_free(void *ptr) static Py_uhash_t -hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey) +hashtable_hash_traceback(const void *key) { - traceback_t *traceback; - - _Py_HASHTABLE_READ_KEY(ht, pkey, traceback); + const traceback_t *traceback = (const traceback_t *)key; return traceback->hash; } static int -hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey, - const _Py_hashtable_entry_t *entry) +hashtable_compare_traceback(const void *key1, const void *key2) { - traceback_t *traceback1, *traceback2; - const frame_t *frame1, *frame2; - int i; + const traceback_t *traceback1 = (const traceback_t *)key1; + const traceback_t *traceback2 = (const traceback_t *)key2; - _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1); - _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2); - - if (traceback1->nframe != traceback2->nframe) + if (traceback1->nframe != traceback2->nframe) { return 0; - - if (traceback1->total_nframe != traceback2->total_nframe) + } + if (traceback1->total_nframe != traceback2->total_nframe) { return 0; + } - for (i=0; i < traceback1->nframe; i++) { - frame1 = &traceback1->frames[i]; - frame2 = &traceback2->frames[i]; + for (int i=0; i < traceback1->nframe; i++) { + const frame_t *frame1 = &traceback1->frames[i]; + const frame_t *frame2 = &traceback2->frames[i]; - if (frame1->lineno != frame2->lineno) + if (frame1->lineno != frame2->lineno) { return 0; - + } if (frame1->filename != frame2->filename) { assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0); return 0; @@ -349,7 +341,7 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame) _Py_hashtable_entry_t *entry; entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename); if (entry != NULL) { - _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename); + filename = (PyObject *)entry->key; } else { /* tracemalloc_filenames is responsible to keep a reference @@ -444,7 +436,7 @@ traceback_new(void) /* intern the traceback */ entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback); if (entry != NULL) { - _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback); + traceback = (traceback_t *)entry->key; } else { traceback_t *copy; @@ -477,8 +469,7 @@ traceback_new(void) static _Py_hashtable_t* tracemalloc_create_traces_table(void) { - return hashtable_new(sizeof(uintptr_t), - sizeof(trace_t), + return hashtable_new(sizeof(trace_t), _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct); } @@ -487,8 +478,7 @@ tracemalloc_create_traces_table(void) static _Py_hashtable_t* tracemalloc_create_domains_table(void) { - return hashtable_new(sizeof(unsigned int), - sizeof(_Py_hashtable_t *), + return hashtable_new(sizeof(_Py_hashtable_t *), hashtable_hash_uint, _Py_hashtable_compare_direct); } @@ -522,7 +512,7 @@ tracemalloc_get_traces_table(unsigned int domain) } else { _Py_hashtable_t *traces = NULL; - (void)_Py_HASHTABLE_GET(tracemalloc_domains, domain, traces); + (void)_Py_HASHTABLE_GET(tracemalloc_domains, TO_PTR(domain), traces); return traces; } } @@ -539,7 +529,7 @@ tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr) } trace_t trace; - if (!_Py_HASHTABLE_POP(traces, ptr, trace)) { + if (!_Py_HASHTABLE_POP(traces, TO_PTR(ptr), trace)) { return; } assert(tracemalloc_traced_memory >= trace.size); @@ -568,7 +558,7 @@ tracemalloc_add_trace(unsigned int domain, uintptr_t ptr, return -1; } - if (_Py_HASHTABLE_SET(tracemalloc_domains, domain, traces) < 0) { + if (_Py_HASHTABLE_SET(tracemalloc_domains, TO_PTR(domain), traces) < 0) { _Py_hashtable_destroy(traces); return -1; } @@ -590,7 +580,7 @@ tracemalloc_add_trace(unsigned int domain, uintptr_t ptr, trace.size = size; trace.traceback = traceback; - int res = _Py_HASHTABLE_SET(traces, ptr, trace); + int res = _Py_HASHTABLE_SET(traces, TO_PTR(ptr), trace); if (res != 0) { return res; } @@ -859,9 +849,7 @@ static int tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry, void *user_data) { - PyObject *filename; - - _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename); + PyObject *filename = (PyObject *)entry->key; Py_DECREF(filename); return 0; } @@ -871,9 +859,7 @@ static int traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry, void *user_data) { - traceback_t *traceback; - - _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback); + traceback_t *traceback = (traceback_t *)entry->key; raw_free(traceback); return 0; } @@ -936,11 +922,11 @@ tracemalloc_init(void) } #endif - tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0, + tracemalloc_filenames = hashtable_new(0, hashtable_hash_pyobject, hashtable_compare_unicode); - tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0, + tracemalloc_tracebacks = hashtable_new(0, hashtable_hash_traceback, hashtable_compare_traceback); @@ -1154,7 +1140,7 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) PyObject *frames, *frame; if (intern_table != NULL) { - if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) { + if (_Py_HASHTABLE_GET(intern_table, (const void *)traceback, frames)) { Py_INCREF(frames); return frames; } @@ -1244,13 +1230,12 @@ tracemalloc_get_traces_copy_domain(_Py_hashtable_t *domains, { get_traces_t *get_traces = user_data; - unsigned int domain; - _Py_HASHTABLE_ENTRY_READ_KEY(domains, entry, domain); + unsigned int domain = (unsigned int)FROM_PTR(entry->key); _Py_hashtable_t *traces; _Py_HASHTABLE_ENTRY_READ_DATA(domains, entry, traces); _Py_hashtable_t *traces2 = _Py_hashtable_copy(traces); - if (_Py_HASHTABLE_SET(get_traces->domains, domain, traces2) < 0) { + if (_Py_HASHTABLE_SET(get_traces->domains, TO_PTR(domain), traces2) < 0) { _Py_hashtable_destroy(traces2); return -1; } @@ -1289,8 +1274,7 @@ tracemalloc_get_traces_domain(_Py_hashtable_t *domains, { get_traces_t *get_traces = user_data; - unsigned int domain; - _Py_HASHTABLE_ENTRY_READ_KEY(domains, entry, domain); + unsigned int domain = (unsigned int)FROM_PTR(entry->key); _Py_hashtable_t *traces; _Py_HASHTABLE_ENTRY_READ_DATA(domains, entry, traces); @@ -1343,8 +1327,7 @@ _tracemalloc__get_traces_impl(PyObject *module) /* 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(PyObject *), _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct); if (get_traces.tracebacks == NULL) { @@ -1425,7 +1408,7 @@ tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr) TABLES_LOCK(); _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); if (traces) { - found = _Py_HASHTABLE_GET(traces, ptr, trace); + found = _Py_HASHTABLE_GET(traces, TO_PTR(ptr), trace); } else { found = 0; diff --git a/Python/hashtable.c b/Python/hashtable.c index 90fe34e6280..01d84398cc7 100644 --- a/Python/hashtable.c +++ b/Python/hashtable.c @@ -59,7 +59,7 @@ #define ENTRY_NEXT(ENTRY) \ ((_Py_hashtable_entry_t *)_Py_SLIST_ITEM_NEXT(ENTRY)) #define HASHTABLE_ITEM_SIZE(HT) \ - (sizeof(_Py_hashtable_entry_t) + (HT)->key_size + (HT)->data_size) + (sizeof(_Py_hashtable_entry_t) + (HT)->data_size) #define ENTRY_READ_PDATA(TABLE, ENTRY, DATA_SIZE, PDATA) \ do { \ @@ -105,20 +105,16 @@ _Py_slist_remove(_Py_slist_t *list, _Py_slist_item_t *previous, Py_uhash_t -_Py_hashtable_hash_ptr(struct _Py_hashtable_t *ht, const void *pkey) +_Py_hashtable_hash_ptr(const void *key) { - void *key; - _Py_HASHTABLE_READ_KEY(ht, pkey, key); return (Py_uhash_t)_Py_HashPointerRaw(key); } int -_Py_hashtable_compare_direct(_Py_hashtable_t *ht, const void *pkey, - const _Py_hashtable_entry_t *entry) +_Py_hashtable_compare_direct(const void *key1, const void *key2) { - const void *pkey2 = _Py_HASHTABLE_ENTRY_PKEY(entry); - return (memcmp(pkey, pkey2, ht->key_size) == 0); + return (key1 == key2); } @@ -195,16 +191,16 @@ _Py_hashtable_print_stats(_Py_hashtable_t *ht) _Py_hashtable_entry_t * -_Py_hashtable_get_entry_generic(_Py_hashtable_t *ht, const void *pkey) +_Py_hashtable_get_entry_generic(_Py_hashtable_t *ht, const void *key) { - Py_uhash_t key_hash = ht->hash_func(ht, pkey); + Py_uhash_t key_hash = ht->hash_func(key); size_t index = key_hash & (ht->num_buckets - 1); _Py_hashtable_entry_t *entry = entry = TABLE_HEAD(ht, index); while (1) { if (entry == NULL) { return NULL; } - if (entry->key_hash == key_hash && ht->compare_func(ht, pkey, entry)) { + if (entry->key_hash == key_hash && ht->compare_func(key, entry->key)) { break; } entry = ENTRY_NEXT(entry); @@ -214,28 +210,27 @@ _Py_hashtable_get_entry_generic(_Py_hashtable_t *ht, const void *pkey) static int -_Py_hashtable_pop_entry(_Py_hashtable_t *ht, size_t key_size, const void *pkey, +_Py_hashtable_pop_entry(_Py_hashtable_t *ht, const void *key, void *data, size_t data_size) { - Py_uhash_t key_hash; - size_t index; - _Py_hashtable_entry_t *entry, *previous; - assert(key_size == ht->key_size); + Py_uhash_t key_hash = ht->hash_func(key); + size_t index = key_hash & (ht->num_buckets - 1); - key_hash = ht->hash_func(ht, pkey); - index = key_hash & (ht->num_buckets - 1); - - previous = NULL; - for (entry = TABLE_HEAD(ht, index); entry != NULL; entry = ENTRY_NEXT(entry)) { - if (entry->key_hash == key_hash && ht->compare_func(ht, pkey, entry)) + _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index); + _Py_hashtable_entry_t *previous = NULL; + while (1) { + if (entry == NULL) { + // not found + return 0; + } + if (entry->key_hash == key_hash && ht->compare_func(key, entry->key)) { break; + } previous = entry; + entry = ENTRY_NEXT(entry); } - if (entry == NULL) - return 0; - _Py_slist_remove(&ht->buckets[index], (_Py_slist_item_t *)previous, (_Py_slist_item_t *)entry); ht->entries--; @@ -251,26 +246,22 @@ _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, +_Py_hashtable_set(_Py_hashtable_t *ht, const void *key, size_t data_size, const void *data) { - Py_uhash_t key_hash; - size_t index; _Py_hashtable_entry_t *entry; - assert(key_size == ht->key_size); - assert(data != NULL || data_size == 0); #ifndef NDEBUG /* Don't write the assertion on a single line because it is interesting to know the duplicated entry if the assertion failed. The entry can be read using a debugger. */ - entry = ht->get_entry_func(ht, pkey); + entry = ht->get_entry_func(ht, key); assert(entry == NULL); #endif - key_hash = ht->hash_func(ht, pkey); - index = key_hash & (ht->num_buckets - 1); + Py_uhash_t key_hash = ht->hash_func(key); + size_t index = key_hash & (ht->num_buckets - 1); entry = ht->alloc.malloc(HASHTABLE_ITEM_SIZE(ht)); if (entry == NULL) { @@ -279,9 +270,10 @@ _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey, } entry->key_hash = key_hash; - memcpy((void *)_Py_HASHTABLE_ENTRY_PKEY(entry), pkey, ht->key_size); - if (data) + entry->key = (void *)key; + if (data) { ENTRY_WRITE_PDATA(ht, entry, data_size, data); + } _Py_slist_prepend(&ht->buckets[index], (_Py_slist_item_t*)entry); ht->entries++; @@ -293,10 +285,10 @@ _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey, int -_Py_hashtable_get_generic(_Py_hashtable_t *ht, const void *pkey, void *data) +_Py_hashtable_get_generic(_Py_hashtable_t *ht, const void *key, void *data) { assert(data != NULL); - _Py_hashtable_entry_t *entry = ht->get_entry_func(ht, pkey); + _Py_hashtable_entry_t *entry = ht->get_entry_func(ht, key); if (entry != NULL) { ENTRY_READ_PDATA(ht, entry, ht->data_size, data); return 1; @@ -308,13 +300,12 @@ _Py_hashtable_get_generic(_Py_hashtable_t *ht, const void *pkey, void *data) // Specialized for: -// key_size == sizeof(void*) // hash_func == _Py_hashtable_hash_ptr // compare_func == _Py_hashtable_compare_direct _Py_hashtable_entry_t * -_Py_hashtable_get_entry_ptr(_Py_hashtable_t *ht, const void *pkey) +_Py_hashtable_get_entry_ptr(_Py_hashtable_t *ht, const void *key) { - Py_uhash_t key_hash = _Py_hashtable_hash_ptr(ht, pkey); + Py_uhash_t key_hash = _Py_hashtable_hash_ptr(key); size_t index = key_hash & (ht->num_buckets - 1); _Py_hashtable_entry_t *entry = entry = TABLE_HEAD(ht, index); while (1) { @@ -322,8 +313,7 @@ _Py_hashtable_get_entry_ptr(_Py_hashtable_t *ht, const void *pkey) return NULL; } if (entry->key_hash == key_hash) { - const void *pkey2 = _Py_HASHTABLE_ENTRY_PKEY(entry); - if (memcmp(pkey, pkey2, sizeof(void*)) == 0) { + if (entry->key == key) { break; } } @@ -334,14 +324,13 @@ _Py_hashtable_get_entry_ptr(_Py_hashtable_t *ht, const void *pkey) // Specialized for: -// key_size == sizeof(void*) // hash_func == _Py_hashtable_hash_ptr // compare_func == _Py_hashtable_compare_direct int -_Py_hashtable_get_ptr(_Py_hashtable_t *ht, const void *pkey, void *data) +_Py_hashtable_get_ptr(_Py_hashtable_t *ht, const void *key, void *data) { assert(data != NULL); - _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry_ptr(ht, pkey); + _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry_ptr(ht, key); if (entry != NULL) { ENTRY_READ_PDATA(ht, entry, ht->data_size, data); return 1; @@ -353,24 +342,24 @@ _Py_hashtable_get_ptr(_Py_hashtable_t *ht, const void *pkey, void *data) int -_Py_hashtable_pop(_Py_hashtable_t *ht, size_t key_size, const void *pkey, +_Py_hashtable_pop(_Py_hashtable_t *ht, const void *key, size_t data_size, void *data) { assert(data != NULL); - return _Py_hashtable_pop_entry(ht, key_size, pkey, data, data_size); + return _Py_hashtable_pop_entry(ht, key, data, data_size); } /* Code commented since the function is not needed in Python */ #if 0 void -_Py_hashtable_delete(_Py_hashtable_t *ht, size_t key_size, const void *pkey) +_Py_hashtable_delete(_Py_hashtable_t *ht, size_t const void *key) { #ifndef NDEBUG - int found = _Py_hashtable_pop_entry(ht, key_size, pkey, NULL, 0); + int found = _Py_hashtable_pop_entry(ht, key, NULL, 0); assert(found); #else - (void)_Py_hashtable_pop_entry(ht, key_size, pkey, NULL, 0); + (void)_Py_hashtable_pop_entry(ht, key, NULL, 0); #endif } #endif @@ -427,7 +416,7 @@ hashtable_rehash(_Py_hashtable_t *ht) size_t entry_index; - assert(ht->hash_func(ht, _Py_HASHTABLE_ENTRY_PKEY(entry)) == entry->key_hash); + assert(ht->hash_func(entry->key) == entry->key_hash); next = ENTRY_NEXT(entry); entry_index = entry->key_hash & (new_size - 1); @@ -440,8 +429,7 @@ hashtable_rehash(_Py_hashtable_t *ht) _Py_hashtable_t * -_Py_hashtable_new_full(size_t key_size, size_t data_size, - size_t init_size, +_Py_hashtable_new_full(size_t data_size, size_t init_size, _Py_hashtable_hash_func hash_func, _Py_hashtable_compare_func compare_func, _Py_hashtable_allocator_t *allocator) @@ -464,7 +452,6 @@ _Py_hashtable_new_full(size_t key_size, size_t data_size, ht->num_buckets = round_size(init_size); ht->entries = 0; - ht->key_size = key_size; ht->data_size = data_size; buckets_size = ht->num_buckets * sizeof(ht->buckets[0]); @@ -480,8 +467,7 @@ _Py_hashtable_new_full(size_t key_size, size_t data_size, ht->hash_func = hash_func; ht->compare_func = compare_func; ht->alloc = alloc; - if (ht->key_size == sizeof(void*) - && ht->hash_func == _Py_hashtable_hash_ptr + if (ht->hash_func == _Py_hashtable_hash_ptr && ht->compare_func == _Py_hashtable_compare_direct) { ht->get_func = _Py_hashtable_get_ptr; @@ -492,12 +478,11 @@ _Py_hashtable_new_full(size_t key_size, size_t data_size, _Py_hashtable_t * -_Py_hashtable_new(size_t key_size, size_t data_size, +_Py_hashtable_new(size_t data_size, _Py_hashtable_hash_func hash_func, _Py_hashtable_compare_func compare_func) { - return _Py_hashtable_new_full(key_size, data_size, - HASHTABLE_MIN_SIZE, + return _Py_hashtable_new_full(data_size, HASHTABLE_MIN_SIZE, hash_func, compare_func, NULL); } @@ -543,15 +528,13 @@ _Py_hashtable_destroy(_Py_hashtable_t *ht) _Py_hashtable_t * _Py_hashtable_copy(_Py_hashtable_t *src) { - const size_t key_size = src->key_size; const size_t data_size = src->data_size; _Py_hashtable_t *dst; _Py_hashtable_entry_t *entry; size_t bucket; int err; - dst = _Py_hashtable_new_full(key_size, data_size, - src->num_buckets, + dst = _Py_hashtable_new_full(data_size, src->num_buckets, src->hash_func, src->compare_func, &src->alloc); @@ -561,9 +544,9 @@ _Py_hashtable_copy(_Py_hashtable_t *src) for (bucket=0; bucket < src->num_buckets; bucket++) { entry = TABLE_HEAD(src, bucket); for (; entry; entry = ENTRY_NEXT(entry)) { - const void *pkey = _Py_HASHTABLE_ENTRY_PKEY(entry); + const void *key = entry->key; const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(src, entry); - err = _Py_hashtable_set(dst, key_size, pkey, data_size, pdata); + err = _Py_hashtable_set(dst, key, data_size, pdata); if (err) { _Py_hashtable_destroy(dst); return NULL; diff --git a/Python/marshal.c b/Python/marshal.c index d2bff524f30..1e901ae7c31 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -549,7 +549,7 @@ static int w_init_refs(WFILE *wf, int version) { if (version >= 3) { - wf->hashtable = _Py_hashtable_new(sizeof(PyObject *), sizeof(int), + wf->hashtable = _Py_hashtable_new(sizeof(int), _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct); if (wf->hashtable == NULL) { @@ -564,9 +564,7 @@ static int w_decref_entry(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry, void *Py_UNUSED(data)) { - PyObject *entry_key; - - _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, entry_key); + PyObject *entry_key = (PyObject *)entry->key; Py_XDECREF(entry_key); return 0; }