summaryrefslogtreecommitdiffstats
path: root/Include
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2023-12-06 14:09:22 (GMT)
committerGitHub <noreply@github.com>2023-12-06 14:09:22 (GMT)
commit828451dfde324f9499ffebc023a22b84dc5a125b (patch)
treeceee17c26f9c9238b602ef9156e6eb8530d032f1 /Include
parentf8852634edf1232ac1aa4561e34796b52f9f7aa2 (diff)
downloadcpython-828451dfde324f9499ffebc023a22b84dc5a125b.zip
cpython-828451dfde324f9499ffebc023a22b84dc5a125b.tar.gz
cpython-828451dfde324f9499ffebc023a22b84dc5a125b.tar.bz2
gh-111545: Add Py_HashPointer() function (#112096)
* Implement _Py_HashPointerRaw() as a static inline function. * Add Py_HashPointer() tests to test_capi.test_hash. * Keep _Py_HashPointer() function as an alias to Py_HashPointer().
Diffstat (limited to 'Include')
-rw-r--r--Include/cpython/pyhash.h6
-rw-r--r--Include/internal/pycore_pyhash.h16
2 files changed, 19 insertions, 3 deletions
diff --git a/Include/cpython/pyhash.h b/Include/cpython/pyhash.h
index 6f7113d..396c208 100644
--- a/Include/cpython/pyhash.h
+++ b/Include/cpython/pyhash.h
@@ -21,7 +21,9 @@
/* Helpers for hash functions */
PyAPI_FUNC(Py_hash_t) _Py_HashDouble(PyObject *, double);
-PyAPI_FUNC(Py_hash_t) _Py_HashPointer(const void*);
+
+// Kept for backward compatibility
+#define _Py_HashPointer Py_HashPointer
/* hash function definition */
@@ -33,3 +35,5 @@ typedef struct {
} PyHash_FuncDef;
PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void);
+
+PyAPI_FUNC(Py_hash_t) Py_HashPointer(const void *ptr);
diff --git a/Include/internal/pycore_pyhash.h b/Include/internal/pycore_pyhash.h
index c3b72d9..0ce0890 100644
--- a/Include/internal/pycore_pyhash.h
+++ b/Include/internal/pycore_pyhash.h
@@ -5,8 +5,20 @@
# error "this header requires Py_BUILD_CORE define"
#endif
-// Similar to _Py_HashPointer(), but don't replace -1 with -2
-extern Py_hash_t _Py_HashPointerRaw(const void*);
+// Similar to Py_HashPointer(), but don't replace -1 with -2.
+static inline Py_hash_t
+_Py_HashPointerRaw(const void *ptr)
+{
+ uintptr_t x = (uintptr_t)ptr;
+ Py_BUILD_ASSERT(sizeof(x) == sizeof(ptr));
+
+ // Bottom 3 or 4 bits are likely to be 0; rotate x by 4 to the right
+ // to avoid excessive hash collisions for dicts and sets.
+ x = (x >> 4) | (x << (8 * sizeof(uintptr_t) - 4));
+
+ Py_BUILD_ASSERT(sizeof(x) == sizeof(Py_hash_t));
+ return (Py_hash_t)x;
+}
// Export for '_datetime' shared extension
PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void*, Py_ssize_t);