mirror of
https://github.com/python/cpython.git
synced 2026-06-21 02:22:23 -04:00
gh-137759: Replace _PyObject_HashFast() with PyObject_Hash() in setobject.c (#137828)
Replace also _PyObject_HashFast() with PyObject_Hash() in _collections._count_elements(). Rename _PyObject_HashFast() to _PyObject_HashDictKey(), and mark it as Py_ALWAYS_INLINE. Only use _PyObject_HashDictKey() on dictionaries.
This commit is contained in:
@@ -830,9 +830,14 @@ _PyObject_IS_GC(PyObject *obj)
|
||||
&& (type->tp_is_gc == NULL || type->tp_is_gc(obj)));
|
||||
}
|
||||
|
||||
// Fast inlined version of PyObject_Hash()
|
||||
static inline Py_hash_t
|
||||
_PyObject_HashFast(PyObject *op)
|
||||
// Fast inlined version of PyObject_Hash(). Dictionaries are very
|
||||
// likely to include string keys (class and instance attributes,
|
||||
// json, ...) so we include a fast path for strings.
|
||||
// This function should not be used in a collection if str is not
|
||||
// very likely, since it is slower than PyObject_Hash() on types
|
||||
// other than str. See gh-137759.
|
||||
static inline Py_ALWAYS_INLINE Py_hash_t
|
||||
_PyObject_HashDictKey(PyObject *op)
|
||||
{
|
||||
if (PyUnicode_CheckExact(op)) {
|
||||
Py_hash_t hash = PyUnstable_Unicode_GET_CACHED_HASH(op);
|
||||
|
||||
@@ -2590,7 +2590,7 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping,
|
||||
if (key == NULL)
|
||||
break;
|
||||
|
||||
hash = _PyObject_HashFast(key);
|
||||
hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
+15
-15
@@ -2384,7 +2384,7 @@ dict_getitem(PyObject *op, PyObject *key, const char *warnmsg)
|
||||
}
|
||||
PyDictObject *mp = (PyDictObject *)op;
|
||||
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
PyErr_FormatUnraisable(warnmsg);
|
||||
return NULL;
|
||||
@@ -2456,7 +2456,7 @@ _PyDict_LookupIndexAndValue(PyDictObject *mp, PyObject *key, PyObject **value)
|
||||
assert(PyDict_CheckExact((PyObject*)mp));
|
||||
assert(PyUnicode_CheckExact(key));
|
||||
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type((PyObject*)mp, key);
|
||||
return -1;
|
||||
@@ -2560,7 +2560,7 @@ PyDict_GetItemRef(PyObject *op, PyObject *key, PyObject **result)
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type(op, key);
|
||||
*result = NULL;
|
||||
@@ -2576,7 +2576,7 @@ _PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject **
|
||||
ASSERT_DICT_LOCKED(op);
|
||||
assert(PyUnicode_CheckExact(key));
|
||||
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type((PyObject*)op, key);
|
||||
*result = NULL;
|
||||
@@ -2614,7 +2614,7 @@ PyDict_GetItemWithError(PyObject *op, PyObject *key)
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
hash = _PyObject_HashFast(key);
|
||||
hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type(op, key);
|
||||
return NULL;
|
||||
@@ -2673,7 +2673,7 @@ _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
|
||||
Py_hash_t hash;
|
||||
PyObject *value;
|
||||
|
||||
hash = _PyObject_HashFast(key);
|
||||
hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -2697,7 +2697,7 @@ _PyDict_LoadGlobalStackRef(PyDictObject *globals, PyDictObject *builtins, PyObje
|
||||
Py_ssize_t ix;
|
||||
Py_hash_t hash;
|
||||
|
||||
hash = _PyObject_HashFast(key);
|
||||
hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
*res = PyStackRef_NULL;
|
||||
return;
|
||||
@@ -2774,7 +2774,7 @@ setitem_take2_lock_held_known_hash(PyDictObject *mp, PyObject *key, PyObject *va
|
||||
static int
|
||||
setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
|
||||
{
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type((PyObject*)mp, key);
|
||||
Py_DECREF(key);
|
||||
@@ -2952,7 +2952,7 @@ int
|
||||
PyDict_DelItem(PyObject *op, PyObject *key)
|
||||
{
|
||||
assert(key);
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type(op, key);
|
||||
return -1;
|
||||
@@ -3296,7 +3296,7 @@ pop_lock_held(PyObject *op, PyObject *key, PyObject **result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type(op, key);
|
||||
if (result) {
|
||||
@@ -3734,7 +3734,7 @@ _PyDict_SubscriptKnownHash(PyObject *self, PyObject *key, Py_hash_t hash)
|
||||
PyObject *
|
||||
_PyDict_Subscript(PyObject *self, PyObject *key)
|
||||
{
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type(self, key);
|
||||
return NULL;
|
||||
@@ -4686,7 +4686,7 @@ dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
|
||||
Py_hash_t hash;
|
||||
Py_ssize_t ix;
|
||||
|
||||
hash = _PyObject_HashFast(key);
|
||||
hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type((PyObject*)self, key);
|
||||
return NULL;
|
||||
@@ -4723,7 +4723,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
|
||||
Py_hash_t hash;
|
||||
Py_ssize_t ix;
|
||||
|
||||
hash = _PyObject_HashFast(key);
|
||||
hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type(d, key);
|
||||
if (result) {
|
||||
@@ -5165,7 +5165,7 @@ static PyMethodDef mapp_methods[] = {
|
||||
static int
|
||||
dict_contains(PyObject *op, PyObject *key)
|
||||
{
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(key);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type(op, key);
|
||||
return -1;
|
||||
@@ -7298,7 +7298,7 @@ _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value)
|
||||
}
|
||||
|
||||
if (value == NULL) {
|
||||
Py_hash_t hash = _PyObject_HashFast(name);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(name);
|
||||
if (hash == -1) {
|
||||
dict_unhashable_type((PyObject*)dict, name);
|
||||
return -1;
|
||||
|
||||
+7
-7
@@ -361,7 +361,7 @@ set_unhashable_type(PyObject *key)
|
||||
int
|
||||
_PySet_AddTakeRef(PySetObject *so, PyObject *key)
|
||||
{
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = PyObject_Hash(key);
|
||||
if (hash == -1) {
|
||||
set_unhashable_type(key);
|
||||
Py_DECREF(key);
|
||||
@@ -600,7 +600,7 @@ set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
|
||||
static int
|
||||
set_add_key(PySetObject *so, PyObject *key)
|
||||
{
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = PyObject_Hash(key);
|
||||
if (hash == -1) {
|
||||
set_unhashable_type(key);
|
||||
return -1;
|
||||
@@ -611,7 +611,7 @@ set_add_key(PySetObject *so, PyObject *key)
|
||||
static int
|
||||
set_contains_key(PySetObject *so, PyObject *key)
|
||||
{
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = PyObject_Hash(key);
|
||||
if (hash == -1) {
|
||||
set_unhashable_type(key);
|
||||
return -1;
|
||||
@@ -622,7 +622,7 @@ set_contains_key(PySetObject *so, PyObject *key)
|
||||
static int
|
||||
set_discard_key(PySetObject *so, PyObject *key)
|
||||
{
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = PyObject_Hash(key);
|
||||
if (hash == -1) {
|
||||
set_unhashable_type(key);
|
||||
return -1;
|
||||
@@ -2514,7 +2514,7 @@ _PySet_Contains(PySetObject *so, PyObject *key)
|
||||
{
|
||||
assert(so);
|
||||
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = PyObject_Hash(key);
|
||||
if (hash == -1) {
|
||||
if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) {
|
||||
set_unhashable_type(key);
|
||||
@@ -2574,7 +2574,7 @@ static PyObject *
|
||||
frozenset___contains___impl(PySetObject *so, PyObject *key)
|
||||
/*[clinic end generated code: output=2301ed91bc3a6dd5 input=2f04922a98d8bab7]*/
|
||||
{
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = PyObject_Hash(key);
|
||||
if (hash == -1) {
|
||||
if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) {
|
||||
set_unhashable_type(key);
|
||||
@@ -3039,7 +3039,7 @@ PySet_Contains(PyObject *anyset, PyObject *key)
|
||||
}
|
||||
|
||||
PySetObject *so = (PySetObject *)anyset;
|
||||
Py_hash_t hash = _PyObject_HashFast(key);
|
||||
Py_hash_t hash = PyObject_Hash(key);
|
||||
if (hash == -1) {
|
||||
set_unhashable_type(key);
|
||||
return -1;
|
||||
|
||||
@@ -3793,7 +3793,7 @@ solid_base(PyTypeObject *type)
|
||||
// or when __bases__ is re-assigned. Since the slots are read without atomic
|
||||
// operations and without locking, we can only safely update them while the
|
||||
// world is stopped. However, with the world stopped, we are very limited on
|
||||
// which APIs can be safely used. For example, calling _PyObject_HashFast()
|
||||
// which APIs can be safely used. For example, calling _PyObject_HashDictKey()
|
||||
// or _PyDict_GetItemRef_KnownHash() are not safe and can potentially cause
|
||||
// deadlocks. Hashing can be re-entrant and _PyDict_GetItemRef_KnownHash can
|
||||
// acquire a lock if the dictionary is not owned by the current thread, to
|
||||
@@ -6134,7 +6134,7 @@ PyObject_GetItemData(PyObject *obj)
|
||||
static int
|
||||
find_name_in_mro(PyTypeObject *type, PyObject *name, _PyStackRef *out)
|
||||
{
|
||||
Py_hash_t hash = _PyObject_HashFast(name);
|
||||
Py_hash_t hash = _PyObject_HashDictKey(name);
|
||||
if (hash == -1) {
|
||||
PyErr_Clear();
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user