mirror of https://github.com/python/cpython
bpo-29304: Simplify dict lookup functions (GH-2407)
* remove hashpos parameter from lookdict functions. * remove many duplicated code from lookdict functions.
This commit is contained in:
parent
87c3c5de73
commit
778928b0c7
|
@ -12,8 +12,7 @@ typedef struct {
|
|||
* -1 when no entry found, -3 when compare raises error.
|
||||
*/
|
||||
typedef Py_ssize_t (*dict_lookup_func)
|
||||
(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr,
|
||||
Py_ssize_t *hashpos);
|
||||
(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);
|
||||
|
||||
#define DKIX_EMPTY (-1)
|
||||
#define DKIX_DUMMY (-2) /* Used internally */
|
||||
|
|
|
@ -223,18 +223,14 @@ equally good collision statistics, needed less code & used less memory.
|
|||
|
||||
/* forward declarations */
|
||||
static Py_ssize_t lookdict(PyDictObject *mp, PyObject *key,
|
||||
Py_hash_t hash, PyObject **value_addr,
|
||||
Py_ssize_t *hashpos);
|
||||
Py_hash_t hash, PyObject **value_addr);
|
||||
static Py_ssize_t lookdict_unicode(PyDictObject *mp, PyObject *key,
|
||||
Py_hash_t hash, PyObject **value_addr,
|
||||
Py_ssize_t *hashpos);
|
||||
Py_hash_t hash, PyObject **value_addr);
|
||||
static Py_ssize_t
|
||||
lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
|
||||
Py_hash_t hash, PyObject **value_addr,
|
||||
Py_ssize_t *hashpos);
|
||||
Py_hash_t hash, PyObject **value_addr);
|
||||
static Py_ssize_t lookdict_split(PyDictObject *mp, PyObject *key,
|
||||
Py_hash_t hash, PyObject **value_addr,
|
||||
Py_ssize_t *hashpos);
|
||||
Py_hash_t hash, PyObject **value_addr);
|
||||
|
||||
static int dictresize(PyDictObject *mp, Py_ssize_t minused);
|
||||
|
||||
|
@ -672,118 +668,59 @@ never raise an exception; that function can never return DKIX_ERROR when key
|
|||
is string. Otherwise, it falls back to lookdict().
|
||||
lookdict_unicode_nodummy is further specialized for string keys that cannot be
|
||||
the <dummy> value.
|
||||
For both, when the key isn't found a DKIX_EMPTY is returned. hashpos returns
|
||||
where the key index should be inserted.
|
||||
For both, when the key isn't found a DKIX_EMPTY is returned.
|
||||
*/
|
||||
static Py_ssize_t _Py_HOT_FUNCTION
|
||||
lookdict(PyDictObject *mp, PyObject *key,
|
||||
Py_hash_t hash, PyObject **value_addr, Py_ssize_t *hashpos)
|
||||
Py_hash_t hash, PyObject **value_addr)
|
||||
{
|
||||
size_t i, mask;
|
||||
Py_ssize_t ix, freeslot;
|
||||
int cmp;
|
||||
size_t i, mask, perturb;
|
||||
PyDictKeysObject *dk;
|
||||
PyDictKeyEntry *ep0, *ep;
|
||||
PyObject *startkey;
|
||||
PyDictKeyEntry *ep0;
|
||||
|
||||
top:
|
||||
dk = mp->ma_keys;
|
||||
mask = DK_MASK(dk);
|
||||
ep0 = DK_ENTRIES(dk);
|
||||
mask = DK_MASK(dk);
|
||||
perturb = hash;
|
||||
i = (size_t)hash & mask;
|
||||
|
||||
ix = dk_get_index(dk, i);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
if (ix == DKIX_DUMMY) {
|
||||
freeslot = i;
|
||||
}
|
||||
else {
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
if (ep->me_key == key) {
|
||||
*value_addr = ep->me_value;
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
return ix;
|
||||
}
|
||||
if (ep->me_hash == hash) {
|
||||
startkey = ep->me_key;
|
||||
Py_INCREF(startkey);
|
||||
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
||||
Py_DECREF(startkey);
|
||||
if (cmp < 0) {
|
||||
*value_addr = NULL;
|
||||
return DKIX_ERROR;
|
||||
}
|
||||
if (dk == mp->ma_keys && ep->me_key == startkey) {
|
||||
if (cmp > 0) {
|
||||
*value_addr = ep->me_value;
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
return ix;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* The dict was mutated, restart */
|
||||
goto top;
|
||||
}
|
||||
}
|
||||
freeslot = -1;
|
||||
}
|
||||
|
||||
for (size_t perturb = hash;;) {
|
||||
perturb >>= PERTURB_SHIFT;
|
||||
i = (i*5 + perturb + 1) & mask;
|
||||
ix = dk_get_index(dk, i);
|
||||
for (;;) {
|
||||
Py_ssize_t ix = dk_get_index(dk, i);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
if (hashpos != NULL) {
|
||||
*hashpos = (freeslot == -1) ? (Py_ssize_t)i : freeslot;
|
||||
}
|
||||
*value_addr = NULL;
|
||||
return ix;
|
||||
}
|
||||
if (ix == DKIX_DUMMY) {
|
||||
if (freeslot == -1)
|
||||
freeslot = i;
|
||||
continue;
|
||||
}
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
if (ep->me_key == key) {
|
||||
if (hashpos != NULL) {
|
||||
*hashpos = i;
|
||||
if (ix >= 0) {
|
||||
PyDictKeyEntry *ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
if (ep->me_key == key) {
|
||||
*value_addr = ep->me_value;
|
||||
return ix;
|
||||
}
|
||||
*value_addr = ep->me_value;
|
||||
return ix;
|
||||
}
|
||||
if (ep->me_hash == hash) {
|
||||
startkey = ep->me_key;
|
||||
Py_INCREF(startkey);
|
||||
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
||||
Py_DECREF(startkey);
|
||||
if (cmp < 0) {
|
||||
*value_addr = NULL;
|
||||
return DKIX_ERROR;
|
||||
}
|
||||
if (dk == mp->ma_keys && ep->me_key == startkey) {
|
||||
if (cmp > 0) {
|
||||
if (hashpos != NULL) {
|
||||
*hashpos = i;
|
||||
if (ep->me_hash == hash) {
|
||||
PyObject *startkey = ep->me_key;
|
||||
Py_INCREF(startkey);
|
||||
int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
||||
Py_DECREF(startkey);
|
||||
if (cmp < 0) {
|
||||
*value_addr = NULL;
|
||||
return DKIX_ERROR;
|
||||
}
|
||||
if (dk == mp->ma_keys && ep->me_key == startkey) {
|
||||
if (cmp > 0) {
|
||||
*value_addr = ep->me_value;
|
||||
return ix;
|
||||
}
|
||||
*value_addr = ep->me_value;
|
||||
return ix;
|
||||
}
|
||||
else {
|
||||
/* The dict was mutated, restart */
|
||||
goto top;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* The dict was mutated, restart */
|
||||
goto top;
|
||||
}
|
||||
}
|
||||
perturb >>= PERTURB_SHIFT;
|
||||
i = (i*5 + perturb + 1) & mask;
|
||||
}
|
||||
assert(0); /* NOT REACHED */
|
||||
return 0;
|
||||
|
@ -792,13 +729,8 @@ top:
|
|||
/* Specialized version for string-only keys */
|
||||
static Py_ssize_t _Py_HOT_FUNCTION
|
||||
lookdict_unicode(PyDictObject *mp, PyObject *key,
|
||||
Py_hash_t hash, PyObject **value_addr, Py_ssize_t *hashpos)
|
||||
Py_hash_t hash, PyObject **value_addr)
|
||||
{
|
||||
size_t i;
|
||||
size_t mask = DK_MASK(mp->ma_keys);
|
||||
Py_ssize_t ix, freeslot;
|
||||
PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
|
||||
|
||||
assert(mp->ma_values == NULL);
|
||||
/* Make sure this function doesn't have to handle non-unicode keys,
|
||||
including subclasses of str; e.g., one reason to subclass
|
||||
|
@ -806,59 +738,34 @@ lookdict_unicode(PyDictObject *mp, PyObject *key,
|
|||
that here. */
|
||||
if (!PyUnicode_CheckExact(key)) {
|
||||
mp->ma_keys->dk_lookup = lookdict;
|
||||
return lookdict(mp, key, hash, value_addr, hashpos);
|
||||
}
|
||||
i = (size_t)hash & mask;
|
||||
ix = dk_get_index(mp->ma_keys, i);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
if (ix == DKIX_DUMMY) {
|
||||
freeslot = i;
|
||||
}
|
||||
else {
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
if (ep->me_key == key
|
||||
|| (ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = ep->me_value;
|
||||
return ix;
|
||||
}
|
||||
freeslot = -1;
|
||||
return lookdict(mp, key, hash, value_addr);
|
||||
}
|
||||
|
||||
for (size_t perturb = hash;;) {
|
||||
perturb >>= PERTURB_SHIFT;
|
||||
i = mask & (i*5 + perturb + 1);
|
||||
ix = dk_get_index(mp->ma_keys, i);
|
||||
PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys);
|
||||
size_t mask = DK_MASK(mp->ma_keys);
|
||||
size_t perturb = (size_t)hash;
|
||||
size_t i = (size_t)hash & mask;
|
||||
|
||||
for (;;) {
|
||||
Py_ssize_t ix = dk_get_index(mp->ma_keys, i);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
if (hashpos != NULL) {
|
||||
*hashpos = (freeslot == -1) ? (Py_ssize_t)i : freeslot;
|
||||
}
|
||||
*value_addr = NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
if (ix == DKIX_DUMMY) {
|
||||
if (freeslot == -1)
|
||||
freeslot = i;
|
||||
continue;
|
||||
}
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
if (ep->me_key == key
|
||||
|| (ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
|
||||
*value_addr = ep->me_value;
|
||||
if (hashpos != NULL) {
|
||||
*hashpos = i;
|
||||
if (ix >= 0) {
|
||||
PyDictKeyEntry *ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
assert(PyUnicode_CheckExact(ep->me_key));
|
||||
if (ep->me_key == key ||
|
||||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
|
||||
*value_addr = ep->me_value;
|
||||
return ix;
|
||||
}
|
||||
return ix;
|
||||
}
|
||||
perturb >>= PERTURB_SHIFT;
|
||||
i = mask & (i*5 + perturb + 1);
|
||||
}
|
||||
|
||||
assert(0); /* NOT REACHED */
|
||||
return 0;
|
||||
}
|
||||
|
@ -867,14 +774,8 @@ lookdict_unicode(PyDictObject *mp, PyObject *key,
|
|||
* will be present. */
|
||||
static Py_ssize_t _Py_HOT_FUNCTION
|
||||
lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
|
||||
Py_hash_t hash, PyObject **value_addr,
|
||||
Py_ssize_t *hashpos)
|
||||
Py_hash_t hash, PyObject **value_addr)
|
||||
{
|
||||
size_t i;
|
||||
size_t mask = DK_MASK(mp->ma_keys);
|
||||
Py_ssize_t ix;
|
||||
PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
|
||||
|
||||
assert(mp->ma_values == NULL);
|
||||
/* Make sure this function doesn't have to handle non-unicode keys,
|
||||
including subclasses of str; e.g., one reason to subclass
|
||||
|
@ -882,47 +783,31 @@ lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
|
|||
that here. */
|
||||
if (!PyUnicode_CheckExact(key)) {
|
||||
mp->ma_keys->dk_lookup = lookdict;
|
||||
return lookdict(mp, key, hash, value_addr, hashpos);
|
||||
return lookdict(mp, key, hash, value_addr);
|
||||
}
|
||||
i = (size_t)hash & mask;
|
||||
ix = dk_get_index(mp->ma_keys, i);
|
||||
assert (ix != DKIX_DUMMY);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
assert(PyUnicode_CheckExact(ep->me_key));
|
||||
if (ep->me_key == key ||
|
||||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = ep->me_value;
|
||||
return ix;
|
||||
}
|
||||
for (size_t perturb = hash;;) {
|
||||
perturb >>= PERTURB_SHIFT;
|
||||
i = mask & (i*5 + perturb + 1);
|
||||
ix = dk_get_index(mp->ma_keys, i);
|
||||
|
||||
PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys);
|
||||
size_t mask = DK_MASK(mp->ma_keys);
|
||||
size_t perturb = (size_t)hash;
|
||||
size_t i = (size_t)hash & mask;
|
||||
|
||||
for (;;) {
|
||||
Py_ssize_t ix = dk_get_index(mp->ma_keys, i);
|
||||
assert (ix != DKIX_DUMMY);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL && PyUnicode_CheckExact(ep->me_key));
|
||||
PyDictKeyEntry *ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
assert(PyUnicode_CheckExact(ep->me_key));
|
||||
if (ep->me_key == key ||
|
||||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = ep->me_value;
|
||||
return ix;
|
||||
}
|
||||
perturb >>= PERTURB_SHIFT;
|
||||
i = mask & (i*5 + perturb + 1);
|
||||
}
|
||||
assert(0); /* NOT REACHED */
|
||||
return 0;
|
||||
|
@ -935,61 +820,40 @@ lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
|
|||
*/
|
||||
static Py_ssize_t _Py_HOT_FUNCTION
|
||||
lookdict_split(PyDictObject *mp, PyObject *key,
|
||||
Py_hash_t hash, PyObject **value_addr, Py_ssize_t *hashpos)
|
||||
Py_hash_t hash, PyObject **value_addr)
|
||||
{
|
||||
size_t i;
|
||||
size_t mask = DK_MASK(mp->ma_keys);
|
||||
Py_ssize_t ix;
|
||||
PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
|
||||
|
||||
/* mp must split table */
|
||||
assert(mp->ma_values != NULL);
|
||||
if (!PyUnicode_CheckExact(key)) {
|
||||
ix = lookdict(mp, key, hash, value_addr, hashpos);
|
||||
Py_ssize_t ix = lookdict(mp, key, hash, value_addr);
|
||||
if (ix >= 0) {
|
||||
*value_addr = mp->ma_values[ix];
|
||||
}
|
||||
return ix;
|
||||
}
|
||||
|
||||
i = (size_t)hash & mask;
|
||||
ix = dk_get_index(mp->ma_keys, i);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
assert(ix >= 0);
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL && PyUnicode_CheckExact(ep->me_key));
|
||||
if (ep->me_key == key ||
|
||||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = mp->ma_values[ix];
|
||||
return ix;
|
||||
}
|
||||
for (size_t perturb = hash;;) {
|
||||
perturb >>= PERTURB_SHIFT;
|
||||
i = mask & (i*5 + perturb + 1);
|
||||
ix = dk_get_index(mp->ma_keys, i);
|
||||
PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys);
|
||||
size_t mask = DK_MASK(mp->ma_keys);
|
||||
size_t perturb = (size_t)hash;
|
||||
size_t i = (size_t)hash & mask;
|
||||
|
||||
for (;;) {
|
||||
Py_ssize_t ix = dk_get_index(mp->ma_keys, i);
|
||||
assert (ix != DKIX_DUMMY);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
assert(ix >= 0);
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL && PyUnicode_CheckExact(ep->me_key));
|
||||
PyDictKeyEntry *ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
assert(PyUnicode_CheckExact(ep->me_key));
|
||||
if (ep->me_key == key ||
|
||||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = mp->ma_values[ix];
|
||||
return ix;
|
||||
}
|
||||
perturb >>= PERTURB_SHIFT;
|
||||
i = mask & (i*5 + perturb + 1);
|
||||
}
|
||||
assert(0); /* NOT REACHED */
|
||||
return 0;
|
||||
|
@ -1061,23 +925,19 @@ _PyDict_MaybeUntrack(PyObject *op)
|
|||
|
||||
The dict must be combined. */
|
||||
static Py_ssize_t
|
||||
find_empty_slot(PyDictKeysObject *keys, PyObject *key, Py_hash_t hash)
|
||||
find_empty_slot(PyDictKeysObject *keys, Py_hash_t hash)
|
||||
{
|
||||
size_t i;
|
||||
size_t mask = DK_MASK(keys);
|
||||
Py_ssize_t ix;
|
||||
assert(keys != NULL);
|
||||
|
||||
assert(key != NULL);
|
||||
|
||||
i = hash & mask;
|
||||
ix = dk_get_index(keys, i);
|
||||
for (size_t perturb = hash; ix != DKIX_EMPTY;) {
|
||||
const size_t mask = DK_MASK(keys);
|
||||
size_t i = hash & mask;
|
||||
Py_ssize_t ix = dk_get_index(keys, i);
|
||||
for (size_t perturb = hash; ix >= 0;) {
|
||||
perturb >>= PERTURB_SHIFT;
|
||||
i = i*5 + perturb + 1;
|
||||
ix = dk_get_index(keys, i & mask);
|
||||
i = (i*5 + perturb + 1) & mask;
|
||||
ix = dk_get_index(keys, i);
|
||||
}
|
||||
assert(DK_ENTRIES(keys)[keys->dk_nentries].me_value == NULL);
|
||||
return i & mask;
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1096,7 +956,6 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
|
|||
{
|
||||
PyObject *old_value;
|
||||
PyDictKeyEntry *ep;
|
||||
Py_ssize_t hashpos, ix;
|
||||
|
||||
Py_INCREF(key);
|
||||
Py_INCREF(value);
|
||||
|
@ -1105,7 +964,7 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
|
|||
goto Fail;
|
||||
}
|
||||
|
||||
ix = mp->ma_keys->dk_lookup(mp, key, hash, &old_value, &hashpos);
|
||||
Py_ssize_t ix = mp->ma_keys->dk_lookup(mp, key, hash, &old_value);
|
||||
if (ix == DKIX_ERROR)
|
||||
goto Fail;
|
||||
|
||||
|
@ -1120,7 +979,6 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
|
|||
(ix == DKIX_EMPTY && mp->ma_used != mp->ma_keys->dk_nentries))) {
|
||||
if (insertion_resize(mp) < 0)
|
||||
goto Fail;
|
||||
hashpos = find_empty_slot(mp->ma_keys, key, hash);
|
||||
ix = DKIX_EMPTY;
|
||||
}
|
||||
|
||||
|
@ -1131,8 +989,8 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
|
|||
/* Need to resize. */
|
||||
if (insertion_resize(mp) < 0)
|
||||
goto Fail;
|
||||
hashpos = find_empty_slot(mp->ma_keys, key, hash);
|
||||
}
|
||||
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
|
||||
ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
|
||||
dk_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
|
||||
ep->me_key = key;
|
||||
|
@ -1411,14 +1269,14 @@ PyDict_GetItem(PyObject *op, PyObject *key)
|
|||
/* preserve the existing exception */
|
||||
PyObject *err_type, *err_value, *err_tb;
|
||||
PyErr_Fetch(&err_type, &err_value, &err_tb);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value, NULL);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value);
|
||||
/* ignore errors */
|
||||
PyErr_Restore(err_type, err_value, err_tb);
|
||||
if (ix < 0)
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value, NULL);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value);
|
||||
if (ix < 0) {
|
||||
PyErr_Clear();
|
||||
return NULL;
|
||||
|
@ -1443,7 +1301,7 @@ _PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value, NULL);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value);
|
||||
if (ix < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1475,7 +1333,7 @@ PyDict_GetItemWithError(PyObject *op, PyObject *key)
|
|||
}
|
||||
}
|
||||
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value, NULL);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value);
|
||||
if (ix < 0)
|
||||
return NULL;
|
||||
return value;
|
||||
|
@ -1514,14 +1372,14 @@ _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
|
|||
}
|
||||
|
||||
/* namespace 1: globals */
|
||||
ix = globals->ma_keys->dk_lookup(globals, key, hash, &value, NULL);
|
||||
ix = globals->ma_keys->dk_lookup(globals, key, hash, &value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return NULL;
|
||||
if (ix != DKIX_EMPTY && value != NULL)
|
||||
return value;
|
||||
|
||||
/* namespace 2: builtins */
|
||||
ix = builtins->ma_keys->dk_lookup(builtins, key, hash, &value, NULL);
|
||||
ix = builtins->ma_keys->dk_lookup(builtins, key, hash, &value);
|
||||
if (ix < 0)
|
||||
return NULL;
|
||||
return value;
|
||||
|
@ -1577,12 +1435,15 @@ _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
|
|||
}
|
||||
|
||||
static int
|
||||
delitem_common(PyDictObject *mp, Py_ssize_t hashpos, Py_ssize_t ix,
|
||||
delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
|
||||
PyObject *old_value)
|
||||
{
|
||||
PyObject *old_key;
|
||||
PyDictKeyEntry *ep;
|
||||
|
||||
Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
|
||||
assert(hashpos >= 0);
|
||||
|
||||
mp->ma_used--;
|
||||
mp->ma_version_tag = DICT_NEXT_VERSION();
|
||||
ep = &DK_ENTRIES(mp->ma_keys)[ix];
|
||||
|
@ -1616,7 +1477,7 @@ PyDict_DelItem(PyObject *op, PyObject *key)
|
|||
int
|
||||
_PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
|
||||
{
|
||||
Py_ssize_t hashpos, ix;
|
||||
Py_ssize_t ix;
|
||||
PyDictObject *mp;
|
||||
PyObject *old_value;
|
||||
|
||||
|
@ -1627,25 +1488,24 @@ _PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
|
|||
assert(key);
|
||||
assert(hash != -1);
|
||||
mp = (PyDictObject *)op;
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value, &hashpos);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return -1;
|
||||
if (ix == DKIX_EMPTY || old_value == NULL) {
|
||||
_PyErr_SetKeyError(key);
|
||||
return -1;
|
||||
}
|
||||
assert(dk_get_index(mp->ma_keys, hashpos) == ix);
|
||||
|
||||
// Split table doesn't allow deletion. Combine it.
|
||||
if (_PyDict_HasSplitTable(mp)) {
|
||||
if (dictresize(mp, DK_SIZE(mp->ma_keys))) {
|
||||
return -1;
|
||||
}
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value, &hashpos);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value);
|
||||
assert(ix >= 0);
|
||||
}
|
||||
|
||||
return delitem_common(mp, hashpos, ix, old_value);
|
||||
return delitem_common(mp, hash, ix, old_value);
|
||||
}
|
||||
|
||||
/* This function promises that the predicate -> deletion sequence is atomic
|
||||
|
@ -1671,27 +1531,30 @@ _PyDict_DelItemIf(PyObject *op, PyObject *key,
|
|||
if (hash == -1)
|
||||
return -1;
|
||||
mp = (PyDictObject *)op;
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value, &hashpos);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return -1;
|
||||
if (ix == DKIX_EMPTY || old_value == NULL) {
|
||||
_PyErr_SetKeyError(key);
|
||||
return -1;
|
||||
}
|
||||
assert(dk_get_index(mp->ma_keys, hashpos) == ix);
|
||||
|
||||
// Split table doesn't allow deletion. Combine it.
|
||||
if (_PyDict_HasSplitTable(mp)) {
|
||||
if (dictresize(mp, DK_SIZE(mp->ma_keys))) {
|
||||
return -1;
|
||||
}
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value, &hashpos);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value);
|
||||
assert(ix >= 0);
|
||||
}
|
||||
|
||||
res = predicate(old_value);
|
||||
if (res == -1)
|
||||
return -1;
|
||||
|
||||
hashpos = lookdict_index(mp->ma_keys, hash, ix);
|
||||
assert(hashpos >= 0);
|
||||
|
||||
if (res > 0)
|
||||
return delitem_common(mp, hashpos, ix, old_value);
|
||||
else
|
||||
|
@ -1828,7 +1691,7 @@ _PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *d
|
|||
_PyErr_SetKeyError(key);
|
||||
return NULL;
|
||||
}
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value, &hashpos);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return NULL;
|
||||
if (ix == DKIX_EMPTY || old_value == NULL) {
|
||||
|
@ -1845,10 +1708,12 @@ _PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *d
|
|||
if (dictresize(mp, DK_SIZE(mp->ma_keys))) {
|
||||
return NULL;
|
||||
}
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value, &hashpos);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value);
|
||||
assert(ix >= 0);
|
||||
}
|
||||
|
||||
hashpos = lookdict_index(mp->ma_keys, hash, ix);
|
||||
assert(hashpos >= 0);
|
||||
assert(old_value != NULL);
|
||||
mp->ma_used--;
|
||||
mp->ma_version_tag = DICT_NEXT_VERSION();
|
||||
|
@ -2107,7 +1972,7 @@ dict_subscript(PyDictObject *mp, PyObject *key)
|
|||
if (hash == -1)
|
||||
return NULL;
|
||||
}
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value, NULL);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return NULL;
|
||||
if (ix == DKIX_EMPTY || value == NULL) {
|
||||
|
@ -2718,7 +2583,7 @@ dict_equal(PyDictObject *a, PyDictObject *b)
|
|||
/* ditto for key */
|
||||
Py_INCREF(key);
|
||||
/* reuse the known hash value */
|
||||
b->ma_keys->dk_lookup(b, key, ep->me_hash, &bval, NULL);
|
||||
b->ma_keys->dk_lookup(b, key, ep->me_hash, &bval);
|
||||
if (bval == NULL) {
|
||||
Py_DECREF(key);
|
||||
Py_DECREF(aval);
|
||||
|
@ -2783,7 +2648,7 @@ dict___contains__(PyDictObject *self, PyObject *key)
|
|||
if (hash == -1)
|
||||
return NULL;
|
||||
}
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value, NULL);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return NULL;
|
||||
if (ix == DKIX_EMPTY || value == NULL)
|
||||
|
@ -2815,7 +2680,7 @@ dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
|
|||
if (hash == -1)
|
||||
return NULL;
|
||||
}
|
||||
ix = (self->ma_keys->dk_lookup) (self, key, hash, &val, NULL);
|
||||
ix = (self->ma_keys->dk_lookup) (self, key, hash, &val);
|
||||
if (ix == DKIX_ERROR)
|
||||
return NULL;
|
||||
if (ix == DKIX_EMPTY || val == NULL) {
|
||||
|
@ -2831,7 +2696,6 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
|
|||
PyDictObject *mp = (PyDictObject *)d;
|
||||
PyObject *value;
|
||||
Py_hash_t hash;
|
||||
Py_ssize_t hashpos, ix;
|
||||
|
||||
if (!PyDict_Check(d)) {
|
||||
PyErr_BadInternalCall();
|
||||
|
@ -2850,7 +2714,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value, &hashpos);
|
||||
Py_ssize_t ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return NULL;
|
||||
|
||||
|
@ -2860,7 +2724,6 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
|
|||
if (insertion_resize(mp) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
hashpos = find_empty_slot(mp->ma_keys, key, hash);
|
||||
ix = DKIX_EMPTY;
|
||||
}
|
||||
|
||||
|
@ -2871,8 +2734,8 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
|
|||
if (insertion_resize(mp) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
hashpos = find_empty_slot(mp->ma_keys, key, hash);
|
||||
}
|
||||
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
|
||||
ep0 = DK_ENTRIES(mp->ma_keys);
|
||||
ep = &ep0[mp->ma_keys->dk_nentries];
|
||||
dk_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
|
||||
|
@ -3167,7 +3030,7 @@ PyDict_Contains(PyObject *op, PyObject *key)
|
|||
if (hash == -1)
|
||||
return -1;
|
||||
}
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value, NULL);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return -1;
|
||||
return (ix != DKIX_EMPTY && value != NULL);
|
||||
|
@ -3181,7 +3044,7 @@ _PyDict_Contains(PyObject *op, PyObject *key, Py_hash_t hash)
|
|||
PyObject *value;
|
||||
Py_ssize_t ix;
|
||||
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value, NULL);
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return -1;
|
||||
return (ix != DKIX_EMPTY && value != NULL);
|
||||
|
|
|
@ -546,7 +546,7 @@ _odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
|
|||
PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
|
||||
Py_ssize_t ix;
|
||||
|
||||
ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value, NULL);
|
||||
ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
return keys->dk_nentries; /* index of new entry */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue