mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Improve code clarity for the set lookup logic (GH-20028)
This commit is contained in:
parent
2fbc57af85
commit
2cc9b8486d
1 changed files with 55 additions and 125 deletions
|
@ -57,77 +57,43 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
|
||||||
{
|
{
|
||||||
setentry *table;
|
setentry *table;
|
||||||
setentry *entry;
|
setentry *entry;
|
||||||
size_t perturb;
|
size_t perturb = hash;
|
||||||
size_t mask = so->mask;
|
size_t mask = so->mask;
|
||||||
size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
|
size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
|
||||||
size_t j;
|
int probes;
|
||||||
int cmp;
|
int cmp;
|
||||||
|
|
||||||
entry = &so->table[i];
|
|
||||||
if (entry->key == NULL)
|
|
||||||
return entry;
|
|
||||||
|
|
||||||
perturb = hash;
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (entry->hash == hash) {
|
entry = &so->table[i];
|
||||||
PyObject *startkey = entry->key;
|
probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
|
||||||
/* startkey cannot be a dummy because the dummy hash field is -1 */
|
do {
|
||||||
assert(startkey != dummy);
|
if (entry->hash == 0 && entry->key == NULL)
|
||||||
if (startkey == key)
|
|
||||||
return entry;
|
return entry;
|
||||||
if (PyUnicode_CheckExact(startkey)
|
if (entry->hash == hash) {
|
||||||
&& PyUnicode_CheckExact(key)
|
PyObject *startkey = entry->key;
|
||||||
&& _PyUnicode_EQ(startkey, key))
|
assert(startkey != dummy);
|
||||||
return entry;
|
if (startkey == key)
|
||||||
table = so->table;
|
|
||||||
Py_INCREF(startkey);
|
|
||||||
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
|
||||||
Py_DECREF(startkey);
|
|
||||||
if (cmp < 0) /* unlikely */
|
|
||||||
return NULL;
|
|
||||||
if (table != so->table || entry->key != startkey) /* unlikely */
|
|
||||||
return set_lookkey(so, key, hash);
|
|
||||||
if (cmp > 0) /* likely */
|
|
||||||
return entry;
|
|
||||||
mask = so->mask; /* help avoid a register spill */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i + LINEAR_PROBES <= mask) {
|
|
||||||
for (j = 0 ; j < LINEAR_PROBES ; j++) {
|
|
||||||
entry++;
|
|
||||||
if (entry->hash == 0 && entry->key == NULL)
|
|
||||||
return entry;
|
return entry;
|
||||||
if (entry->hash == hash) {
|
if (PyUnicode_CheckExact(startkey)
|
||||||
PyObject *startkey = entry->key;
|
&& PyUnicode_CheckExact(key)
|
||||||
assert(startkey != dummy);
|
&& _PyUnicode_EQ(startkey, key))
|
||||||
if (startkey == key)
|
return entry;
|
||||||
return entry;
|
table = so->table;
|
||||||
if (PyUnicode_CheckExact(startkey)
|
Py_INCREF(startkey);
|
||||||
&& PyUnicode_CheckExact(key)
|
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
||||||
&& _PyUnicode_EQ(startkey, key))
|
Py_DECREF(startkey);
|
||||||
return entry;
|
if (cmp < 0)
|
||||||
table = so->table;
|
return NULL;
|
||||||
Py_INCREF(startkey);
|
if (table != so->table || entry->key != startkey)
|
||||||
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
return set_lookkey(so, key, hash);
|
||||||
Py_DECREF(startkey);
|
if (cmp > 0)
|
||||||
if (cmp < 0)
|
return entry;
|
||||||
return NULL;
|
mask = so->mask;
|
||||||
if (table != so->table || entry->key != startkey)
|
|
||||||
return set_lookkey(so, key, hash);
|
|
||||||
if (cmp > 0)
|
|
||||||
return entry;
|
|
||||||
mask = so->mask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
entry++;
|
||||||
|
} while (probes--);
|
||||||
perturb >>= PERTURB_SHIFT;
|
perturb >>= PERTURB_SHIFT;
|
||||||
i = (i * 5 + 1 + perturb) & mask;
|
i = (i * 5 + 1 + perturb) & mask;
|
||||||
|
|
||||||
entry = &so->table[i];
|
|
||||||
if (entry->key == NULL)
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +107,7 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
|
||||||
size_t perturb;
|
size_t perturb;
|
||||||
size_t mask;
|
size_t mask;
|
||||||
size_t i; /* Unsigned for defined overflow behavior */
|
size_t i; /* Unsigned for defined overflow behavior */
|
||||||
size_t j;
|
int probes;
|
||||||
int cmp;
|
int cmp;
|
||||||
|
|
||||||
/* Pre-increment is necessary to prevent arbitrary code in the rich
|
/* Pre-increment is necessary to prevent arbitrary code in the rich
|
||||||
|
@ -152,75 +118,39 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
|
||||||
|
|
||||||
mask = so->mask;
|
mask = so->mask;
|
||||||
i = (size_t)hash & mask;
|
i = (size_t)hash & mask;
|
||||||
|
|
||||||
entry = &so->table[i];
|
|
||||||
if (entry->key == NULL)
|
|
||||||
goto found_unused;
|
|
||||||
|
|
||||||
perturb = hash;
|
perturb = hash;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (entry->hash == hash) {
|
entry = &so->table[i];
|
||||||
PyObject *startkey = entry->key;
|
probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
|
||||||
/* startkey cannot be a dummy because the dummy hash field is -1 */
|
do {
|
||||||
assert(startkey != dummy);
|
if (entry->hash == 0 && entry->key == NULL)
|
||||||
if (startkey == key)
|
goto found_unused;
|
||||||
goto found_active;
|
if (entry->hash == hash) {
|
||||||
if (PyUnicode_CheckExact(startkey)
|
PyObject *startkey = entry->key;
|
||||||
&& PyUnicode_CheckExact(key)
|
assert(startkey != dummy);
|
||||||
&& _PyUnicode_EQ(startkey, key))
|
if (startkey == key)
|
||||||
goto found_active;
|
goto found_active;
|
||||||
table = so->table;
|
if (PyUnicode_CheckExact(startkey)
|
||||||
Py_INCREF(startkey);
|
&& PyUnicode_CheckExact(key)
|
||||||
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
&& _PyUnicode_EQ(startkey, key))
|
||||||
Py_DECREF(startkey);
|
goto found_active;
|
||||||
if (cmp > 0) /* likely */
|
table = so->table;
|
||||||
goto found_active;
|
Py_INCREF(startkey);
|
||||||
if (cmp < 0)
|
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
||||||
goto comparison_error;
|
Py_DECREF(startkey);
|
||||||
/* Continuing the search from the current entry only makes
|
if (cmp > 0)
|
||||||
sense if the table and entry are unchanged; otherwise,
|
goto found_active;
|
||||||
we have to restart from the beginning */
|
if (cmp < 0)
|
||||||
if (table != so->table || entry->key != startkey)
|
goto comparison_error;
|
||||||
goto restart;
|
if (table != so->table || entry->key != startkey)
|
||||||
mask = so->mask; /* help avoid a register spill */
|
goto restart;
|
||||||
}
|
mask = so->mask;
|
||||||
|
|
||||||
if (i + LINEAR_PROBES <= mask) {
|
|
||||||
for (j = 0 ; j < LINEAR_PROBES ; j++) {
|
|
||||||
entry++;
|
|
||||||
if (entry->hash == 0 && entry->key == NULL)
|
|
||||||
goto found_unused;
|
|
||||||
if (entry->hash == hash) {
|
|
||||||
PyObject *startkey = entry->key;
|
|
||||||
assert(startkey != dummy);
|
|
||||||
if (startkey == key)
|
|
||||||
goto found_active;
|
|
||||||
if (PyUnicode_CheckExact(startkey)
|
|
||||||
&& PyUnicode_CheckExact(key)
|
|
||||||
&& _PyUnicode_EQ(startkey, key))
|
|
||||||
goto found_active;
|
|
||||||
table = so->table;
|
|
||||||
Py_INCREF(startkey);
|
|
||||||
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
|
||||||
Py_DECREF(startkey);
|
|
||||||
if (cmp > 0)
|
|
||||||
goto found_active;
|
|
||||||
if (cmp < 0)
|
|
||||||
goto comparison_error;
|
|
||||||
if (table != so->table || entry->key != startkey)
|
|
||||||
goto restart;
|
|
||||||
mask = so->mask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
entry++;
|
||||||
|
} while (probes--);
|
||||||
perturb >>= PERTURB_SHIFT;
|
perturb >>= PERTURB_SHIFT;
|
||||||
i = (i * 5 + 1 + perturb) & mask;
|
i = (i * 5 + 1 + perturb) & mask;
|
||||||
|
|
||||||
entry = &so->table[i];
|
|
||||||
if (entry->key == NULL)
|
|
||||||
goto found_unused;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
found_unused:
|
found_unused:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue