diff --git a/Include/internal/pycore_hashtable.h b/Include/internal/pycore_hashtable.h index 0da2ffdb389e51..2990f9e0c1cc6f 100644 --- a/Include/internal/pycore_hashtable.h +++ b/Include/internal/pycore_hashtable.h @@ -31,20 +31,9 @@ typedef struct { Py_uhash_t key_hash; void *key; - /* data (data_size bytes) follows */ + void *value; } _Py_hashtable_entry_t; -#define _Py_HASHTABLE_ENTRY_PDATA(ENTRY) \ - ((const void *)((char *)(ENTRY) \ - + sizeof(_Py_hashtable_entry_t))) - -#define _Py_HASHTABLE_ENTRY_READ_DATA(TABLE, ENTRY, DATA) \ - do { \ - assert(sizeof(DATA) == (TABLE)->data_size); \ - memcpy(&(DATA), _Py_HASHTABLE_ENTRY_PDATA((ENTRY)), \ - sizeof(DATA)); \ - } while (0) - /* _Py_hashtable: prototypes */ @@ -55,12 +44,8 @@ typedef struct _Py_hashtable_t _Py_hashtable_t; typedef Py_uhash_t (*_Py_hashtable_hash_func) (const void *key); typedef int (*_Py_hashtable_compare_func) (const void *key1, const void *key2); typedef void (*_Py_hashtable_destroy_func) (void *key); -typedef void (*_Py_hashtable_value_destroy_func) (_Py_hashtable_t *ht, - _Py_hashtable_entry_t *entry); typedef _Py_hashtable_entry_t* (*_Py_hashtable_get_entry_func)(_Py_hashtable_t *ht, const void *key); -typedef int (*_Py_hashtable_get_func) (_Py_hashtable_t *ht, - const void *key, void *data); typedef struct { /* allocate a memory block */ @@ -76,14 +61,12 @@ struct _Py_hashtable_t { size_t num_buckets; size_t entries; /* Total number of entries in the table. */ _Py_slist_t *buckets; - size_t data_size; - _Py_hashtable_get_func get_func; _Py_hashtable_get_entry_func get_entry_func; _Py_hashtable_hash_func hash_func; _Py_hashtable_compare_func compare_func; _Py_hashtable_destroy_func key_destroy_func; - _Py_hashtable_value_destroy_func value_destroy_func; + _Py_hashtable_destroy_func value_destroy_func; _Py_hashtable_allocator_t alloc; }; @@ -96,17 +79,14 @@ PyAPI_FUNC(int) _Py_hashtable_compare_direct( const void *key2); PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new( - 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 data_size, - size_t init_size, _Py_hashtable_hash_func hash_func, _Py_hashtable_compare_func compare_func, _Py_hashtable_destroy_func key_destroy_func, - _Py_hashtable_value_destroy_func value_destroy_func, + _Py_hashtable_destroy_func value_destroy_func, _Py_hashtable_allocator_t *allocator); PyAPI_FUNC(void) _Py_hashtable_destroy(_Py_hashtable_t *ht); @@ -114,8 +94,8 @@ PyAPI_FUNC(void) _Py_hashtable_destroy(_Py_hashtable_t *ht); PyAPI_FUNC(void) _Py_hashtable_clear(_Py_hashtable_t *ht); typedef int (*_Py_hashtable_foreach_func) (_Py_hashtable_t *ht, - _Py_hashtable_entry_t *entry, - void *arg); + const void *key, const void *value, + void *user_data); /* Call func() on each entry of the hashtable. Iteration stops if func() result is non-zero, in this case it's the result @@ -123,68 +103,42 @@ typedef int (*_Py_hashtable_foreach_func) (_Py_hashtable_t *ht, PyAPI_FUNC(int) _Py_hashtable_foreach( _Py_hashtable_t *ht, _Py_hashtable_foreach_func func, - void *arg); + void *user_data); -PyAPI_FUNC(size_t) _Py_hashtable_size(_Py_hashtable_t *ht); +PyAPI_FUNC(size_t) _Py_hashtable_size(const _Py_hashtable_t *ht); /* 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. - - Don't call directly this function, - but use _Py_HASHTABLE_SET() and _Py_HASHTABLE_SET_NODATA() macros */ + Return 0 on success, -1 on memory error. */ PyAPI_FUNC(int) _Py_hashtable_set( _Py_hashtable_t *ht, const void *key, - size_t data_size, - const void *data); - -#define _Py_HASHTABLE_SET(TABLE, KEY, DATA) \ - _Py_hashtable_set(TABLE, (KEY), sizeof(DATA), &(DATA)) - -#define _Py_HASHTABLE_SET_NODATA(TABLE, KEY) \ - _Py_hashtable_set(TABLE, (KEY), 0, NULL) + void *value); /* Get an entry. - Return NULL if the key does not exist. - - Don't call directly this function, but use _Py_HASHTABLE_GET_ENTRY() - macro */ + Return NULL if the key does not exist. */ static inline _Py_hashtable_entry_t * _Py_hashtable_get_entry(_Py_hashtable_t *ht, const void *key) { return ht->get_entry_func(ht, key); } -#define _Py_HASHTABLE_GET_ENTRY(TABLE, KEY) \ - _Py_hashtable_get_entry(TABLE, (const void *)(KEY)) +/* Get value from an entry. + Return NULL if the entry is not found. -/* 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. + Use _Py_hashtable_get_entry() to distinguish entry value equal to NULL + and entry not found. */ +extern void *_Py_hashtable_get(_Py_hashtable_t *ht, const void *key); - Don't call directly this function, but use _Py_HASHTABLE_GET() macro */ -static inline int -_Py_hashtable_get(_Py_hashtable_t *ht, const void *key, - size_t data_size, void *data) -{ - assert(data_size == ht->data_size); - return ht->get_func(ht, key, data); -} - -#define _Py_HASHTABLE_GET(TABLE, KEY, 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( +// Remove a key and its associated value without calling key and value destroy +// functions. +// Return the removed value if the key was found. +// Return NULL if the key was not found. +PyAPI_FUNC(void*) _Py_hashtable_steal( _Py_hashtable_t *ht, - const void *key, - size_t data_size, - void *data); - -#define _Py_HASHTABLE_POP(TABLE, KEY, DATA) \ - _Py_hashtable_pop(TABLE, (KEY), sizeof(DATA), &(DATA)) + const void *key); #ifdef __cplusplus diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index a42349a8e47192..4522d1afde9089 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -23,8 +23,8 @@ 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) +#define TO_PTR(key) ((const void *)(uintptr_t)(key)) +#define FROM_PTR(key) ((uintptr_t)(key)) /* Protected by the GIL */ static struct { @@ -236,15 +236,15 @@ hashtable_hash_uint(const void *key_raw) static _Py_hashtable_t * -hashtable_new(size_t data_size, - _Py_hashtable_hash_func hash_func, +hashtable_new(_Py_hashtable_hash_func hash_func, _Py_hashtable_compare_func compare_func, - _Py_hashtable_value_destroy_func value_destroy_fun) + _Py_hashtable_destroy_func key_destroy_func, + _Py_hashtable_destroy_func value_destroy_func) { _Py_hashtable_allocator_t hashtable_alloc = {malloc, free}; - return _Py_hashtable_new_full(data_size, 0, - hash_func, compare_func, - NULL, value_destroy_fun, &hashtable_alloc); + return _Py_hashtable_new_full(hash_func, compare_func, + key_destroy_func, value_destroy_func, + &hashtable_alloc); } @@ -340,7 +340,7 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame) /* intern the filename */ _Py_hashtable_entry_t *entry; - entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename); + entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename); if (entry != NULL) { filename = (PyObject *)entry->key; } @@ -348,7 +348,7 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame) /* 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) { Py_DECREF(filename); #ifdef TRACE_DEBUG tracemalloc_error("failed to intern the filename"); @@ -435,7 +435,7 @@ 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) { traceback = (traceback_t *)entry->key; } @@ -454,7 +454,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) { raw_free(copy); #ifdef TRACE_DEBUG tracemalloc_error("failed to intern the traceback: putdata failed"); @@ -467,50 +467,22 @@ traceback_new(void) } -static void -tracemalloc_destroy_trace_cb(_Py_hashtable_t *traces, - _Py_hashtable_entry_t *entry) -{ - trace_t *trace; - _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace); - raw_free(trace); -} - - static _Py_hashtable_t* tracemalloc_create_traces_table(void) { - return hashtable_new(sizeof(trace_t*), - _Py_hashtable_hash_ptr, + return hashtable_new(_Py_hashtable_hash_ptr, _Py_hashtable_compare_direct, - tracemalloc_destroy_trace_cb); -} - - -static void -tracemalloc_destroy_domain_table(_Py_hashtable_t *domains, - _Py_hashtable_entry_t *entry) -{ - _Py_hashtable_t *traces; - _Py_HASHTABLE_ENTRY_READ_DATA(domains, entry, traces); - _Py_hashtable_destroy(traces); + NULL, raw_free); } static _Py_hashtable_t* tracemalloc_create_domains_table(void) { - return hashtable_new(sizeof(_Py_hashtable_t *), - hashtable_hash_uint, + return hashtable_new(hashtable_hash_uint, _Py_hashtable_compare_direct, - tracemalloc_destroy_domain_table); -} - - -static void -tracemalloc_destroy_domains(_Py_hashtable_t *domains) -{ - _Py_hashtable_destroy(domains); + NULL, + (_Py_hashtable_destroy_func)_Py_hashtable_destroy); } @@ -521,9 +493,7 @@ tracemalloc_get_traces_table(unsigned int domain) return tracemalloc_traces; } else { - _Py_hashtable_t *traces = NULL; - (void)_Py_HASHTABLE_GET(tracemalloc_domains, TO_PTR(domain), traces); - return traces; + return _Py_hashtable_get(tracemalloc_domains, TO_PTR(domain)); } } @@ -538,8 +508,8 @@ tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr) return; } - trace_t *trace; - if (!_Py_HASHTABLE_POP(traces, TO_PTR(ptr), trace)) { + trace_t *trace = _Py_hashtable_steal(traces, TO_PTR(ptr)); + if (!trace) { return; } assert(tracemalloc_traced_memory >= trace->size); @@ -569,17 +539,15 @@ tracemalloc_add_trace(unsigned int domain, uintptr_t ptr, return -1; } - if (_Py_HASHTABLE_SET(tracemalloc_domains, TO_PTR(domain), traces) < 0) { + if (_Py_hashtable_set(tracemalloc_domains, TO_PTR(domain), traces) < 0) { _Py_hashtable_destroy(traces); return -1; } } - _Py_hashtable_entry_t* entry = _Py_HASHTABLE_GET_ENTRY(traces, ptr); - if (entry != NULL) { + trace_t *trace = _Py_hashtable_get(traces, TO_PTR(ptr)); + if (trace != NULL) { /* the memory block is already tracked */ - trace_t *trace; - _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace); assert(tracemalloc_traced_memory >= trace->size); tracemalloc_traced_memory -= trace->size; @@ -587,14 +555,14 @@ tracemalloc_add_trace(unsigned int domain, uintptr_t ptr, trace->traceback = traceback; } else { - trace_t *trace = raw_malloc(sizeof(trace_t)); + trace = raw_malloc(sizeof(trace_t)); if (trace == NULL) { return -1; } trace->size = size; trace->traceback = traceback; - int res = _Py_HASHTABLE_SET(traces, TO_PTR(ptr), trace); + int res = _Py_hashtable_set(traces, TO_PTR(ptr), trace); if (res != 0) { raw_free(trace); return res; @@ -860,23 +828,11 @@ 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) +static void +tracemalloc_clear_filename(void *value) { - PyObject *filename = (PyObject *)entry->key; + PyObject *filename = (PyObject *)value; Py_DECREF(filename); - return 0; -} - - -static int -traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry, - void *user_data) -{ - traceback_t *traceback = (traceback_t *)entry->key; - raw_free(traceback); - return 0; } @@ -894,10 +850,8 @@ tracemalloc_clear_traces(void) tracemalloc_peak_traced_memory = 0; TABLES_UNLOCK(); - _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL); _Py_hashtable_clear(tracemalloc_tracebacks); - _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL); _Py_hashtable_clear(tracemalloc_filenames); } @@ -937,15 +891,13 @@ tracemalloc_init(void) } #endif - tracemalloc_filenames = hashtable_new(0, - hashtable_hash_pyobject, + tracemalloc_filenames = hashtable_new(hashtable_hash_pyobject, hashtable_compare_unicode, - NULL); + tracemalloc_clear_filename, NULL); - tracemalloc_tracebacks = hashtable_new(0, - hashtable_hash_traceback, + tracemalloc_tracebacks = hashtable_new(hashtable_hash_traceback, hashtable_compare_traceback, - NULL); + NULL, raw_free); tracemalloc_traces = tracemalloc_create_traces_table(); tracemalloc_domains = tracemalloc_create_domains_table(); @@ -983,7 +935,7 @@ tracemalloc_deinit(void) tracemalloc_stop(); /* destroy hash tables */ - tracemalloc_destroy_domains(tracemalloc_domains); + _Py_hashtable_destroy(tracemalloc_domains); _Py_hashtable_destroy(tracemalloc_traces); _Py_hashtable_destroy(tracemalloc_tracebacks); _Py_hashtable_destroy(tracemalloc_filenames); @@ -1153,11 +1105,11 @@ frame_to_pyobject(frame_t *frame) static PyObject* traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) { - int i; - PyObject *frames, *frame; + PyObject *frames; if (intern_table != NULL) { - if (_Py_HASHTABLE_GET(intern_table, (const void *)traceback, frames)) { + frames = _Py_hashtable_get(intern_table, (const void *)traceback); + if (frames) { Py_INCREF(frames); return frames; } @@ -1167,8 +1119,8 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) if (frames == NULL) return NULL; - for (i=0; i < traceback->nframe; i++) { - frame = frame_to_pyobject(&traceback->frames[i]); + for (int i=0; i < traceback->nframe; i++) { + PyObject *frame = frame_to_pyobject(&traceback->frames[i]); if (frame == NULL) { Py_DECREF(frames); return NULL; @@ -1177,7 +1129,7 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) } if (intern_table != NULL) { - if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) { + if (_Py_hashtable_set(intern_table, traceback, frames) < 0) { Py_DECREF(frames); PyErr_NoMemory(); return NULL; @@ -1190,7 +1142,7 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) static PyObject* -trace_to_pyobject(unsigned int domain, trace_t *trace, +trace_to_pyobject(unsigned int domain, const trace_t *trace, _Py_hashtable_t *intern_tracebacks) { PyObject *trace_obj = NULL; @@ -1243,20 +1195,19 @@ typedef struct { static int tracemalloc_copy_trace(_Py_hashtable_t *traces, - _Py_hashtable_entry_t *entry, - void *traces2_raw) + const void *key, const void *value, + void *user_data) { - _Py_hashtable_t *traces2 = (_Py_hashtable_t *)traces2_raw; + _Py_hashtable_t *traces2 = (_Py_hashtable_t *)user_data; - trace_t *trace; - _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace); + trace_t *trace = (trace_t *)value; trace_t *trace2 = raw_malloc(sizeof(trace_t)); if (traces2 == NULL) { return -1; } *trace2 = *trace; - if (_Py_HASHTABLE_SET(traces2, entry->key, trace2) < 0) { + if (_Py_hashtable_set(traces2, key, trace2) < 0) { raw_free(trace2); return -1; } @@ -1285,17 +1236,16 @@ tracemalloc_copy_traces(_Py_hashtable_t *traces) static int tracemalloc_copy_domain(_Py_hashtable_t *domains, - _Py_hashtable_entry_t *entry, - void *domains2_raw) + const void *key, const void *value, + void *user_data) { - _Py_hashtable_t *domains2 = (_Py_hashtable_t *)domains2_raw; + _Py_hashtable_t *domains2 = (_Py_hashtable_t *)user_data; - unsigned int domain = (unsigned int)FROM_PTR(entry->key); - _Py_hashtable_t *traces; - _Py_HASHTABLE_ENTRY_READ_DATA(domains, entry, traces); + unsigned int domain = (unsigned int)FROM_PTR(key); + _Py_hashtable_t *traces = (_Py_hashtable_t *)value; _Py_hashtable_t *traces2 = tracemalloc_copy_traces(traces); - if (_Py_HASHTABLE_SET(domains2, TO_PTR(domain), traces2) < 0) { + if (_Py_hashtable_set(domains2, TO_PTR(domain), traces2) < 0) { _Py_hashtable_destroy(traces2); return -1; } @@ -1323,24 +1273,25 @@ tracemalloc_copy_domains(_Py_hashtable_t *domains) static int -tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry, +tracemalloc_get_traces_fill(_Py_hashtable_t *traces, + const void *key, const void *value, void *user_data) { get_traces_t *get_traces = user_data; - trace_t *trace; - PyObject *tracemalloc_obj; - int res; - _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace); + const trace_t *trace = (const trace_t *)value; - tracemalloc_obj = trace_to_pyobject(get_traces->domain, trace, get_traces->tracebacks); - if (tracemalloc_obj == NULL) + PyObject *tuple = trace_to_pyobject(get_traces->domain, trace, + get_traces->tracebacks); + if (tuple == NULL) { return 1; + } - res = PyList_Append(get_traces->list, tracemalloc_obj); - Py_DECREF(tracemalloc_obj); - if (res < 0) + int res = PyList_Append(get_traces->list, tuple); + Py_DECREF(tuple); + if (res < 0) { return 1; + } return 0; } @@ -1348,14 +1299,13 @@ tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entr static int tracemalloc_get_traces_domain(_Py_hashtable_t *domains, - _Py_hashtable_entry_t *entry, + const void *key, const void *value, void *user_data) { get_traces_t *get_traces = user_data; - unsigned int domain = (unsigned int)FROM_PTR(entry->key); - _Py_hashtable_t *traces; - _Py_HASHTABLE_ENTRY_READ_DATA(domains, entry, traces); + unsigned int domain = (unsigned int)FROM_PTR(key); + _Py_hashtable_t *traces = (_Py_hashtable_t *)value; get_traces->domain = domain; return _Py_hashtable_foreach(traces, @@ -1365,11 +1315,9 @@ tracemalloc_get_traces_domain(_Py_hashtable_t *domains, static void -tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks, - _Py_hashtable_entry_t *entry) +tracemalloc_pyobject_decref(void *value) { - PyObject *obj; - _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj); + PyObject *obj = (PyObject *)value; Py_DECREF(obj); } @@ -1404,10 +1352,9 @@ _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(PyObject *), - _Py_hashtable_hash_ptr, + get_traces.tracebacks = hashtable_new(_Py_hashtable_hash_ptr, _Py_hashtable_compare_direct, - tracemalloc_pyobject_decref_cb); + NULL, tracemalloc_pyobject_decref); if (get_traces.tracebacks == NULL) { goto no_memory; } @@ -1462,7 +1409,7 @@ _tracemalloc__get_traces_impl(PyObject *module) _Py_hashtable_destroy(get_traces.traces); } if (get_traces.domains != NULL) { - tracemalloc_destroy_domains(get_traces.domains); + _Py_hashtable_destroy(get_traces.domains); } return get_traces.list; @@ -1472,23 +1419,22 @@ _tracemalloc__get_traces_impl(PyObject *module) static traceback_t* tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr) { - trace_t *trace; - int found; if (!_Py_tracemalloc_config.tracing) return NULL; + trace_t *trace; TABLES_LOCK(); _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); if (traces) { - found = _Py_HASHTABLE_GET(traces, TO_PTR(ptr), trace); + trace = _Py_hashtable_get(traces, TO_PTR(ptr)); } else { - found = 0; + trace = NULL; } TABLES_UNLOCK(); - if (!found) { + if (!trace) { return NULL; } @@ -1634,12 +1580,10 @@ _tracemalloc_get_traceback_limit_impl(PyObject *module) static int tracemalloc_get_tracemalloc_memory_cb(_Py_hashtable_t *domains, - _Py_hashtable_entry_t *entry, + const void *key, const void *value, void *user_data) { - _Py_hashtable_t *traces; - _Py_HASHTABLE_ENTRY_READ_DATA(domains, entry, traces); - + const _Py_hashtable_t *traces = value; size_t *size = (size_t*)user_data; *size += _Py_hashtable_size(traces); return 0; @@ -1827,14 +1771,11 @@ _PyTraceMalloc_NewReference(PyObject *op) int res = -1; TABLES_LOCK(); - _Py_hashtable_entry_t* entry; - entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr); - if (entry != NULL) { + trace_t *trace = _Py_hashtable_get(tracemalloc_traces, TO_PTR(ptr)); + if (trace != NULL) { /* update the traceback of the memory block */ traceback_t *traceback = traceback_new(); if (traceback != NULL) { - trace_t *trace; - _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace); trace->traceback = traceback; res = 0; } diff --git a/Python/hashtable.c b/Python/hashtable.c index e7681fb1565198..dc4af3395181cd 100644 --- a/Python/hashtable.c +++ b/Python/hashtable.c @@ -58,22 +58,6 @@ ((_Py_hashtable_entry_t *)_Py_SLIST_HEAD(&(HT)->buckets[BUCKET])) #define ENTRY_NEXT(ENTRY) \ ((_Py_hashtable_entry_t *)_Py_SLIST_ITEM_NEXT(ENTRY)) -#define HASHTABLE_ITEM_SIZE(HT) \ - (sizeof(_Py_hashtable_entry_t) + (HT)->data_size) - -#define ENTRY_READ_PDATA(TABLE, ENTRY, DATA_SIZE, PDATA) \ - do { \ - assert((DATA_SIZE) == (TABLE)->data_size); \ - memcpy((PDATA), _Py_HASHTABLE_ENTRY_PDATA(ENTRY), \ - (DATA_SIZE)); \ - } while (0) - -#define ENTRY_WRITE_PDATA(TABLE, ENTRY, DATA_SIZE, PDATA) \ - do { \ - assert((DATA_SIZE) == (TABLE)->data_size); \ - memcpy((void *)_Py_HASHTABLE_ENTRY_PDATA(ENTRY), \ - (PDATA), (DATA_SIZE)); \ - } while (0) /* Forward declaration */ static void hashtable_rehash(_Py_hashtable_t *ht); @@ -133,7 +117,7 @@ round_size(size_t s) size_t -_Py_hashtable_size(_Py_hashtable_t *ht) +_Py_hashtable_size(const _Py_hashtable_t *ht) { size_t size; @@ -143,7 +127,7 @@ _Py_hashtable_size(_Py_hashtable_t *ht) size += ht->num_buckets * sizeof(_Py_hashtable_entry_t *); /* entries */ - size += ht->entries * HASHTABLE_ITEM_SIZE(ht); + size += ht->entries * sizeof(_Py_hashtable_entry_t); return size; } @@ -209,11 +193,9 @@ _Py_hashtable_get_entry_generic(_Py_hashtable_t *ht, const void *key) } -static int -_Py_hashtable_pop_entry(_Py_hashtable_t *ht, const void *key, - void *data, size_t data_size) +void* +_Py_hashtable_steal(_Py_hashtable_t *ht, const void *key) { - Py_uhash_t key_hash = ht->hash_func(key); size_t index = key_hash & (ht->num_buckets - 1); @@ -222,7 +204,7 @@ _Py_hashtable_pop_entry(_Py_hashtable_t *ht, const void *key, while (1) { if (entry == NULL) { // not found - return 0; + return NULL; } if (entry->key_hash == key_hash && ht->compare_func(key, entry->key)) { break; @@ -235,23 +217,21 @@ _Py_hashtable_pop_entry(_Py_hashtable_t *ht, const void *key, (_Py_slist_item_t *)entry); ht->entries--; - if (data != NULL) - ENTRY_READ_PDATA(ht, entry, data_size, data); + void *value = entry->value; ht->alloc.free(entry); - if ((float)ht->entries / (float)ht->num_buckets < HASHTABLE_LOW) + if ((float)ht->entries / (float)ht->num_buckets < HASHTABLE_LOW) { hashtable_rehash(ht); - return 1; + } + return value; } int -_Py_hashtable_set(_Py_hashtable_t *ht, const void *key, - size_t data_size, const void *data) +_Py_hashtable_set(_Py_hashtable_t *ht, const void *key, void *value) { _Py_hashtable_entry_t *entry; - 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 @@ -263,7 +243,7 @@ _Py_hashtable_set(_Py_hashtable_t *ht, const void *key, 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)); + entry = ht->alloc.malloc(sizeof(_Py_hashtable_entry_t)); if (entry == NULL) { /* memory allocation failed */ return -1; @@ -271,9 +251,7 @@ _Py_hashtable_set(_Py_hashtable_t *ht, const void *key, entry->key_hash = key_hash; entry->key = (void *)key; - if (data) { - ENTRY_WRITE_PDATA(ht, entry, data_size, data); - } + entry->value = value; _Py_slist_prepend(&ht->buckets[index], (_Py_slist_item_t*)entry); ht->entries++; @@ -284,17 +262,15 @@ _Py_hashtable_set(_Py_hashtable_t *ht, const void *key, } -int -_Py_hashtable_get_generic(_Py_hashtable_t *ht, const void *key, void *data) +void* +_Py_hashtable_get(_Py_hashtable_t *ht, const void *key) { - assert(data != NULL); _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; + return entry->value; } else { - return 0; + return NULL; } } @@ -323,44 +299,17 @@ _Py_hashtable_get_entry_ptr(_Py_hashtable_t *ht, const void *key) } -// Specialized for: -// hash_func == _Py_hashtable_hash_ptr -// compare_func == _Py_hashtable_compare_direct -int -_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, key); - if (entry != NULL) { - ENTRY_READ_PDATA(ht, entry, ht->data_size, data); - return 1; - } - else { - return 0; - } -} - - -int -_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, data, data_size); -} - - int _Py_hashtable_foreach(_Py_hashtable_t *ht, _Py_hashtable_foreach_func func, - void *arg) + void *user_data) { _Py_hashtable_entry_t *entry; size_t hv; 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(ht, entry->key, entry->value, user_data); if (res) return res; } @@ -414,11 +363,10 @@ hashtable_rehash(_Py_hashtable_t *ht) _Py_hashtable_t * -_Py_hashtable_new_full(size_t data_size, size_t init_size, - _Py_hashtable_hash_func hash_func, +_Py_hashtable_new_full(_Py_hashtable_hash_func hash_func, _Py_hashtable_compare_func compare_func, _Py_hashtable_destroy_func key_destroy_func, - _Py_hashtable_value_destroy_func value_destroy_func, + _Py_hashtable_destroy_func value_destroy_func, _Py_hashtable_allocator_t *allocator) { _Py_hashtable_t *ht; @@ -437,9 +385,8 @@ _Py_hashtable_new_full(size_t data_size, size_t init_size, if (ht == NULL) return ht; - ht->num_buckets = round_size(init_size); + ht->num_buckets = HASHTABLE_MIN_SIZE; ht->entries = 0; - ht->data_size = data_size; buckets_size = ht->num_buckets * sizeof(ht->buckets[0]); ht->buckets = alloc.malloc(buckets_size); @@ -449,7 +396,6 @@ _Py_hashtable_new_full(size_t data_size, size_t init_size, } memset(ht->buckets, 0, buckets_size); - ht->get_func = _Py_hashtable_get_generic; ht->get_entry_func = _Py_hashtable_get_entry_generic; ht->hash_func = hash_func; ht->compare_func = compare_func; @@ -459,7 +405,6 @@ _Py_hashtable_new_full(size_t data_size, size_t init_size, if (ht->hash_func == _Py_hashtable_hash_ptr && ht->compare_func == _Py_hashtable_compare_direct) { - ht->get_func = _Py_hashtable_get_ptr; ht->get_entry_func = _Py_hashtable_get_entry_ptr; } return ht; @@ -467,16 +412,27 @@ _Py_hashtable_new_full(size_t data_size, size_t init_size, _Py_hashtable_t * -_Py_hashtable_new(size_t data_size, - _Py_hashtable_hash_func hash_func, +_Py_hashtable_new(_Py_hashtable_hash_func hash_func, _Py_hashtable_compare_func compare_func) { - return _Py_hashtable_new_full(data_size, HASHTABLE_MIN_SIZE, - hash_func, compare_func, + return _Py_hashtable_new_full(hash_func, compare_func, NULL, NULL, NULL); } +static void +_Py_hashtable_destroy_entry(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry) +{ + if (ht->key_destroy_func) { + ht->key_destroy_func(entry->key); + } + if (ht->value_destroy_func) { + ht->value_destroy_func(entry->value); + } + ht->alloc.free(entry); +} + + void _Py_hashtable_clear(_Py_hashtable_t *ht) { @@ -486,7 +442,7 @@ _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); - ht->alloc.free(entry); + _Py_hashtable_destroy_entry(ht, entry); } _Py_slist_init(&ht->buckets[i]); } @@ -495,19 +451,6 @@ _Py_hashtable_clear(_Py_hashtable_t *ht) } -static void -_Py_hashtable_destroy_entry(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry) -{ - if (ht->key_destroy_func) { - ht->key_destroy_func(entry->key); - } - if (ht->value_destroy_func) { - ht->value_destroy_func(ht, entry); - } - ht->alloc.free(entry); -} - - void _Py_hashtable_destroy(_Py_hashtable_t *ht) { diff --git a/Python/marshal.c b/Python/marshal.c index 7c99c1ee13c0ee..b096ff89322209 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -302,10 +302,10 @@ 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, entry, w); + w = (int)(uintptr_t)entry->value; /* we don't store "long" indices in the dict */ assert(0 <= w && w <= 0x7fffffff); w_byte(TYPE_REF, p); @@ -320,7 +320,7 @@ w_ref(PyObject *v, char *flag, WFILE *p) } w = (int)s; Py_INCREF(v); - if (_Py_HASHTABLE_SET(p->hashtable, v, w) < 0) { + if (_Py_hashtable_set(p->hashtable, v, (void *)(uintptr_t)w) < 0) { Py_DECREF(v); goto err; } @@ -556,8 +556,7 @@ static int w_init_refs(WFILE *wf, int version) { if (version >= 3) { - wf->hashtable = _Py_hashtable_new_full(sizeof(int), 0, - _Py_hashtable_hash_ptr, + wf->hashtable = _Py_hashtable_new_full(_Py_hashtable_hash_ptr, _Py_hashtable_compare_direct, w_decref_entry, NULL, NULL); if (wf->hashtable == NULL) { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy