diff -r 9d2c4d887c19 Objects/setobject.c --- a/Objects/setobject.c Tue May 12 14:28:08 2015 -0400 +++ b/Objects/setobject.c Tue May 12 22:52:52 2015 +0300 @@ -557,7 +557,7 @@ set_merge(PySetObject *so, PyObject *oth other = (PySetObject*)otherset; if (other == so || other->used == 0) - /* a.update(a) or a.update({}); nothing to do */ + /* a.update(a) or a.update(set()); nothing to do */ return 0; /* Do one big resize at the start, rather than * incrementally resizing as we insert new keys. Expect @@ -567,16 +567,46 @@ set_merge(PySetObject *so, PyObject *oth if (set_table_resize(so, (so->used + other->used)*2) != 0) return -1; } - for (i = 0; i <= other->mask; i++) { - entry = &other->table[i]; - key = entry->key; - 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 (so->fill != 0) { + for (i = 0; i <= other->mask; i++) { + entry = &other->table[i]; + key = entry->key; + hash = entry->hash; + if (key != NULL && key != dummy) { + Py_INCREF(key); + if (set_insert_key(so, key, hash) == -1) { + Py_DECREF(key); + return -1; + } + } + } + } + else if (other->fill == other->used && so->mask == other->mask) { + /* If no dummies, we can just copy entries at the same indices. */ + for (i = 0; i <= other->mask; i++) { + entry = &other->table[i]; + key = entry->key; + hash = entry->hash; + if (key != NULL && key != dummy) { + Py_INCREF(key); + entry = &so->table[i]; + assert(entry->key == NULL); + entry->key = key; + entry->hash = hash; + so->used++; + so->fill++; + } + } + } + else { + /* If the table is clean, we can use fast set_insert_clean(). */ + for (i = 0; i <= other->mask; i++) { + entry = &other->table[i]; + key = entry->key; + hash = entry->hash; + if (key != NULL && key != dummy) { + Py_INCREF(key); + set_insert_clean(so, key, hash); } } }