@@ -1236,14 +1236,39 @@ PyDict_PopString(PyObject *dict, const char *key, PyObject **result)
12361236
12371237
12381238// gh-111545 added Py_HashPointer() to Python 3.13
1239- #if PY_VERSION_HEX < _Py_PACK_VERSION(3, 13) && ! defined(Py_LIMITED_API)
1239+ #if PY_VERSION_HEX < _Py_PACK_VERSION(3, 13) || defined(Py_LIMITED_API)
12401240static inline Py_hash_t Py_HashPointer (const void *ptr)
12411241{
1242- #if PY_VERSION_HEX >= _Py_PACK_VERSION(3, 9) && !defined(PYPY_VERSION)
1242+ #if PY_VERSION_HEX >= _Py_PACK_VERSION(3, 9) && !defined(PYPY_VERSION) && !defined(Py_LIMITED_API)
12431243 return _Py_HashPointer (ptr);
1244- #else
1244+ #elif !defined(Py_LIMITED_API)
1245+ // PyPy _Py_HashPointer() argument type is "void*", not "const void*"
12451246 return _Py_HashPointer (_Py_CAST (void *, ptr));
1247+ #else
1248+ // Limited C API implementation
1249+ uintptr_t x = (uintptr_t )ptr;
1250+ Py_BUILD_ASSERT (sizeof (x) == sizeof (ptr));
1251+
1252+ // Bottom 3 or 4 bits are likely to be 0; rotate x by 4 to the right
1253+ // to avoid excessive hash collisions for dicts and sets.
1254+ x = (x >> 4 ) | (x << (8 * sizeof (uintptr_t ) - 4 ));
1255+
1256+ if (x == (uintptr_t )-1 ) {
1257+ x = (uintptr_t )-2 ;
1258+ }
1259+
1260+ Py_BUILD_ASSERT (sizeof (x) == sizeof (Py_hash_t));
1261+ return (Py_hash_t)x;
1262+ #endif
1263+ }
12461264#endif
1265+
1266+
1267+ #if PY_VERSION_HEX < _Py_PACK_VERSION(3, 13) || defined(Py_LIMITED_API)
1268+ Py_hash_t
1269+ PyObject_GenericHash (PyObject *obj)
1270+ {
1271+ return Py_HashPointer (obj);
12471272}
12481273#endif
12491274
0 commit comments