diff options
author | Raymond Hettinger <python@rcn.com> | 2007-02-19 02:03:19 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2007-02-19 02:03:19 (GMT) |
commit | d6fc72a5ae27048dae56c773896ccbd6152d9b9b (patch) | |
tree | fceb231e6ba8e5b85b6f5baab0a908d056b9390d /Objects | |
parent | f7ccc101d2d623428dd03114bd8723946d5dbcae (diff) | |
download | cpython-d6fc72a5ae27048dae56c773896ccbd6152d9b9b.zip cpython-d6fc72a5ae27048dae56c773896ccbd6152d9b9b.tar.gz cpython-d6fc72a5ae27048dae56c773896ccbd6152d9b9b.tar.bz2 |
Extend work on revision 52962: Eliminate redundant calls to PyObject_Hash().
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/dictobject.c | 39 | ||||
-rw-r--r-- | Objects/setobject.c | 18 |
2 files changed, 50 insertions, 7 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 901e333..1cb3ee6 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -803,6 +803,34 @@ PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) 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, long *phash) +{ + register Py_ssize_t i; + register Py_ssize_t mask; + register dictentry *ep; + + if (!PyDict_Check(op)) + return 0; + i = *ppos; + if (i < 0) + return 0; + ep = ((dictobject *)op)->ma_table; + mask = ((dictobject *)op)->ma_mask; + while (i <= mask && ep[i].me_value == NULL) + i++; + *ppos = i+1; + if (i > mask) + return 0; + *phash = (long)(ep[i].me_hash); + if (pkey) + *pkey = ep[i].me_key; + if (pvalue) + *pvalue = ep[i].me_value; + return 1; +} + /* Methods */ static void @@ -1987,6 +2015,17 @@ PyDict_Contains(PyObject *op, PyObject *key) return ep == NULL ? -1 : (ep->me_value != NULL); } +/* Internal version of PyDict_Contains used when the hash value is already known */ +int +_PyDict_Contains(PyObject *op, PyObject *key, long hash) +{ + dictobject *mp = (dictobject *)op; + dictentry *ep; + + ep = (mp->ma_lookup)(mp, key, hash); + return ep == NULL ? -1 : (ep->me_value != NULL); +} + /* Hack to implement "key in dict" */ static PySequenceMethods dict_as_sequence = { 0, /* sq_length */ diff --git a/Objects/setobject.c b/Objects/setobject.c index fc9d823..1f06cee 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -918,8 +918,14 @@ set_update_internal(PySetObject *so, PyObject *other) if (PyDict_CheckExact(other)) { PyObject *value; Py_ssize_t pos = 0; - while (PyDict_Next(other, &pos, &key, &value)) { - if (set_add_key(so, key) == -1) + long hash; + + while (_PyDict_Next(other, &pos, &key, &value, &hash)) { + setentry an_entry; + + an_entry.hash = hash; + an_entry.key = key; + if (set_add_entry(so, &an_entry) == -1) return -1; } return 0; @@ -1382,7 +1388,7 @@ set_difference(PySetObject *so, PyObject *other) setentry entrycopy; entrycopy.hash = entry->hash; entrycopy.key = entry->key; - if (!PyDict_Contains(other, entry->key)) { + if (!_PyDict_Contains(other, entry->key, entry->hash)) { if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { Py_DECREF(result); return NULL; @@ -1453,12 +1459,10 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other) if (PyDict_CheckExact(other)) { PyObject *value; int rv; - while (PyDict_Next(other, &pos, &key, &value)) { + long hash; + while (_PyDict_Next(other, &pos, &key, &value, &hash)) { setentry an_entry; - long hash = PyObject_Hash(key); - if (hash == -1) - return NULL; an_entry.hash = hash; an_entry.key = key; rv = set_discard_entry(so, &an_entry); |