[Python-Dev] cpython: Tighten-up code in the set iterator to use an entry pointer rather than

Serhiy Storchaka storchaka at gmail.com
Tue Jul 7 09:42:43 CEST 2015


On 07.07.15 05:03, raymond.hettinger wrote:
> https://hg.python.org/cpython/rev/c9782a9ac031
> changeset:   96865:c9782a9ac031
> user:        Raymond Hettinger <python at rcn.com>
> date:        Mon Jul 06 19:03:01 2015 -0700
> summary:
>    Tighten-up code in the set iterator to use an entry pointer rather than indexing.
>
> files:
>    Objects/setobject.c |  35 ++++++++++++--------------------
>    1 files changed, 13 insertions(+), 22 deletions(-)
>
>
> diff --git a/Objects/setobject.c b/Objects/setobject.c
> --- a/Objects/setobject.c
> +++ b/Objects/setobject.c
> @@ -766,8 +766,8 @@
>       PyObject_HEAD
>       PySetObject *si_set; /* Set to NULL when iterator is exhausted */
>       Py_ssize_t si_used;
> -    Py_ssize_t si_pos;
>       Py_ssize_t len;
> +    setentry *entry;
>   } setiterobject;
>
>   static void
> @@ -845,8 +845,6 @@
>
>   static PyObject *setiter_iternext(setiterobject *si)
>   {
> -    PyObject *key;
> -    Py_ssize_t i, mask;
>       setentry *entry;
>       PySetObject *so = si->si_set;
>
> @@ -860,25 +858,18 @@
>           si->si_used = -1; /* Make this state sticky */
>           return NULL;
>       }
> -
> -    i = si->si_pos;
> -    assert(i>=0);
> -    entry = so->table;
> -    mask = so->mask;
> -    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy))
> -        i++;
> -    si->si_pos = i+1;
> -    if (i > mask)
> -        goto fail;
> +    if (si->len <= 0) {
> +        Py_DECREF(so);
> +        si->si_set = NULL;
> +        return NULL;
> +    }
> +    entry = si->entry;
> +    while (entry->key == NULL || entry->key == dummy)
> +        entry++;
>       si->len--;
> -    key = entry[i].key;
> -    Py_INCREF(key);
> -    return key;
> -
> -fail:
> -    Py_DECREF(so);
> -    si->si_set = NULL;
> -    return NULL;
> +    si->entry = entry + 1;
> +    Py_INCREF(entry->key);
> +    return entry->key;
>   }
>
>   PyTypeObject PySetIter_Type = {
> @@ -923,8 +914,8 @@
>       Py_INCREF(so);
>       si->si_set = so;
>       si->si_used = so->used;
> -    si->si_pos = 0;
>       si->len = so->used;
> +    si->entry = so->table;
>       _PyObject_GC_TRACK(si);
>       return (PyObject *)si;
>   }

What if so->table was reallocated during the iteration, but so->used is 
left the same? This change looks unsafe to me.




More information about the Python-Dev mailing list