diff options
author | Raymond Hettinger <python@rcn.com> | 2015-07-20 11:34:05 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2015-07-20 11:34:05 (GMT) |
commit | ff9e18a863aa9f7efd894f660d413cd02ccb1834 (patch) | |
tree | 0a324d2e1681bbb687f3f5e8aa0d7b42a35b6e68 /Objects | |
parent | aa23fa2e21677c21f5727e6c2602a8bbf67d7fe4 (diff) | |
download | cpython-ff9e18a863aa9f7efd894f660d413cd02ccb1834.zip cpython-ff9e18a863aa9f7efd894f660d413cd02ccb1834.tar.gz cpython-ff9e18a863aa9f7efd894f660d413cd02ccb1834.tar.bz2 |
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.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/setobject.c | 39 |
1 files changed, 20 insertions, 19 deletions
diff --git a/Objects/setobject.c b/Objects/setobject.c index 83bff81..3c4c484 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -127,17 +127,27 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash) 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 @@ _set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) 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 @@ _set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) 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 @@ _set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) 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; } |