Index: Objects/setobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/setobject.c,v
retrieving revision 1.56
diff -C2 -r1.56 setobject.c
*** Objects/setobject.c 26 Aug 2005 06:42:30 -0000 1.56
--- Objects/setobject.c 3 Sep 2005 02:37:12 -0000
***************
*** 211,214 ****
--- 211,410 ----
Eats a reference to key.
*/
+
+ /* */
+ #define BRENT 1
+
+ static void
+ set_lookup_insert_key(PySetObject *so, PyObject *key, register long hash)
+ {
+ register int i;
+ register unsigned int perturb;
+ register setentry *freeslot;
+ register unsigned int mask = so->mask;
+ setentry *table = so->table;
+ register setentry *entry;
+ register int restore_error;
+ register int checked_error;
+ register int cmp;
+ PyObject *err_type, *err_value, *err_tb;
+ PyObject *startkey;
+
+ #if BRENT
+ /* Brent's variation */
+ register int len, alt_len, freeslot_len;
+ register int j, k, alt;
+ register unsigned int alt_perturb;
+ register setentry *alt_entry, *opt_entry, *opt_alt_entry;
+ #endif
+
+ i = hash & mask;
+ entry = &table[i];
+ restore_error = checked_error = 0;
+ #if BRENT
+ len = 0;
+ #endif
+ if (entry->key == NULL)
+ goto NotFound;
+ if (entry->key == key)
+ goto Found;
+
+ if (entry->key == dummy) {
+ freeslot = entry;
+ #if BRENT
+ freeslot_len = len;
+ #endif
+ }
+ else {
+ if (entry->hash == hash) {
+ /* error can't have been checked yet */
+ checked_error = 1;
+ if (_PyErr_OCCURRED()) {
+ restore_error = 1;
+ PyErr_Fetch(&err_type, &err_value, &err_tb);
+ }
+ startkey = entry->key;
+ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
+ if (cmp < 0)
+ PyErr_Clear();
+ if (table == so->table && entry->key == startkey) {
+ if (cmp > 0)
+ goto Found;
+ }
+ else {
+ /* The compare did major nasty stuff to the
+ * set: start over.
+ */
+ set_lookup_insert_key(so, key, hash);
+ goto Done;
+ }
+ }
+ #if BRENT
+ freeslot_len = 0;
+ #endif
+ freeslot = NULL;
+ }
+
+ /* In the loop, key == dummy is by far (factor of 100s) the
+ least likely outcome, so test for that last. */
+ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
+ #if BRENT
+ len++;
+ #endif
+ i = (i << 2) + i + perturb + 1;
+ entry = &table[i & mask];
+ if (entry->key == NULL) {
+ if (freeslot != NULL) {
+ #if BRENT
+ len = freeslot_len;
+ #endif
+ entry = freeslot;
+ }
+ goto NotFound;
+ }
+ if (entry->key == key)
+ goto Found;
+ if (entry->hash == hash && entry->key != dummy) {
+ if (!checked_error) {
+ checked_error = 1;
+ if (_PyErr_OCCURRED()) {
+ restore_error = 1;
+ PyErr_Fetch(&err_type, &err_value,
+ &err_tb);
+ }
+ }
+ startkey = entry->key;
+ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
+ if (cmp < 0)
+ PyErr_Clear();
+ if (table == so->table && entry->key == startkey) {
+ if (cmp > 0)
+ goto Found;
+ }
+ else {
+ /* The compare did major nasty stuff to the
+ * set: start over.
+ */
+ set_lookup_insert_key(so, key, hash);
+ goto Done;
+ }
+ }
+ else if (entry->key == dummy && freeslot == NULL) {
+ #if BRENT
+ freeslot_len = len;
+ #endif
+ freeslot = entry;
+ }
+ }
+
+ Found:
+ /* ACTIVE */
+ Py_DECREF(key);
+ goto Done;
+ NotFound:
+ #if BRENT
+ if (len >= 2) {
+ alt_len = len;
+ opt_entry = opt_alt_entry = entry;
+ /* First slot in main branch */
+ /* Traverse main branch */
+ i = hash & mask;
+ perturb = hash;
+ for (j = 0; j < alt_len; j++, perturb >>= PERTURB_SHIFT) {
+ entry = &table[i & mask];
+ i = (i << 2) + i + perturb + 1;
+ assert(entry->key != NULL && entry->key != dummy);
+ /* Traverse alternate branch */
+ alt_perturb = entry->hash;
+ alt = entry->hash & mask;
+ for (k = 0; k < alt_len; k++, alt_perturb >>= PERTURB_SHIFT) {
+ alt_entry = &table[alt & mask];
+ alt = (alt << 2) + alt + alt_perturb + 1;
+ if (alt_entry->key == NULL || alt_entry->key == dummy) {
+ alt_len = k;
+ opt_entry = entry;
+ opt_alt_entry = alt_entry;
+ break;
+ }
+ }
+ }
+ /* An alternate was found ? */
+ if (opt_entry != opt_alt_entry) {
+ if (opt_alt_entry->key != NULL) {
+ /* Alternate was DUMMY */
+ so->used++;
+ Py_DECREF(dummy);
+ }
+ else {
+ /* Alternate was UNUSED */
+ so->used++;
+ so->fill++;
+ }
+ opt_alt_entry->key = opt_entry->key;
+ opt_alt_entry->hash = opt_entry->hash;
+ opt_entry->key = key;
+ opt_entry->hash = hash;
+ goto Done;
+ }
+ entry = opt_entry;
+ }
+ #endif
+ if (entry->key != NULL) {
+ /* DUMMY */
+ so->used++;
+ Py_DECREF(dummy);
+ }
+ else {
+ /* UNUSED */
+ so->fill++;
+ so->used++;
+ }
+ entry->key = key;
+ entry->hash = hash;
+ Done:
+ if (restore_error)
+ PyErr_Restore(err_type, err_value, err_tb);
+ }
+ /* */
+
static void
set_insert_key(register PySetObject *so, PyObject *key, long hash)
***************
*** 218,221 ****
--- 414,423 ----
assert(so->lookup != NULL);
+ /* */
+ if (so->lookup == set_lookkey) {
+ set_lookup_insert_key(so, key, hash);
+ return;
+ }
+ /* */
entry = so->lookup(so, key, hash);
if (entry->key == NULL) {
***************
*** 237,240 ****
--- 439,443 ----
}
+
/*
Restructure the table by allocating a new table and reinserting all