Skip to content

Commit f9b3b58

Browse files
authored
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 *".
1 parent 9e2ca17 commit f9b3b58

File tree

4 files changed

+120
-188
lines changed

4 files changed

+120
-188
lines changed

Include/internal/pycore_hashtable.h

Lines changed: 21 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -30,32 +30,13 @@ typedef struct {
3030
_Py_slist_item_t _Py_slist_item;
3131

3232
Py_uhash_t key_hash;
33-
34-
/* key (key_size bytes) and then data (data_size bytes) follows */
33+
void *key;
34+
/* data (data_size bytes) follows */
3535
} _Py_hashtable_entry_t;
3636

37-
#define _Py_HASHTABLE_ENTRY_PKEY(ENTRY) \
38-
((const void *)((char *)(ENTRY) \
39-
+ sizeof(_Py_hashtable_entry_t)))
40-
4137
#define _Py_HASHTABLE_ENTRY_PDATA(TABLE, ENTRY) \
4238
((const void *)((char *)(ENTRY) \
43-
+ sizeof(_Py_hashtable_entry_t) \
44-
+ (TABLE)->key_size))
45-
46-
/* Get a key value from pkey: use memcpy() rather than a pointer dereference
47-
to avoid memory alignment issues. */
48-
#define _Py_HASHTABLE_READ_KEY(TABLE, PKEY, DST_KEY) \
49-
do { \
50-
assert(sizeof(DST_KEY) == (TABLE)->key_size); \
51-
memcpy(&(DST_KEY), (PKEY), sizeof(DST_KEY)); \
52-
} while (0)
53-
54-
#define _Py_HASHTABLE_ENTRY_READ_KEY(TABLE, ENTRY, KEY) \
55-
do { \
56-
assert(sizeof(KEY) == (TABLE)->key_size); \
57-
memcpy(&(KEY), _Py_HASHTABLE_ENTRY_PKEY(ENTRY), sizeof(KEY)); \
58-
} while (0)
39+
+ sizeof(_Py_hashtable_entry_t)))
5940

6041
#define _Py_HASHTABLE_ENTRY_READ_DATA(TABLE, ENTRY, DATA) \
6142
do { \
@@ -78,15 +59,12 @@ typedef struct {
7859
struct _Py_hashtable_t;
7960
typedef struct _Py_hashtable_t _Py_hashtable_t;
8061

81-
typedef Py_uhash_t (*_Py_hashtable_hash_func) (_Py_hashtable_t *ht,
82-
const void *pkey);
83-
typedef int (*_Py_hashtable_compare_func) (_Py_hashtable_t *ht,
84-
const void *pkey,
85-
const _Py_hashtable_entry_t *he);
62+
typedef Py_uhash_t (*_Py_hashtable_hash_func) (const void *key);
63+
typedef int (*_Py_hashtable_compare_func) (const void *key1, const void *key2);
8664
typedef _Py_hashtable_entry_t* (*_Py_hashtable_get_entry_func)(_Py_hashtable_t *ht,
87-
const void *pkey);
65+
const void *key);
8866
typedef int (*_Py_hashtable_get_func) (_Py_hashtable_t *ht,
89-
const void *pkey, void *data);
67+
const void *key, void *data);
9068

