diff -r 0893b9ee44ea Objects/setobject.c --- a/Objects/setobject.c Tue Jan 20 17:21:41 2015 -0800 +++ b/Objects/setobject.c Wed Jan 21 15:16:06 2015 +0200 @@ -49,6 +49,32 @@ static PyObject _dummy_struct; #define PERTURB_SHIFT 5 static setentry * +set_find_free_slot(PySetObject *so, Py_hash_t hash) +{ + setentry *table = so->table; + setentry *entry; + size_t perturb = hash; + size_t mask = so->mask; + size_t i = (size_t)hash; /* Unsigned for defined overflow behavior. */ + size_t j; + + while (1) { + entry = &table[i & mask]; + if (entry->key == NULL || entry->key == dummy) + return entry; + + for (j = 1 ; j <= LINEAR_PROBES ; j++) { + entry = &table[(i + j) & mask]; + if (entry->key == NULL || entry->key == dummy) + return entry; + } + + perturb >>= PERTURB_SHIFT; + i = i * 5 + 1 + perturb; + } +} + +static setentry * set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) { setentry *table = so->table; @@ -593,6 +619,7 @@ set_merge(PySetObject *so, PyObject *oth Py_hash_t hash; Py_ssize_t i; setentry *entry; + int clear; assert (PyAnySet_Check(so)); assert (PyAnySet_Check(otherset)); @@ -601,6 +628,7 @@ set_merge(PySetObject *so, PyObject *oth if (other == so || other->used == 0) /* a.update(a) or a.update({}); nothing to do */ return 0; + clear = so->used == 0; /* Do one big resize at the start, rather than * incrementally resizing as we insert new keys. Expect * that there will be no (or few) overlapping keys. @@ -615,10 +643,23 @@ set_merge(PySetObject *so, PyObject *oth hash = entry->hash; if (key != NULL && key != dummy) { - Py_INCREF(key); - if (set_insert_key(so, key, hash) == -1) { - Py_DECREF(key); - return -1; + if (clear) { + assert(!(entry->key == NULL || entry->key == dummy)); + entry = set_find_free_slot(so, hash); + assert(entry->key == NULL || entry->key == dummy); + if (entry->key == NULL) + so->fill++; + Py_INCREF(key); + entry->key = key; + entry->hash = hash; + so->used++; + } + else { + Py_INCREF(key); + if (set_insert_key(so, key, hash) == -1) { + Py_DECREF(key); + return -1; + } } } }