@@ -108,7 +108,6 @@ Py_uhash_t
108
108
_Py_hashtable_hash_ptr (struct _Py_hashtable_t * ht , const void * pkey )
109
109
{
110
110
void * key ;
111
-
112
111
_Py_HASHTABLE_READ_KEY (ht , pkey , key );
113
112
return (Py_uhash_t )_Py_HashPointer (key );
114
113
}
@@ -137,60 +136,6 @@ round_size(size_t s)
137
136
}
138
137
139
138
140
- _Py_hashtable_t *
141
- _Py_hashtable_new_full (size_t key_size , size_t data_size ,
142
- size_t init_size ,
143
- _Py_hashtable_hash_func hash_func ,
144
- _Py_hashtable_compare_func compare_func ,
145
- _Py_hashtable_allocator_t * allocator )
146
- {
147
- _Py_hashtable_t * ht ;
148
- size_t buckets_size ;
149
- _Py_hashtable_allocator_t alloc ;
150
-
151
- if (allocator == NULL ) {
152
- alloc .malloc = PyMem_RawMalloc ;
153
- alloc .free = PyMem_RawFree ;
154
- }
155
- else
156
- alloc = * allocator ;
157
-
158
- ht = (_Py_hashtable_t * )alloc .malloc (sizeof (_Py_hashtable_t ));
159
- if (ht == NULL )
160
- return ht ;
161
-
162
- ht -> num_buckets = round_size (init_size );
163
- ht -> entries = 0 ;
164
- ht -> key_size = key_size ;
165
- ht -> data_size = data_size ;
166
-
167
- buckets_size = ht -> num_buckets * sizeof (ht -> buckets [0 ]);
168
- ht -> buckets = alloc .malloc (buckets_size );
169
- if (ht -> buckets == NULL ) {
170
- alloc .free (ht );
171
- return NULL ;
172
- }
173
- memset (ht -> buckets , 0 , buckets_size );
174
-
175
- ht -> hash_func = hash_func ;
176
- ht -> compare_func = compare_func ;
177
- ht -> alloc = alloc ;
178
- return ht ;
179
- }
180
-
181
-
182
- _Py_hashtable_t *
183
- _Py_hashtable_new (size_t key_size , size_t data_size ,
184
- _Py_hashtable_hash_func hash_func ,
185
- _Py_hashtable_compare_func compare_func )
186
- {
187
- return _Py_hashtable_new_full (key_size , data_size ,
188
- HASHTABLE_MIN_SIZE ,
189
- hash_func , compare_func ,
190
- NULL );
191
- }
192
-
193
-
194
139
size_t
195
140
_Py_hashtable_size (_Py_hashtable_t * ht )
196
141
{
@@ -250,23 +195,20 @@ _Py_hashtable_print_stats(_Py_hashtable_t *ht)
250
195
251
196
252
197
_Py_hashtable_entry_t *
253
- _Py_hashtable_get_entry (_Py_hashtable_t * ht ,
254
- size_t key_size , const void * pkey )
198
+ _Py_hashtable_get_entry_generic (_Py_hashtable_t * ht , const void * pkey )
255
199
{
256
- Py_uhash_t key_hash ;
257
- size_t index ;
258
- _Py_hashtable_entry_t * entry ;
259
-
260
- assert (key_size == ht -> key_size );
261
-
262
- key_hash = ht -> hash_func (ht , pkey );
263
- index = key_hash & (ht -> num_buckets - 1 );
264
-
265
- for (entry = TABLE_HEAD (ht , index ); entry != NULL ; entry = ENTRY_NEXT (entry )) {
266
- if (entry -> key_hash == key_hash && ht -> compare_func (ht , pkey , entry ))
200
+ Py_uhash_t key_hash = ht -> hash_func (ht , pkey );
201
+ size_t index = key_hash & (ht -> num_buckets - 1 );
202
+ _Py_hashtable_entry_t * entry = entry = TABLE_HEAD (ht , index );
203
+ while (1 ) {
204
+ if (entry == NULL ) {
205
+ return NULL ;
206
+ }
207
+ if (entry -> key_hash == key_hash && ht -> compare_func (ht , pkey , entry )) {
267
208
break ;
209
+ }
210
+ entry = ENTRY_NEXT (entry );
268
211
}
269
-
270
212
return entry ;
271
213
}
272
214
@@ -323,7 +265,7 @@ _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey,
323
265
/* Don't write the assertion on a single line because it is interesting
324
266
to know the duplicated entry if the assertion failed. The entry can
325
267
be read using a debugger. */
326
- entry = _Py_hashtable_get_entry (ht , key_size , pkey );
268
+ entry = ht -> get_entry_func (ht , pkey );
327
269
assert (entry == NULL );
328
270
#endif
329
271
@@ -351,18 +293,62 @@ _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey,
351
293
352
294
353
295
int
354
- _Py_hashtable_get (_Py_hashtable_t * ht , size_t key_size ,const void * pkey ,
355
- size_t data_size , void * data )
296
+ _Py_hashtable_get_generic (_Py_hashtable_t * ht , const void * pkey , void * data )
356
297
{
357
- _Py_hashtable_entry_t * entry ;
358
-
359
298
assert (data != NULL );
299
+ _Py_hashtable_entry_t * entry = ht -> get_entry_func (ht , pkey );
300
+ if (entry != NULL ) {
301
+ ENTRY_READ_PDATA (ht , entry , ht -> data_size , data );
302
+ return 1 ;
303
+ }
304
+ else {
305
+ return 0 ;
306
+ }
307
+ }
360
308
361
- entry = _Py_hashtable_get_entry (ht , key_size , pkey );
362
- if (entry == NULL )
309
+
310
+ // Specialized for:
311
+ // key_size == sizeof(void*)
312
+ // hash_func == _Py_hashtable_hash_ptr
313
+ // compare_func == _Py_hashtable_compare_direct
314
+ _Py_hashtable_entry_t *
315
+ _Py_hashtable_get_entry_ptr (_Py_hashtable_t * ht , const void * pkey )
316
+ {
317
+ Py_uhash_t key_hash = _Py_hashtable_hash_ptr (ht , pkey );
318
+ size_t index = key_hash & (ht -> num_buckets - 1 );
319
+ _Py_hashtable_entry_t * entry = entry = TABLE_HEAD (ht , index );
320
+ while (1 ) {
321
+ if (entry == NULL ) {
322
+ return NULL ;
323
+ }
324
+ if (entry -> key_hash == key_hash ) {
325
+ const void * pkey2 = _Py_HASHTABLE_ENTRY_PKEY (entry );
326
+ if (memcmp (pkey , pkey2 , sizeof (void * )) == 0 ) {
327
+ break ;
328
+ }
329
+ }
330
+ entry = ENTRY_NEXT (entry );
331
+ }
332
+ return entry ;
333
+ }
334
+
335
+
336
+ // Specialized for:
337
+ // key_size == sizeof(void*)
338
+ // hash_func == _Py_hashtable_hash_ptr
339
+ // compare_func == _Py_hashtable_compare_direct
340
+ int
341
+ _Py_hashtable_get_ptr (_Py_hashtable_t * ht , const void * pkey , void * data )
342
+ {
343
+ assert (data != NULL );
344
+ _Py_hashtable_entry_t * entry = _Py_hashtable_get_entry_ptr (ht , pkey );
345
+ if (entry != NULL ) {
346
+ ENTRY_READ_PDATA (ht , entry , ht -> data_size , data );
347
+ return 1 ;
348
+ }
349
+ else {
363
350
return 0 ;
364
- ENTRY_READ_PDATA (ht , entry , data_size , data );
365
- return 1 ;
351
+ }
366
352
}
367
353
368
354
@@ -453,6 +439,70 @@ hashtable_rehash(_Py_hashtable_t *ht)
453
439
}
454
440
455
441
442
+ _Py_hashtable_t *
443
+ _Py_hashtable_new_full (size_t key_size , size_t data_size ,
444
+ size_t init_size ,
445
+ _Py_hashtable_hash_func hash_func ,
446
+ _Py_hashtable_compare_func compare_func ,
447
+ _Py_hashtable_allocator_t * allocator )
448
+ {
449
+ _Py_hashtable_t * ht ;
450
+ size_t buckets_size ;
451
+ _Py_hashtable_allocator_t alloc ;
452
+
453
+ if (allocator == NULL ) {
454
+ alloc .malloc = PyMem_Malloc ;
455
+ alloc .free = PyMem_Free ;
456
+ }
457
+ else {
458
+ alloc = * allocator ;
459
+ }
460
+
461
+ ht = (_Py_hashtable_t * )alloc .malloc (sizeof (_Py_hashtable_t ));
462
+ if (ht == NULL )
463
+ return ht ;
464
+
465
+ ht -> num_buckets = round_size (init_size );
466
+ ht -> entries = 0 ;
467
+ ht -> key_size = key_size ;
468
+ ht -> data_size = data_size ;
469
+
470
+ buckets_size = ht -> num_buckets * sizeof (ht -> buckets [0 ]);
471
+ ht -> buckets = alloc .malloc (buckets_size );
472
+ if (ht -> buckets == NULL ) {
473
+ alloc .free (ht );
474
+ return NULL ;
475
+ }
476
+ memset (ht -> buckets , 0 , buckets_size );
477
+
478
+ ht -> get_func = _Py_hashtable_get_generic ;
479
+ ht -> get_entry_func = _Py_hashtable_get_entry_generic ;
480
+ ht -> hash_func = hash_func ;
481
+ ht -> compare_func = compare_func ;
482
+ ht -> alloc = alloc ;
483
+ if (ht -> key_size == sizeof (void * )
484
+ && ht -> hash_func == _Py_hashtable_hash_ptr
485
+ && ht -> compare_func == _Py_hashtable_compare_direct )
486
+ {
487
+ ht -> get_func = _Py_hashtable_get_ptr ;
488
+ ht -> get_entry_func = _Py_hashtable_get_entry_ptr ;
489
+ }
490
+ return ht ;
491
+ }
492
+
493
+
494
+ _Py_hashtable_t *
495
+ _Py_hashtable_new (size_t key_size , size_t data_size ,
496
+ _Py_hashtable_hash_func hash_func ,
497
+ _Py_hashtable_compare_func compare_func )
498
+ {
499
+ return _Py_hashtable_new_full (key_size , data_size ,
500
+ HASHTABLE_MIN_SIZE ,
501
+ hash_func , compare_func ,
502
+ NULL );
503
+ }
504
+
505
+
456
506
void
457
507
_Py_hashtable_clear (_Py_hashtable_t * ht )
458
508
{
0 commit comments