[Python-checkins] cpython: Issue #24583: Consolidate previous set object updates into a single function

raymond.hettinger python-checkins at python.org
Mon Jul 20 13:34:11 CEST 2015


https://hg.python.org/cpython/rev/3f2c12c0abdb
changeset:   96960:3f2c12c0abdb
parent:      96958:eb689c088e18
user:        Raymond Hettinger <python at rcn.com>
date:        Mon Jul 20 07:34:05 2015 -0400
summary:
  Issue #24583:  Consolidate previous set object updates into a single function
with a single entry point, named exit points at the bottom, more self-evident
refcount adjustments, and a comment describing why the pre-increment was
necessary at all.

files:
  Objects/setobject.c |  39 ++++++++++++++++----------------
  1 files changed, 20 insertions(+), 19 deletions(-)


diff --git a/Objects/setobject.c b/Objects/setobject.c
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -127,17 +127,27 @@
 static int set_table_resize(PySetObject *, Py_ssize_t);
 
 static int
-_set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
+set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
 {
-    setentry *table = so->table;
+    setentry *table;
     setentry *freeslot;
     setentry *entry;
     size_t perturb;
-    size_t mask = so->mask;
-    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
+    size_t mask;
+    size_t i;                       /* Unsigned for defined overflow behavior */
     size_t j;
     int cmp;
 
+    /* Pre-increment is necessary to prevent arbitrary code in the rich
+       comparison from deallocating the key just before the insertion. */
+    Py_INCREF(key);
+
+  restart:
+
+    table = so->table;
+    mask = so->mask;
+    i = (size_t)hash & mask;
+
     entry = &table[i];
     if (entry->key == NULL)
         goto found_unused;
@@ -160,9 +170,9 @@
             cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
             Py_DECREF(startkey);
             if (cmp < 0)                                          /* unlikely */
-                return -1;
+                goto comparison_error;
             if (table != so->table || entry->key != startkey)     /* unlikely */
-                return _set_add_entry(so, key, hash);
+                goto restart;
             if (cmp > 0)                                          /* likely */
                 goto found_active;
             mask = so->mask;                 /* help avoid a register spill */
@@ -188,9 +198,9 @@
                     cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
                     Py_DECREF(startkey);
                     if (cmp < 0)
-                        return -1;
+                        goto comparison_error;
                     if (table != so->table || entry->key != startkey)
-                        return _set_add_entry(so, key, hash);
+                        goto restart;
                     if (cmp > 0)
                         goto found_active;
                     mask = so->mask;
@@ -223,22 +233,13 @@
     entry->hash = hash;
     if ((size_t)so->fill*3 < mask*2)
         return 0;
-    if (!set_table_resize(so, so->used))
-        return 0;
-    Py_INCREF(key);
-    return -1;
+    return set_table_resize(so, so->used);
 
   found_active:
     Py_DECREF(key);
     return 0;
-}
 
-static int
-set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
-{
-    Py_INCREF(key);
-    if (!_set_add_entry(so, key, hash))
-        return 0;
+  comparison_error:
     Py_DECREF(key);
     return -1;
 }

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list