diff options
author | Raymond Hettinger <python@rcn.com> | 2014-05-03 23:32:11 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2014-05-03 23:32:11 (GMT) |
commit | 4b74fba62ff9e9733da01a55d4091b656324e969 (patch) | |
tree | 3cec3f8e3aac0f6f0e3fb30e1fa06c11c6a4e746 | |
parent | 1b5eebcfa3e5d21c14e89dc7e5bf2d124f8710a2 (diff) | |
download | cpython-4b74fba62ff9e9733da01a55d4091b656324e969.zip cpython-4b74fba62ff9e9733da01a55d4091b656324e969.tar.gz cpython-4b74fba62ff9e9733da01a55d4091b656324e969.tar.bz2 |
Issue 21101: Internal API for dict getitem and setitem where the hash value is known.
-rw-r--r-- | Include/dictobject.h | 4 | ||||
-rw-r--r-- | Objects/dictobject.c | 56 |
2 files changed, 60 insertions, 0 deletions
diff --git a/Include/dictobject.h b/Include/dictobject.h index ef122bd..3e0544a 100644 --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -50,6 +50,8 @@ PyAPI_DATA(PyTypeObject) PyDictValues_Type; PyAPI_FUNC(PyObject *) PyDict_New(void); PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key); +PyAPI_FUNC(PyObject *) _PyDict_GetItem_KnownHash(PyObject *mp, PyObject *key, + Py_hash_t hash); PyAPI_FUNC(PyObject *) PyDict_GetItemWithError(PyObject *mp, PyObject *key); PyAPI_FUNC(PyObject *) _PyDict_GetItemIdWithError(PyObject *dp, struct _Py_Identifier *key); @@ -58,6 +60,8 @@ PyAPI_FUNC(PyObject *) PyDict_SetDefault( PyObject *mp, PyObject *key, PyObject *defaultobj); #endif PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item); +PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key, + PyObject *item, Py_hash_t hash); PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key); PyAPI_FUNC(void) PyDict_Clear(PyObject *mp); PyAPI_FUNC(int) PyDict_Next( diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 1ccea6e..6c78b94 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1101,6 +1101,44 @@ PyDict_GetItem(PyObject *op, PyObject *key) return *value_addr; } +PyObject * +_PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash) +{ + PyDictObject *mp = (PyDictObject *)op; + PyDictKeyEntry *ep; + PyThreadState *tstate; + PyObject **value_addr; + + if (!PyDict_Check(op)) + return NULL; + + /* We can arrive here with a NULL tstate during initialization: try + running "python -Wi" for an example related to string interning. + Let's just hope that no exception occurs then... This must be + _PyThreadState_Current and not PyThreadState_GET() because in debug + mode, the latter complains if tstate is NULL. */ + tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); + if (tstate != NULL && tstate->curexc_type != NULL) { + /* preserve the existing exception */ + PyObject *err_type, *err_value, *err_tb; + PyErr_Fetch(&err_type, &err_value, &err_tb); + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); + /* ignore errors */ + PyErr_Restore(err_type, err_value, err_tb); + if (ep == NULL) + return NULL; + } + else { + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); + if (ep == NULL) { + PyErr_Clear(); + return NULL; + } + } + return *value_addr; +} + /* Variant of PyDict_GetItem() that doesn't suppress exceptions. This returns NULL *with* an exception set if an exception occurred. It returns NULL *without* an exception set if the key wasn't present. @@ -1208,6 +1246,24 @@ PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value) } int +_PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value, + Py_hash_t hash) +{ + PyDictObject *mp; + + if (!PyDict_Check(op)) { + PyErr_BadInternalCall(); + return -1; + } + assert(key); + assert(value); + mp = (PyDictObject *)op; + + /* insertdict() handles any resizing that might be necessary */ + return insertdict(mp, key, hash, value); +} + +int PyDict_DelItem(PyObject *op, PyObject *key) { PyDictObject *mp; |