summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2014-05-03 23:32:11 (GMT)
committerRaymond Hettinger <python@rcn.com>2014-05-03 23:32:11 (GMT)
commit4b74fba62ff9e9733da01a55d4091b656324e969 (patch)
tree3cec3f8e3aac0f6f0e3fb30e1fa06c11c6a4e746
parent1b5eebcfa3e5d21c14e89dc7e5bf2d124f8710a2 (diff)
downloadcpython-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.h4
-rw-r--r--Objects/dictobject.c56
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;