diff -r 1a97b10cb420 Objects/dictobject.c --- a/Objects/dictobject.c Tue Jan 17 04:20:26 2017 +0100 +++ b/Objects/dictobject.c Wed Jan 18 00:30:33 2017 +0900 @@ -631,29 +631,20 @@ PyDict_New(void) static Py_ssize_t lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index) { - size_t i; size_t mask = DK_MASK(k); - Py_ssize_t ix; - - i = (size_t)hash & mask; - ix = dk_get_index(k, i); - if (ix == index) { - return i; - } - if (ix == DKIX_EMPTY) { - return DKIX_EMPTY; - } - - for (size_t perturb = hash;;) { - perturb >>= PERTURB_SHIFT; - i = mask & ((i << 2) + i + perturb + 1); - ix = dk_get_index(k, i); + size_t perturb = (size_t)hash; + size_t i = (size_t)hash & mask; + + for (;;) { + Py_ssize_t ix = dk_get_index(k, i); if (ix == index) { return i; } if (ix == DKIX_EMPTY) { return DKIX_EMPTY; } + perturb >>= PERTURB_SHIFT; + i = mask & ((i << 2) + i + perturb + 1); } assert(0); /* NOT REACHED */ return DKIX_ERROR; @@ -687,9 +678,8 @@ static Py_ssize_t _Py_HOT_FUNCTION lookdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr, Py_ssize_t *hashpos) { - size_t i, mask; - Py_ssize_t ix, freeslot; - int cmp; + size_t i, mask, perturb; + Py_ssize_t freeslot; PyDictKeysObject *dk; PyDictKeyEntry *ep0, *ep; PyObject *startkey; @@ -698,100 +688,57 @@ top: dk = mp->ma_keys; mask = DK_MASK(dk); ep0 = DK_ENTRIES(dk); + perturb = (size_t)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 << 2) + i + perturb + 1) & mask; - ix = dk_get_index(dk, i); + freeslot = -1; + + 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; + 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) { - 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; + 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 (dk == mp->ma_keys && ep->me_key == startkey) { - if (cmp > 0) { - if (hashpos != NULL) { - *hashpos = i; + if (ep->me_hash == hash) { + 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; + if (hashpos != NULL) + *hashpos = i; + 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 << 2) + i + perturb + 1) & mask; } assert(0); /* NOT REACHED */ return 0; @@ -802,11 +749,6 @@ static Py_ssize_t _Py_HOT_FUNCTION lookdict_unicode(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr, Py_ssize_t *hashpos) { - 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 @@ -816,34 +758,15 @@ lookdict_unicode(PyDictObject *mp, PyObj 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; - } - - for (size_t perturb = hash;;) { - perturb >>= PERTURB_SHIFT; - i = mask & ((i << 2) + i + perturb + 1); - ix = dk_get_index(mp->ma_keys, i); + + size_t mask = DK_MASK(mp->ma_keys); + PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys); + size_t perturb = hash; + size_t i = (size_t)hash & mask; + Py_ssize_t freeslot = -1; + + 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; @@ -854,18 +777,22 @@ lookdict_unicode(PyDictObject *mp, PyObj 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; + else { + PyDictKeyEntry *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; } - return ix; + freeslot = -1; } + + perturb >>= PERTURB_SHIFT; + i = mask & ((i << 2) + i + perturb + 1); } assert(0); /* NOT REACHED */ return 0; @@ -878,11 +805,6 @@ lookdict_unicode_nodummy(PyDictObject *m Py_hash_t hash, PyObject **value_addr, Py_ssize_t *hashpos) { - 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 @@ -892,38 +814,26 @@ lookdict_unicode_nodummy(PyDictObject *m 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); - 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 << 2) + i + 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 i = (size_t)hash & mask; + size_t perturb = hash; + + 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) @@ -931,6 +841,9 @@ lookdict_unicode_nodummy(PyDictObject *m *value_addr = ep->me_value; return ix; } + + perturb >>= PERTURB_SHIFT; + i = mask & ((i << 2) + i + perturb + 1); } assert(0); /* NOT REACHED */ return 0; @@ -945,52 +858,36 @@ static Py_ssize_t _Py_HOT_FUNCTION lookdict_split(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr, Py_ssize_t *hashpos) { - 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, hashpos); 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 << 2) + i + 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 i = (size_t)hash & mask; + size_t perturb = hash; + + 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) @@ -998,6 +895,9 @@ lookdict_split(PyDictObject *mp, PyObjec *value_addr = mp->ma_values[ix]; return ix; } + + perturb >>= PERTURB_SHIFT; + i = mask & ((i << 2) + i + perturb + 1); } assert(0); /* NOT REACHED */ return 0;