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().
This commit is contained in:
Victor Stinner 2023-12-06 15:09:22 +01:00 committed by GitHub
parent f8852634ed
commit 828451dfde
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 103 additions and 22 deletions

View file

@ -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);

View file

@ -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);