diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -25,17 +25,17 @@ Unlike the dictionary implementation, the lookkey functions can return NULL if the rich comparison returns an error. + + Another difference from the dictionary implementation is that the lookkey + functions can never return a dummy entry. The means that dummy entries do + not get reused. The benefit is that the code for lookkey, insert, discard, + and contains is simplified. */ #include "Python.h" #include "structmember.h" #include "stringlib/eq.h" -/* Object used as dummy key to fill deleted entries */ -static PyObject _dummy_struct; - -#define dummy (&_dummy_struct) - /* ======================================================================== */ /* ======= Begin logic for probing the hash table ========================= */ @@ -48,11 +48,14 @@ /* This must be >= 1 */ #define PERTURB_SHIFT 5 +/* Object used as dummy key to fill deleted entries */ +static PyObject _dummy_struct; +#define dummy (&_dummy_struct) + static setentry * set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *table = so->table; - setentry *freeslot = NULL; setentry *entry; size_t perturb = hash; size_t mask = so->mask; @@ -79,13 +82,11 @@ if (cmp > 0) /* likely */ return entry; } - if (entry->key == dummy && freeslot == NULL) - freeslot = entry; for (j = 1 ; j <= LINEAR_PROBES ; j++) { entry = &table[(i + j) & mask]; if (entry->key == NULL) - goto found_null; + return entry; if (entry->hash == hash && entry->key != dummy) { PyObject *startkey = entry->key; if (startkey == key) @@ -100,8 +101,6 @@ if (cmp > 0) return entry; } - if (entry->key == dummy && freeslot == NULL) - freeslot = entry; } perturb >>= PERTURB_SHIFT; @@ -109,10 +108,9 @@ entry = &table[i & mask]; if (entry->key == NULL) - goto found_null; + return entry; } - found_null: - return freeslot == NULL ? entry : freeslot; + assert(0); } /* @@ -124,7 +122,6 @@ set_lookkey_unicode(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *table = so->table; - setentry *freeslot = NULL; setentry *entry; size_t perturb = hash; size_t mask = so->mask; @@ -150,20 +147,16 @@ || (entry->key != dummy /* unlikely */ && unicode_eq(entry->key, key)))) /* likely */ return entry; - if (entry->key == dummy && freeslot == NULL) - freeslot = entry; for (j = 1 ; j <= LINEAR_PROBES ; j++) { entry = &table[(i + j) & mask]; if (entry->key == NULL) - goto found_null; + return entry; if (entry->hash == hash && (entry->key == key || (entry->key != dummy /* unlikely */ && unicode_eq(entry->key, key)))) /* likely */ return entry; - if (entry->key == dummy && freeslot == NULL) - freeslot = entry; } perturb >>= PERTURB_SHIFT; @@ -171,10 +164,9 @@ entry = &table[i & mask]; if (entry->key == NULL) - goto found_null; + return entry; } - found_null: - return freeslot == NULL ? entry : freeslot; + assert(0); } /* @@ -229,17 +221,13 @@ entry = so->lookup(so, key, hash); if (entry == NULL) return -1; + assert(entry->key != dummy); if (entry->key == NULL) { /* UNUSED */ entry->key = key; entry->hash = hash; so->fill++; so->used++; - } else if (entry->key == dummy) { - /* DUMMY */ - entry->key = key; - entry->hash = hash; - so->used++; } else { /* ACTIVE */ Py_DECREF(key); @@ -388,7 +376,8 @@ entry = (so->lookup)(so, oldentry->key, oldentry->hash); if (entry == NULL) return -1; - if (entry->key == NULL || entry->key == dummy) + assert(entry->key != dummy); + if (entry->key == NULL) return DISCARD_NOTFOUND; old_key = entry->key; entry->key = dummy; @@ -635,7 +624,8 @@ if (lu_entry == NULL) return -1; key = lu_entry->key; - return key != NULL && key != dummy; + assert(key != dummy); + return key != NULL; } static int