diff -r de0fa478c22e Misc/NEWS --- a/Misc/NEWS Wed Oct 05 03:24:45 2016 +1100 +++ b/Misc/NEWS Wed Oct 05 13:40:56 2016 +0900 @@ -7,12 +7,15 @@ *Release date: XXXX-XX-XX* Core and Builtins ----------------- +- Issue #28201: Dict reduces possibility of 2nd conflict in hash table when + hashes have same lower bits. + - Issue #28350: String constants with null character no longer interned. - Issue #26617: Fix crash when GC runs during weakref callbacks. - Issue #27942: String constants now interned recursively in tuples and frozensets. diff -r de0fa478c22e Objects/dictobject.c --- a/Objects/dictobject.c Wed Oct 05 03:24:45 2016 +1100 +++ b/Objects/dictobject.c Wed Oct 05 13:40:56 2016 +0900 @@ -627,26 +627,26 @@ } /* Search index of hash table from offset of entry table */ static Py_ssize_t lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index) { - size_t i, perturb; + 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 (perturb = hash; ; perturb >>= PERTURB_SHIFT) { + for (size_t perturb = hash >> PERTURB_SHIFT; ; perturb >>= PERTURB_SHIFT) { i = mask & ((i << 2) + i + perturb + 1); ix = dk_get_index(k, i); if (ix == index) { return i; } if (ix == DKIX_EMPTY) { @@ -682,13 +682,13 @@ where the key index should be inserted. */ static Py_ssize_t lookdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos) { - size_t i, perturb, mask; + size_t i, mask; Py_ssize_t ix, freeslot; int cmp; PyDictKeysObject *dk; PyDictKeyEntry *ep0, *ep; PyObject *startkey; @@ -737,13 +737,13 @@ goto top; } } freeslot = -1; } - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { + for (size_t perturb = hash >> PERTURB_SHIFT; ; perturb >>= PERTURB_SHIFT) { i = ((i << 2) + i + perturb + 1) & mask; ix = dk_get_index(dk, i); if (ix == DKIX_EMPTY) { if (hashpos != NULL) { *hashpos = (freeslot == -1) ? (Py_ssize_t)i : freeslot; } @@ -794,13 +794,13 @@ /* Specialized version for string-only keys */ static Py_ssize_t lookdict_unicode(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos) { - size_t i, perturb; + 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, @@ -832,13 +832,13 @@ *value_addr = &ep->me_value; return ix; } freeslot = -1; } - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { + for (size_t perturb = hash >> PERTURB_SHIFT; ; perturb >>= PERTURB_SHIFT) { i = mask & ((i << 2) + i + perturb + 1); ix = dk_get_index(mp->ma_keys, i); if (ix == DKIX_EMPTY) { if (hashpos != NULL) { *hashpos = (freeslot == -1) ? (Py_ssize_t)i : freeslot; } @@ -869,13 +869,13 @@ * will be present. */ static Py_ssize_t lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos) { - size_t i, perturb; + 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, @@ -902,13 +902,13 @@ (ep->me_hash == hash && unicode_eq(ep->me_key, key))) { if (hashpos != NULL) *hashpos = i; *value_addr = &ep->me_value; return ix; } - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { + for (size_t perturb = hash >> PERTURB_SHIFT; ; perturb >>= PERTURB_SHIFT) { i = mask & ((i << 2) + i + perturb + 1); ix = dk_get_index(mp->ma_keys, i); assert (ix != DKIX_DUMMY); if (ix == DKIX_EMPTY) { if (hashpos != NULL) *hashpos = i; @@ -935,13 +935,13 @@ * so algorithm is the same as lookdict_unicode_nodummy. */ static Py_ssize_t lookdict_split(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos) { - size_t i, perturb; + 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); @@ -968,13 +968,13 @@ (ep->me_hash == hash && unicode_eq(ep->me_key, key))) { if (hashpos != NULL) *hashpos = i; *value_addr = &mp->ma_values[ix]; return ix; } - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { + for (size_t perturb = hash >> PERTURB_SHIFT; ; perturb >>= PERTURB_SHIFT) { i = mask & ((i << 2) + i + perturb + 1); ix = dk_get_index(mp->ma_keys, i); if (ix == DKIX_EMPTY) { if (hashpos != NULL) *hashpos = i; *value_addr = NULL; @@ -1061,26 +1061,27 @@ The dict must be combined. */ static void find_empty_slot(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos) { - size_t i, perturb; + size_t i; size_t mask = DK_MASK(mp->ma_keys); Py_ssize_t ix; PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys); assert(!_PyDict_HasSplitTable(mp)); assert(hashpos != NULL); assert(key != NULL); if (!PyUnicode_CheckExact(key)) mp->ma_keys->dk_lookup = lookdict; i = hash & mask; ix = dk_get_index(mp->ma_keys, i); - for (perturb = hash; ix != DKIX_EMPTY; perturb >>= PERTURB_SHIFT) { + for (size_t perturb = hash >> PERTURB_SHIFT; ix != DKIX_EMPTY; + perturb >>= PERTURB_SHIFT) { i = (i << 2) + i + perturb + 1; ix = dk_get_index(mp->ma_keys, i & mask); } ep = &ep0[mp->ma_keys->dk_nentries]; *hashpos = i & mask; assert(ep->me_value == NULL); @@ -1199,25 +1200,25 @@ must set them correctly */ static void insertdict_clean(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) { - size_t i, perturb; + size_t i; PyDictKeysObject *k = mp->ma_keys; size_t mask = (size_t)DK_SIZE(k)-1; PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys); PyDictKeyEntry *ep; assert(k->dk_lookup != NULL); assert(value != NULL); assert(key != NULL); assert(PyUnicode_CheckExact(key) || k->dk_lookup == lookdict); i = hash & mask; - for (perturb = hash; dk_get_index(k, i) != DKIX_EMPTY; - perturb >>= PERTURB_SHIFT) { + for (size_t perturb = hash >> PERTURB_SHIFT; + dk_get_index(k, i) != DKIX_EMPTY; perturb >>= PERTURB_SHIFT) { i = mask & ((i << 2) + i + perturb + 1); } ep = &ep0[k->dk_nentries]; assert(ep->me_value == NULL); dk_set_index(k, i, k->dk_nentries); k->dk_nentries++;