@@ -8,6 +8,7 @@ extern "C" {
88# error "this header requires Py_BUILD_CORE define"
99#endif
1010
11+ #include "pycore_object.h" // _PyObject_GC_IS_TRACKED
1112#include "pycore_structs.h" // _PyStackRef
1213
1314extern void _PyTuple_MaybeUntrack (PyObject * );
@@ -32,6 +33,42 @@ typedef struct {
3233 PyTupleObject * it_seq ; /* Set to NULL when iterator is exhausted */
3334} _PyTupleIterObject ;
3435
36+ #define _PyTuple_RESET_HASH_CACHE (op ) \
37+ do { \
38+ assert(op != NULL); \
39+ _PyTuple_CAST(op)->ob_hash = -1; \
40+ } while (0)
41+
42+ /* bpo-42536: If reusing a tuple object, this should be called to re-track it
43+ with the garbage collector and reset its hash cache. */
44+ static inline void
45+ _PyTuple_Recycle (PyObject * op )
46+ {
47+ _PyTuple_RESET_HASH_CACHE (op );
48+ if (!_PyObject_GC_IS_TRACKED (op )) {
49+ _PyObject_GC_TRACK (op );
50+ }
51+ }
52+
53+ /* Below are the official constants from the xxHash specification. Optimizing
54+ compilers should emit a single "rotate" instruction for the
55+ _PyTuple_HASH_XXROTATE() expansion. If that doesn't happen for some important
56+ platform, the macro could be changed to expand to a platform-specific rotate
57+ spelling instead.
58+ */
59+ #if SIZEOF_PY_UHASH_T > 4
60+ #define _PyTuple_HASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
61+ #define _PyTuple_HASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
62+ #define _PyTuple_HASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
63+ #define _PyTuple_HASH_XXROTATE (x ) ((x << 31) | (x >> 33)) /* Rotate left 31 bits */
64+ #else
65+ #define _PyTuple_HASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
66+ #define _PyTuple_HASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
67+ #define _PyTuple_HASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
68+ #define _PyTuple_HASH_XXROTATE (x ) ((x << 13) | (x >> 19)) /* Rotate left 13 bits */
69+ #endif
70+ #define _PyTuple_HASH_EMPTY (_PyTuple_HASH_XXPRIME_5 + (_PyTuple_HASH_XXPRIME_5 ^ 3527539UL))
71+
3572#ifdef __cplusplus
3673}
3774#endif
0 commit comments