9169
typedef struct {
9270
/* allocate a memory block */
@@ -102,7 +80,6 @@ struct _Py_hashtable_t {
10280
size_t num_buckets;
10381
size_t entries; /* Total number of entries in the table. */
10482
_Py_slist_t *buckets;
105-
size_t key_size;
10683
size_t data_size;
10784

10885
_Py_hashtable_get_func get_func;
@@ -113,24 +90,19 @@ struct _Py_hashtable_t {
11390
};
11491

11592
/* hash a pointer (void*) */
116-
PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr(
117-
struct _Py_hashtable_t *ht,
118-
const void *pkey);
93+
PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr(const void *key);
11994

12095
/* comparison using memcmp() */
12196
PyAPI_FUNC(int) _Py_hashtable_compare_direct(
122-
_Py_hashtable_t *ht,
123-
const void *pkey,
124-
const _Py_hashtable_entry_t *entry);
97+
const void *key1,
98+
const void *key2);
12599

126100
PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new(
127-
size_t key_size,
128101
size_t data_size,
129102
_Py_hashtable_hash_func hash_func,
130103
_Py_hashtable_compare_func compare_func);
131104

132105
PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new_full(
133-
size_t key_size,
134106
size_t data_size,
135107
size_t init_size,
136108
_Py_hashtable_hash_func hash_func,
@@ -165,16 +137,15 @@ PyAPI_FUNC(size_t) _Py_hashtable_size(_Py_hashtable_t *ht);
165137
but use _Py_HASHTABLE_SET() and _Py_HASHTABLE_SET_NODATA() macros */
166138
PyAPI_FUNC(int) _Py_hashtable_set(
167139
_Py_hashtable_t *ht,
168-
size_t key_size,
169-
const void *pkey,
140+
const void *key,
170141
size_t data_size,
171142
const void *data);
172143

173144
#define _Py_HASHTABLE_SET(TABLE, KEY, DATA) \
174-
_Py_hashtable_set(TABLE, sizeof(KEY), &(KEY), sizeof(DATA), &(DATA))
145+
_Py_hashtable_set(TABLE, (KEY), sizeof(DATA), &(DATA))
175146

176147
#define _Py_HASHTABLE_SET_NODATA(TABLE, KEY) \
177-
_Py_hashtable_set(TABLE, sizeof(KEY), &(KEY), 0, NULL)
148+
_Py_hashtable_set(TABLE, (KEY), 0, NULL)
178149

179150

180151
/* Get an entry.
@@ -183,43 +154,40 @@ PyAPI_FUNC(int) _Py_hashtable_set(
183154
Don't call directly this function, but use _Py_HASHTABLE_GET_ENTRY()
184155
macro */
185156
static inline _Py_hashtable_entry_t *
186-
_Py_hashtable_get_entry(_Py_hashtable_t *ht, size_t key_size, const void *pkey)
157+
_Py_hashtable_get_entry(_Py_hashtable_t *ht, const void *key)
187158
{
188-
assert(key_size == ht->key_size);
189-
return ht->get_entry_func(ht, pkey);
159+
return ht->get_entry_func(ht, key);
190160
}
191161

192162
#define _Py_HASHTABLE_GET_ENTRY(TABLE, KEY) \
193-
_Py_hashtable_get_entry(TABLE, sizeof(KEY), &(KEY))
163+
_Py_hashtable_get_entry(TABLE, (const void *)(KEY))
194164

195165

196166
/* Get data from an entry. Copy entry data into data and return 1 if the entry
197167
exists, return 0 if the entry does not exist.
198168
199169
Don't call directly this function, but use _Py_HASHTABLE_GET() macro */
200170
static inline int
201-
_Py_hashtable_get(_Py_hashtable_t *ht, size_t key_size, const void *pkey,
171+
_Py_hashtable_get(_Py_hashtable_t *ht, const void *key,
202172
size_t data_size, void *data)
203173
{
204-
assert(key_size == ht->key_size);
205174
assert(data_size == ht->data_size);
206-
return ht->get_func(ht, pkey, data);
175+
return ht->get_func(ht, key, data);
207176
}
208177

209178
#define _Py_HASHTABLE_GET(TABLE, KEY, DATA) \
210-
_Py_hashtable_get(TABLE, sizeof(KEY), &(KEY), sizeof(DATA), &(DATA))
179+
_Py_hashtable_get(TABLE, (KEY), sizeof(DATA), &(DATA))
211180

212181

213182
/* Don't call directly this function, but use _Py_HASHTABLE_POP() macro */
214183
PyAPI_FUNC(int) _Py_hashtable_pop(
215184
_Py_hashtable_t *ht,
216-
size_t key_size,
217-
const void *pkey,
185+
const void *key,
218186
size_t data_size,
219187
void *data);
220188

221189
#define _Py_HASHTABLE_POP(TABLE, KEY, DATA) \
222-
_Py_hashtable_pop(TABLE, sizeof(KEY), &(KEY), sizeof(DATA), &(DATA))
190+
_Py_hashtable_pop(TABLE, (KEY), sizeof(DATA), &(DATA))
223191

224192

225193
#ifdef __cplusplus

0 commit comments

Comments
 (0)