From 322bc12c3142e7816dd34c6c3085929ab29d3ed8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 21 Mar 2016 14:36:39 +0100 Subject: Ooops, revert changeset ea9efa06c137 Change pushed by mistake, the patch is still under review :-/ """ _tracemalloc: add domain to trace keys * hashtable.h: key has now a variable size * _tracemalloc uses (pointer: void*, domain: unsigned int) as key for traces """ --- Modules/_tracemalloc.c | 186 +++++++++++++------------------------------------ Modules/hashtable.c | 105 ++++++++++++---------------- Modules/hashtable.h | 89 +++++++---------------- Python/marshal.c | 11 ++- 4 files changed, 121 insertions(+), 270 deletions(-) diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index 73aa53b..5752904 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -3,7 +3,6 @@ #include "frameobject.h" #include "pythread.h" #include "osdefs.h" -#include /* For offsetof */ /* Trace memory blocks allocated by PyMem_RawMalloc() */ #define TRACE_RAW_MALLOC @@ -55,26 +54,6 @@ static PyThread_type_lock tables_lock; # define TABLES_UNLOCK() #endif -typedef unsigned int domain_t; - -/* FIXME: pack also? */ -typedef struct { - void *ptr; - domain_t domain; -} pointer_t; - -/* Size of pointer_t content, it can be smaller than sizeof(pointer_t) */ -#define POINTER_T_SIZE \ - (offsetof(pointer_t, domain) + sizeof(domain_t)) - -#define POINTER_T_FILL_PADDING(key) \ - do { \ - if (POINTER_T_SIZE != sizeof(pointer_t)) { \ - memset((char *)&(key) + POINTER_T_SIZE, 0, \ - sizeof(pointer_t) - POINTER_T_SIZE); \ - } \ - } while (0) - /* Pack the frame_t structure to reduce the memory footprint on 64-bit architectures: 12 bytes instead of 16. This optimization might produce SIGBUS on architectures not supporting unaligned memory accesses (64-bit @@ -217,56 +196,23 @@ set_reentrant(int reentrant) } #endif -static Py_uhash_t -hashtable_hash_pointer(size_t key_size, const void *pkey) -{ - pointer_t ptr; - Py_uhash_t hash; - - assert(sizeof(ptr) == key_size); - ptr = *(pointer_t *)pkey; - - hash = (Py_uhash_t)_Py_HashPointer(ptr.ptr); - hash ^= ptr.domain; - return hash; -} - -static Py_uhash_t -hashtable_hash_pyobject(size_t key_size, const void *pkey) -{ - PyObject *obj; - - assert(key_size == sizeof(PyObject *)); - obj = *(PyObject **)pkey; - - return PyObject_Hash(obj); -} - static int -hashtable_compare_unicode(size_t key_size, const void *pkey, - const _Py_hashtable_entry_t *entry) +hashtable_compare_unicode(const void *key, const _Py_hashtable_entry_t *entry) { - PyObject *key, *entry_key; - - assert(sizeof(key) == key_size); - key = *(PyObject **)pkey; - assert(sizeof(entry_key) == key_size); - entry_key = *(PyObject **)_Py_HASHTABLE_ENTRY_KEY(entry); - - if (key != NULL && entry_key != NULL) - return (PyUnicode_Compare(key, entry_key) == 0); + if (key != NULL && entry->key != NULL) + return (PyUnicode_Compare((PyObject *)key, (PyObject *)entry->key) == 0); else - return key == entry_key; + 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, +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, 0, + return _Py_hashtable_new_full(data_size, 0, hash_func, compare_func, NULL, NULL, NULL, &hashtable_alloc); } @@ -284,26 +230,20 @@ raw_free(void *ptr) } static Py_uhash_t -hashtable_hash_traceback(size_t key_size, const void *pkey) +hashtable_hash_traceback(const void *key) { - const traceback_t *traceback = *(const traceback_t **)pkey; - assert(key_size == sizeof(const traceback_t *)); + const traceback_t *traceback = key; return traceback->hash; } static int -hashtable_compare_traceback(size_t key_size, const void *pkey, +hashtable_compare_traceback(const traceback_t *traceback1, const _Py_hashtable_entry_t *he) { - traceback_t *traceback1, *traceback2; + const traceback_t *traceback2 = he->key; const frame_t *frame1, *frame2; int i; - assert(sizeof(traceback1) == key_size); - assert(sizeof(traceback2) == key_size); - traceback1 = *(traceback_t **)pkey; - traceback2 = *(traceback_t **)_Py_HASHTABLE_ENTRY_KEY(he); - if (traceback1->nframe != traceback2->nframe) return 0; @@ -372,16 +312,15 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame) } /* intern the filename */ - entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename); + entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename); if (entry != NULL) { - assert(sizeof(filename) == tracemalloc_filenames->key_size); - filename = *(PyObject **)_Py_HASHTABLE_ENTRY_KEY(entry); + filename = (PyObject *)entry->key; } else { /* tracemalloc_filenames is responsible to keep a reference to the filename */ Py_INCREF(filename); - if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) { + if (_Py_hashtable_set(tracemalloc_filenames, filename, NULL, 0) < 0) { Py_DECREF(filename); #ifdef TRACE_DEBUG tracemalloc_error("failed to intern the filename"); @@ -464,10 +403,9 @@ traceback_new(void) traceback->hash = traceback_hash(traceback); /* intern the traceback */ - entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback); + entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback); if (entry != NULL) { - assert(sizeof(traceback) == tracemalloc_tracebacks->key_size); - traceback = *(traceback_t **)_Py_HASHTABLE_ENTRY_KEY(entry); + traceback = (traceback_t *)entry->key; } else { traceback_t *copy; @@ -484,7 +422,7 @@ traceback_new(void) } memcpy(copy, traceback, traceback_size); - if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) { + if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL, 0) < 0) { raw_free(copy); #ifdef TRACE_DEBUG tracemalloc_error("failed to intern the traceback: putdata failed"); @@ -497,9 +435,8 @@ traceback_new(void) } static int -tracemalloc_add_trace(void *ptr, domain_t domain, size_t size) +tracemalloc_add_trace(void *ptr, size_t size) { - pointer_t key; traceback_t *traceback; trace_t trace; int res; @@ -508,14 +445,10 @@ tracemalloc_add_trace(void *ptr, domain_t domain, size_t size) if (traceback == NULL) return -1; - key.ptr = ptr; - key.domain = 0; - POINTER_T_FILL_PADDING(key); - trace.size = size; trace.traceback = traceback; - res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace); + res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace); if (res == 0) { assert(tracemalloc_traced_memory <= PY_SIZE_MAX - size); tracemalloc_traced_memory += size; @@ -527,16 +460,11 @@ tracemalloc_add_trace(void *ptr, domain_t domain, size_t size) } static void -tracemalloc_remove_trace(void *ptr, domain_t domain) +tracemalloc_remove_trace(void *ptr) { - pointer_t key; trace_t trace; - key.ptr = ptr; - key.domain = domain; - POINTER_T_FILL_PADDING(key); - - if (_Py_HASHTABLE_POP(tracemalloc_traces, key, trace)) { + if (_Py_hashtable_pop(tracemalloc_traces, ptr, &trace, sizeof(trace))) { assert(tracemalloc_traced_memory >= trace.size); tracemalloc_traced_memory -= trace.size; } @@ -558,7 +486,7 @@ tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize) return NULL; TABLES_LOCK(); - if (tracemalloc_add_trace(ptr, 0, nelem * elsize) < 0) { + if (tracemalloc_add_trace(ptr, nelem * elsize) < 0) { /* Failed to allocate a trace for the new memory block */ TABLES_UNLOCK(); alloc->free(alloc->ctx, ptr); @@ -582,9 +510,9 @@ tracemalloc_realloc(void *ctx, void *ptr, size_t new_size) /* an existing memory block has been resized */ TABLES_LOCK(); - tracemalloc_remove_trace(ptr, 0); + tracemalloc_remove_trace(ptr); - if (tracemalloc_add_trace(ptr2, 0, new_size) < 0) { + if (tracemalloc_add_trace(ptr2, new_size) < 0) { /* Memory allocation failed. The error cannot be reported to the caller, because realloc() may already have shrinked the memory block and so removed bytes. @@ -602,7 +530,7 @@ tracemalloc_realloc(void *ctx, void *ptr, size_t new_size) /* new allocation */ TABLES_LOCK(); - if (tracemalloc_add_trace(ptr2, 0, new_size) < 0) { + if (tracemalloc_add_trace(ptr2, new_size) < 0) { /* Failed to allocate a trace for the new memory block */ TABLES_UNLOCK(); alloc->free(alloc->ctx, ptr2); @@ -627,7 +555,7 @@ tracemalloc_free(void *ctx, void *ptr) alloc->free(alloc->ctx, ptr); TABLES_LOCK(); - tracemalloc_remove_trace(ptr, 0); + tracemalloc_remove_trace(ptr); TABLES_UNLOCK(); } @@ -682,7 +610,7 @@ tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size) ptr2 = alloc->realloc(alloc->ctx, ptr, new_size); if (ptr2 != NULL && ptr != NULL) { TABLES_LOCK(); - tracemalloc_remove_trace(ptr, 0); + tracemalloc_remove_trace(ptr); TABLES_UNLOCK(); } return ptr2; @@ -761,7 +689,7 @@ tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size) if (ptr2 != NULL && ptr != NULL) { TABLES_LOCK(); - tracemalloc_remove_trace(ptr, 0); + tracemalloc_remove_trace(ptr); TABLES_UNLOCK(); } return ptr2; @@ -786,27 +714,17 @@ tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size) #endif /* TRACE_RAW_MALLOC */ static int -tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry, - void *user_data) +tracemalloc_clear_filename(_Py_hashtable_entry_t *entry, void *user_data) { - PyObject *filename; - - assert(sizeof(filename) == ht->key_size); - filename = *(PyObject **)_Py_HASHTABLE_ENTRY_KEY(entry); - + PyObject *filename = (PyObject *)entry->key; Py_DECREF(filename); return 0; } static int -traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry, - void *user_data) +traceback_free_traceback(_Py_hashtable_entry_t *entry, void *user_data) { - traceback_t *traceback; - - assert(sizeof(traceback) == ht->key_size); - traceback = *(traceback_t **)_Py_HASHTABLE_ENTRY_KEY(entry); - + traceback_t *traceback = (traceback_t *)entry->key; raw_free(traceback); return 0; } @@ -873,16 +791,16 @@ tracemalloc_init(void) } #endif - tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0, - hashtable_hash_pyobject, + tracemalloc_filenames = hashtable_new(0, + (_Py_hashtable_hash_func)PyObject_Hash, hashtable_compare_unicode); - tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0, - hashtable_hash_traceback, - hashtable_compare_traceback); + tracemalloc_tracebacks = hashtable_new(0, + (_Py_hashtable_hash_func)hashtable_hash_traceback, + (_Py_hashtable_compare_func)hashtable_compare_traceback); - tracemalloc_traces = hashtable_new(sizeof(pointer_t), sizeof(trace_t), - hashtable_hash_pointer, + tracemalloc_traces = hashtable_new(sizeof(trace_t), + _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct); if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL @@ -1147,15 +1065,14 @@ typedef struct { } get_traces_t; static int -tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry, - void *user_data) +tracemalloc_get_traces_fill(_Py_hashtable_entry_t *entry, void *user_data) { get_traces_t *get_traces = user_data; trace_t *trace; PyObject *tracemalloc_obj; int res; - trace = (trace_t *)_Py_HASHTABLE_ENTRY_DATA(traces, entry); + trace = (trace_t *)_Py_HASHTABLE_ENTRY_DATA(entry); tracemalloc_obj = trace_to_pyobject(trace, get_traces->tracebacks); if (tracemalloc_obj == NULL) @@ -1170,11 +1087,9 @@ tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entr } static int -tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks, - _Py_hashtable_entry_t *entry, - void *user_data) +tracemalloc_pyobject_decref_cb(_Py_hashtable_entry_t *entry, void *user_data) { - PyObject *obj = (PyObject *)_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(tracebacks, entry); + PyObject *obj = (PyObject *)_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry); Py_DECREF(obj); return 0; } @@ -1205,7 +1120,7 @@ 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(PyObject *), _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct); if (get_traces.tracebacks == NULL) { @@ -1237,7 +1152,7 @@ error: finally: if (get_traces.tracebacks != NULL) { _Py_hashtable_foreach(get_traces.tracebacks, - tracemalloc_pyobject_decref_cb, NULL); + tracemalloc_pyobject_decref_cb, NULL); _Py_hashtable_destroy(get_traces.tracebacks); } if (get_traces.traces != NULL) @@ -1247,21 +1162,16 @@ finally: } static traceback_t* -tracemalloc_get_traceback(const void *ptr, domain_t domain) +tracemalloc_get_traceback(const void *ptr) { - pointer_t key; trace_t trace; int found; if (!tracemalloc_config.tracing) return NULL; - key.ptr = (void *)ptr; - key.domain = domain; - POINTER_T_FILL_PADDING(key); - TABLES_LOCK(); - found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace); + found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace); TABLES_UNLOCK(); if (!found) @@ -1292,7 +1202,7 @@ py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj) else ptr = (void *)obj; - traceback = tracemalloc_get_traceback(ptr, 0); + traceback = tracemalloc_get_traceback(ptr); if (traceback == NULL) Py_RETURN_NONE; @@ -1319,7 +1229,7 @@ _PyMem_DumpTraceback(int fd, const void *ptr) traceback_t *traceback; int i; - traceback = tracemalloc_get_traceback(ptr, 0); + traceback = tracemalloc_get_traceback(ptr); if (traceback == NULL) return; diff --git a/Modules/hashtable.c b/Modules/hashtable.c index 002c0a9..7de154b 100644 --- a/Modules/hashtable.c +++ b/Modules/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) /* Forward declaration */ static void hashtable_rehash(_Py_hashtable_t *ht); @@ -88,21 +88,21 @@ _Py_slist_remove(_Py_slist_t *list, _Py_slist_item_t *previous, } Py_uhash_t -_Py_hashtable_hash_ptr(size_t key_size, const void *pkey) +_Py_hashtable_hash_int(const void *key) { - void *key; - - assert(key_size == sizeof(void *)); - key = *(void**)pkey; + return (Py_uhash_t)key; +} +Py_uhash_t +_Py_hashtable_hash_ptr(const void *key) +{ return (Py_uhash_t)_Py_HashPointer((void *)key); } int -_Py_hashtable_compare_direct(size_t key_size, const void *pkey, - const _Py_hashtable_entry_t *entry) +_Py_hashtable_compare_direct(const void *key, const _Py_hashtable_entry_t *entry) { - return (memcmp(pkey, _Py_HASHTABLE_ENTRY_KEY(entry), key_size) == 0); + return entry->key == key; } /* makes sure the real size of the buckets array is a power of 2 */ @@ -119,8 +119,7 @@ round_size(size_t s) } _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_copy_data_func copy_data_func, @@ -145,7 +144,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]); @@ -166,12 +164,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, NULL, NULL, NULL); } @@ -198,7 +195,7 @@ _Py_hashtable_size(_Py_hashtable_t *ht) for (entry = TABLE_HEAD(ht, hv); entry; entry = ENTRY_NEXT(entry)) { void *data; - data = _Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(ht, entry); + data = _Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry); size += ht->get_data_size_func(data); } } @@ -248,21 +245,17 @@ _Py_hashtable_print_stats(_Py_hashtable_t *ht) /* Get an entry. Return NULL if the key does not exist. */ _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) { Py_uhash_t key_hash; size_t index; _Py_hashtable_entry_t *entry; - assert(key_size == ht->key_size); - - key_hash = ht->hash_func(key_size, pkey); + key_hash = ht->hash_func(key); index = key_hash & (ht->num_buckets - 1); for (entry = TABLE_HEAD(ht, index); entry != NULL; entry = ENTRY_NEXT(entry)) { - if (entry->key_hash == key_hash - && ht->compare_func(key_size, pkey, entry)) + if (entry->key_hash == key_hash && ht->compare_func(key, entry)) break; } @@ -270,20 +263,18 @@ _Py_hashtable_get_entry(_Py_hashtable_t *ht, } static int -_hashtable_pop_entry(_Py_hashtable_t *ht, size_t key_size, const void *pkey, - void *data, size_t data_size) +_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; - key_hash = ht->hash_func(key_size, pkey); + key_hash = ht->hash_func(key); 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(key_size, pkey, entry)) + if (entry->key_hash == key_hash && ht->compare_func(key, entry)) break; previous = entry; } @@ -307,8 +298,8 @@ _hashtable_pop_entry(_Py_hashtable_t *ht, size_t key_size, const void *pkey, /* Add a new entry to the hash. The key must not be present in the hash table. Return 0 on success, -1 on memory error. */ int -_Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey, - size_t data_size, void *data) +_Py_hashtable_set(_Py_hashtable_t *ht, const void *key, + void *data, size_t data_size) { Py_uhash_t key_hash; size_t index; @@ -319,11 +310,11 @@ _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey, /* 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 = _Py_hashtable_get_entry(ht, key_size, pkey); + entry = _Py_hashtable_get_entry(ht, key); assert(entry == NULL); #endif - key_hash = ht->hash_func(key_size, pkey); + key_hash = ht->hash_func(key); index = key_hash & (ht->num_buckets - 1); entry = ht->alloc.malloc(HASHTABLE_ITEM_SIZE(ht)); @@ -332,11 +323,11 @@ _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey, return -1; } + entry->key = (void *)key; entry->key_hash = key_hash; - memcpy(_Py_HASHTABLE_ENTRY_KEY(entry), pkey, key_size); assert(data_size == ht->data_size); - memcpy(_Py_HASHTABLE_ENTRY_DATA(ht, entry), data, data_size); + memcpy(_Py_HASHTABLE_ENTRY_DATA(entry), data, data_size); _Py_slist_prepend(&ht->buckets[index], (_Py_slist_item_t*)entry); ht->entries++; @@ -349,14 +340,13 @@ _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey, /* Get data from an entry. Copy entry data into data and return 1 if the entry exists, return 0 if the entry does not exist. */ int -_Py_hashtable_get(_Py_hashtable_t *ht, size_t key_size,const void *pkey, - size_t data_size, void *data) +_Py_hashtable_get(_Py_hashtable_t *ht, const void *key, void *data, size_t data_size) { _Py_hashtable_entry_t *entry; assert(data != NULL); - entry = _Py_hashtable_get_entry(ht, key_size, pkey); + entry = _Py_hashtable_get_entry(ht, key); if (entry == NULL) return 0; _Py_HASHTABLE_ENTRY_READ_DATA(ht, data, data_size, entry); @@ -364,23 +354,22 @@ _Py_hashtable_get(_Py_hashtable_t *ht, size_t key_size,const void *pkey, } int -_Py_hashtable_pop(_Py_hashtable_t *ht, size_t key_size, const void *pkey, - size_t data_size, void *data) +_Py_hashtable_pop(_Py_hashtable_t *ht, const void *key, void *data, size_t data_size) { assert(data != NULL); assert(ht->free_data_func == NULL); - return _hashtable_pop_entry(ht, key_size, pkey, data, data_size); + return _hashtable_pop_entry(ht, key, data, data_size); } /* Delete an entry. The entry must exist. */ void -_Py_hashtable_delete(_Py_hashtable_t *ht, size_t key_size, const void *pkey) +_Py_hashtable_delete(_Py_hashtable_t *ht, const void *key) { #ifndef NDEBUG - int found = _hashtable_pop_entry(ht, key_size, pkey, NULL, 0); + int found = _hashtable_pop_entry(ht, key, NULL, 0); assert(found); #else - (void)_hashtable_pop_entry(ht, key_size, pkey, NULL, 0); + (void)_hashtable_pop_entry(ht, key, NULL, 0); #endif } @@ -389,7 +378,7 @@ _Py_hashtable_delete(_Py_hashtable_t *ht, size_t key_size, const void *pkey) stops if a non-zero value is returned. */ int _Py_hashtable_foreach(_Py_hashtable_t *ht, - _Py_hashtable_foreach_func func, + int (*func) (_Py_hashtable_entry_t *entry, void *arg), void *arg) { _Py_hashtable_entry_t *entry; @@ -397,7 +386,7 @@ _Py_hashtable_foreach(_Py_hashtable_t *ht, for (hv = 0; hv < ht->num_buckets; hv++) { for (entry = TABLE_HEAD(ht, hv); entry; entry = ENTRY_NEXT(entry)) { - int res = func(ht, entry, arg); + int res = func(entry, arg); if (res) return res; } @@ -408,7 +397,6 @@ _Py_hashtable_foreach(_Py_hashtable_t *ht, static void hashtable_rehash(_Py_hashtable_t *ht) { - const size_t key_size = ht->key_size; size_t buckets_size, new_size, bucket; _Py_slist_t *old_buckets = NULL; size_t old_num_buckets; @@ -437,8 +425,7 @@ hashtable_rehash(_Py_hashtable_t *ht) for (entry = BUCKETS_HEAD(old_buckets[bucket]); entry != NULL; entry = next) { size_t entry_index; - - assert(ht->hash_func(key_size, _Py_HASHTABLE_ENTRY_KEY(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); @@ -459,7 +446,7 @@ _Py_hashtable_clear(_Py_hashtable_t *ht) 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->free_data_func(_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry)); ht->alloc.free(entry); } _Py_slist_init(&ht->buckets[i]); @@ -478,7 +465,7 @@ _Py_hashtable_destroy(_Py_hashtable_t *ht) 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->free_data_func(_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry)); ht->alloc.free(entry); entry = entry_next; } @@ -492,16 +479,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; void *data, *new_data; - dst = _Py_hashtable_new_full(key_size, data_size, - src->num_buckets, + dst = _Py_hashtable_new_full(src->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); @@ -512,20 +496,17 @@ _Py_hashtable_copy(_Py_hashtable_t *src) 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); + data = _Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(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); + err = _Py_hashtable_set(dst, entry->key, + &new_data, src->data_size); 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); + data = _Py_HASHTABLE_ENTRY_DATA(entry); + err = _Py_hashtable_set(dst, entry->key, data, src->data_size); } if (err) { _Py_hashtable_destroy(dst); diff --git a/Modules/hashtable.h b/Modules/hashtable.h index aed3ed0..a9f9993 100644 --- a/Modules/hashtable.h +++ b/Modules/hashtable.h @@ -20,31 +20,26 @@ typedef struct { /* used by _Py_hashtable_t.buckets to link entries */ _Py_slist_item_t _Py_slist_item; + const void *key; Py_uhash_t key_hash; /* data follows */ } _Py_hashtable_entry_t; -#define _Py_HASHTABLE_ENTRY_KEY(ENTRY) \ - ((void *)((char *)(ENTRY) + sizeof(_Py_hashtable_entry_t))) +#define _Py_HASHTABLE_ENTRY_DATA(ENTRY) \ + ((char *)(ENTRY) + sizeof(_Py_hashtable_entry_t)) -#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)) +#define _Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(ENTRY) \ + (*(void **)_Py_HASHTABLE_ENTRY_DATA(ENTRY)) #define _Py_HASHTABLE_ENTRY_READ_DATA(TABLE, DATA, DATA_SIZE, ENTRY) \ do { \ assert((DATA_SIZE) == (TABLE)->data_size); \ - memcpy(DATA, _Py_HASHTABLE_ENTRY_DATA(TABLE, ENTRY), DATA_SIZE); \ + memcpy(DATA, _Py_HASHTABLE_ENTRY_DATA(ENTRY), DATA_SIZE); \ } while (0) -typedef Py_uhash_t (*_Py_hashtable_hash_func) (size_t key_size, - const void *pkey); -typedef int (*_Py_hashtable_compare_func) (size_t key_size, - 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 *key, 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); @@ -61,7 +56,6 @@ typedef struct { 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_hash_func hash_func; @@ -73,21 +67,15 @@ typedef struct { } _Py_hashtable_t; /* hash and compare functions for integers and pointers */ -PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr( - size_t key_size, - const void *pkey); -PyAPI_FUNC(int) _Py_hashtable_compare_direct( - size_t key_size, - const void *pkey, - const _Py_hashtable_entry_t *entry); +PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr(const void *key); +PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_int(const void *key); +PyAPI_FUNC(int) _Py_hashtable_compare_direct(const void *key, const _Py_hashtable_entry_t *entry); 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, @@ -100,65 +88,40 @@ PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_copy(_Py_hashtable_t *src); PyAPI_FUNC(void) _Py_hashtable_clear(_Py_hashtable_t *ht); PyAPI_FUNC(void) _Py_hashtable_destroy(_Py_hashtable_t *ht); -typedef int (*_Py_hashtable_foreach_func) (_Py_hashtable_t *ht, - _Py_hashtable_entry_t *entry, - void *arg); +typedef int (*_Py_hashtable_foreach_func) (_Py_hashtable_entry_t *entry, void *arg); PyAPI_FUNC(int) _Py_hashtable_foreach( _Py_hashtable_t *ht, - _Py_hashtable_foreach_func func, - void *arg); + _Py_hashtable_foreach_func func, void *arg); PyAPI_FUNC(size_t) _Py_hashtable_size(_Py_hashtable_t *ht); PyAPI_FUNC(_Py_hashtable_entry_t*) _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_SET() and _Py_HASHTABLE_SET_NODATA() macros */ + const void *key); PyAPI_FUNC(int) _Py_hashtable_set( _Py_hashtable_t *ht, - size_t key_size, - const void *pkey, - size_t data_size, - void *data); - -/* Don't call directly this function, but use _Py_HASHTABLE_GET() macro */ + const void *key, + void *data, + size_t data_size); PyAPI_FUNC(int) _Py_hashtable_get( _Py_hashtable_t *ht, - size_t key_size, - const void *pkey, - size_t data_size, - void *data); - -/* Don't call directly this function, but use _Py_HASHTABLE_POP() macro */ + const void *key, + void *data, + size_t data_size); PyAPI_FUNC(int) _Py_hashtable_pop( _Py_hashtable_t *ht, - size_t key_size, - const void *pkey, - size_t data_size, - void *data); - + const void *key, + void *data, + size_t data_size); PyAPI_FUNC(void) _Py_hashtable_delete( _Py_hashtable_t *ht, - size_t key_size, - const void *pkey); + const void *key); #define _Py_HASHTABLE_SET(TABLE, KEY, DATA) \ - _Py_hashtable_set(TABLE, sizeof(KEY), &KEY, sizeof(DATA), &(DATA)) - -#define _Py_HASHTABLE_SET_NODATA(TABLE, KEY) \ - _Py_hashtable_set(TABLE, sizeof(KEY), &KEY, 0, NULL) - -#define _Py_HASHTABLE_GET_ENTRY(TABLE, KEY) \ - _Py_hashtable_get_entry(TABLE, sizeof(KEY), &(KEY)) + _Py_hashtable_set(TABLE, KEY, &(DATA), sizeof(DATA)) #define _Py_HASHTABLE_GET(TABLE, KEY, DATA) \ - _Py_hashtable_get(TABLE, sizeof(KEY), &(KEY), sizeof(DATA), &(DATA)) - -#define _Py_HASHTABLE_POP(TABLE, KEY, DATA) \ - _Py_hashtable_pop(TABLE, sizeof(KEY), &(KEY), sizeof(DATA), &(DATA)) + _Py_hashtable_get(TABLE, KEY, &(DATA), sizeof(DATA)) #endif /* Py_LIMITED_API */ diff --git a/Python/marshal.c b/Python/marshal.c index 64084f4..7a4b9d2 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -263,7 +263,7 @@ w_ref(PyObject *v, char *flag, WFILE *p) if (Py_REFCNT(v) == 1) return 0; - entry = _Py_HASHTABLE_GET_ENTRY(p->hashtable, v); + entry = _Py_hashtable_get_entry(p->hashtable, v); if (entry != NULL) { /* write the reference index to the stream */ _Py_HASHTABLE_ENTRY_READ_DATA(p->hashtable, &w, sizeof(w), entry); @@ -571,8 +571,7 @@ static int w_init_refs(WFILE *wf, int version) { if (version >= 3) { - wf->hashtable = _Py_hashtable_new(sizeof(void *), sizeof(int), - _Py_hashtable_hash_ptr, + wf->hashtable = _Py_hashtable_new(sizeof(int), _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct); if (wf->hashtable == NULL) { PyErr_NoMemory(); @@ -583,11 +582,9 @@ w_init_refs(WFILE *wf, int version) } static int -w_decref_entry(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry, void *Py_UNUSED(data)) +w_decref_entry(_Py_hashtable_entry_t *entry, void *Py_UNUSED(data)) { - void *entry_key = *(void **)_Py_HASHTABLE_ENTRY_KEY(entry); - assert(ht->key_size == sizeof(entry_key)); - Py_XDECREF(entry_key); + Py_XDECREF(entry->key); return 0; } -- cgit v0.12