diff -r b6ca2d734f8e Objects/dictobject.c --- a/Objects/dictobject.c Wed Sep 14 23:54:09 2016 -0700 +++ b/Objects/dictobject.c Sat Sep 17 00:26:09 2016 +0300 @@ -1683,43 +1683,46 @@ PyDict_Clear(PyObject *op) assert(_PyDict_CheckConsistency(mp)); } -/* Returns -1 if no more items (or op is not a dict), - * index of item otherwise. Stores value in pvalue +/* Internal version of PyDict_Next that returns a hash value in addition + * to the key and value. */ -static inline Py_ssize_t -dict_next(PyObject *op, Py_ssize_t i, PyObject **pvalue) +int +_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, + PyObject **pvalue, Py_hash_t *phash) { - Py_ssize_t n; + Py_ssize_t i, n; PyDictObject *mp; - PyObject **value_ptr = NULL; + PyDictKeyEntry *entry_ptr; + PyObject *key; if (!PyDict_Check(op)) - return -1; + return 0; mp = (PyDictObject *)op; + i = *ppos; if (i < 0) - return -1; + return 0; n = mp->ma_keys->dk_nentries; - if (mp->ma_values) { - for (; i < n; i++) { - value_ptr = &mp->ma_values[i]; - if (*value_ptr != NULL) - break; + entry_ptr = &DK_ENTRIES(mp->ma_keys)[i]; + while (i < n && (key = entry_ptr->me_key) == NULL) { + entry_ptr++; + i++; + } + if (i >= n) + return 0; + *ppos = i+1; + if (pkey) + *pkey = key; + *phash = entry_ptr->me_hash; + if (pvalue) { + if (mp->ma_values) { + *pvalue = mp->ma_values[i]; + } + else { + *pvalue = entry_ptr->me_value; } } - else { - PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys); - for (; i < n; i++) { - value_ptr = &ep0[i].me_value; - if (*value_ptr != NULL) - break; - } - } - if (i >= n) - return -1; - if (pvalue) - *pvalue = *value_ptr; - return i; + return 1; } /* @@ -1740,36 +1743,8 @@ dict_next(PyObject *op, Py_ssize_t i, Py int PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) { - PyDictObject *mp = (PyDictObject*)op; - Py_ssize_t i = dict_next(op, *ppos, pvalue); - if (i < 0) - return 0; - mp = (PyDictObject *)op; - *ppos = i+1; - if (pkey) - *pkey = DK_ENTRIES(mp->ma_keys)[i].me_key; - return 1; -} - -/* Internal version of PyDict_Next that returns a hash value in addition - * to the key and value. - */ -int -_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, - PyObject **pvalue, Py_hash_t *phash) -{ - PyDictObject *mp; - PyDictKeyEntry *ep0; - Py_ssize_t i = dict_next(op, *ppos, pvalue); - if (i < 0) - return 0; - mp = (PyDictObject *)op; - ep0 = DK_ENTRIES(mp->ma_keys); - *ppos = i+1; - *phash = ep0[i].me_hash; - if (pkey) - *pkey = ep0[i].me_key; - return 1; + Py_hash_t hash; + return _PyDict_Next(op, ppos, pkey, pvalue, &hash); } /* Internal version of dict.pop(). */ @@ -3321,10 +3296,10 @@ static PyMethodDef dictiter_methods[] = static PyObject *dictiter_iternextkey(dictiterobject *di) { PyObject *key; - Py_ssize_t i, n, offset; + Py_ssize_t i, n; PyDictKeysObject *k; + PyDictKeyEntry *entry_ptr; PyDictObject *d = di->di_dict; - PyObject **value_ptr; if (d == NULL) return NULL; @@ -3338,27 +3313,17 @@ static PyObject *dictiter_iternextkey(di } i = di->di_pos; - if (i < 0) - goto fail; k = d->ma_keys; - if (d->ma_values) { - value_ptr = &d->ma_values[i]; - offset = sizeof(PyObject *); - } - else { - value_ptr = &DK_ENTRIES(k)[i].me_value; - offset = sizeof(PyDictKeyEntry); - } - n = k->dk_nentries - 1; - while (i <= n && *value_ptr == NULL) { - value_ptr = (PyObject **)(((char *)value_ptr) + offset); + n = k->dk_nentries; + entry_ptr = &DK_ENTRIES(k)[i]; + while (i < n && (key = entry_ptr->me_key) == NULL) { + entry_ptr++; i++; } + if (i >= n) + goto fail; di->di_pos = i+1; - if (i > n) - goto fail; di->len--; - key = DK_ENTRIES(k)[i].me_key; Py_INCREF(key); return key; @@ -3404,9 +3369,8 @@ PyTypeObject PyDictIterKey_Type = { static PyObject *dictiter_iternextvalue(dictiterobject *di) { PyObject *value; - Py_ssize_t i, n, offset; + Py_ssize_t i, n; PyDictObject *d = di->di_dict; - PyObject **value_ptr; if (d == NULL) return NULL; @@ -3420,26 +3384,25 @@ static PyObject *dictiter_iternextvalue( } i = di->di_pos; - n = d->ma_keys->dk_nentries - 1; - if (i < 0 || i > n) - goto fail; + n = d->ma_keys->dk_nentries; if (d->ma_values) { - value_ptr = &d->ma_values[i]; - offset = sizeof(PyObject *); + PyObject **value_ptr = &d->ma_values[i]; + while (i < n && (value = *value_ptr) == NULL) { + value_ptr++; + i++; + } } else { - value_ptr = &DK_ENTRIES(d->ma_keys)[i].me_value; - offset = sizeof(PyDictKeyEntry); - } - while (i <= n && *value_ptr == NULL) { - value_ptr = (PyObject **)(((char *)value_ptr) + offset); - i++; - if (i > n) - goto fail; + PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i]; + while (i < n && (value = entry_ptr->me_value) == NULL) { + entry_ptr++; + i++; + } } di->di_pos = i+1; + if (i >= n) + goto fail; di->len--; - value = *value_ptr; Py_INCREF(value); return value; @@ -3485,9 +3448,9 @@ PyTypeObject PyDictIterValue_Type = { static PyObject *dictiter_iternextitem(dictiterobject *di) { PyObject *key, *value, *result = di->di_result; - Py_ssize_t i, n, offset; + Py_ssize_t i, n; + PyDictKeyEntry *entry_ptr; PyDictObject *d = di->di_dict; - PyObject **value_ptr; if (d == NULL) return NULL; @@ -3501,25 +3464,17 @@ static PyObject *dictiter_iternextitem(d } i = di->di_pos; - if (i < 0) - goto fail; - n = d->ma_keys->dk_nentries - 1; - if (d->ma_values) { - value_ptr = &d->ma_values[i]; - offset = sizeof(PyObject *); - } - else { - value_ptr = &DK_ENTRIES(d->ma_keys)[i].me_value; - offset = sizeof(PyDictKeyEntry); - } - while (i <= n && *value_ptr == NULL) { - value_ptr = (PyObject **)(((char *)value_ptr) + offset); + n = d->ma_keys->dk_nentries; + entry_ptr = &DK_ENTRIES(d->ma_keys)[i]; + while (i < n && (key = entry_ptr->me_key) == NULL) { + entry_ptr++; i++; } + if (i >= n) + goto fail; + di->di_pos = i+1; - if (i > n) - goto fail; - + di->len--; if (result->ob_refcnt == 1) { Py_INCREF(result); Py_DECREF(PyTuple_GET_ITEM(result, 0)); @@ -3529,9 +3484,7 @@ static PyObject *dictiter_iternextitem(d if (result == NULL) return NULL; } - di->len--; - key = DK_ENTRIES(d->ma_keys)[i].me_key; - value = *value_ptr; + value = entry_ptr->me_value; Py_INCREF(key); Py_INCREF(value); PyTuple_SET_ITEM(result, 0, key); /* steals reference */