https://github.com/python/cpython/commit/778928b0c7aa438c282727535814d73df85... commit: 778928b0c7aa438c282727535814d73df850693a branch: master author: INADA Naoki <methane@users.noreply.github.com> committer: GitHub <noreply@github.com> date: 2017-08-03T23:45:15+09:00 summary: bpo-29304: Simplify dict lookup functions (GH-2407) * remove hashpos parameter from lookdict functions. * remove many duplicated code from lookdict functions. files: M Objects/dict-common.h M Objects/dictobject.c M Objects/odictobject.c diff --git a/Objects/dict-common.h b/Objects/dict-common.h index 62185527347..3e524686b44 100644 --- a/Objects/dict-common.h +++ b/Objects/dict-common.h @@ -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 */ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index c44ff47f8b3..e395f4dabb3 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -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; - } - *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 (ix >= 0) { + PyDictKeyEntry *ep = &ep0[ix]; + assert(ep->me_key != NULL); + if (ep->me_key == key) { + *value_addr = ep->me_value; + return ix; } - 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 @@ lookdict(PyDictObject *mp, PyObject *key, /* 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(key != NULL); + assert(keys != 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); diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 771dcc308c5..c3d1a09584e 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -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 */ }