summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorMichael Droettboom <mdboom@gmail.com>2025-03-27 13:57:06 (GMT)
committerGitHub <noreply@github.com>2025-03-27 13:57:06 (GMT)
commit8614f86b7163b1c39798b481902dbb511292a537 (patch)
tree2bf6a46b432df3d6bf01a4176f3a614a01c48566 /Objects
parentcf5e438c0297954c4411c1c3ae4ba67a48b134ea (diff)
downloadcpython-8614f86b7163b1c39798b481902dbb511292a537.zip
cpython-8614f86b7163b1c39798b481902dbb511292a537.tar.gz
cpython-8614f86b7163b1c39798b481902dbb511292a537.tar.bz2
gh-131525: Cache the result of tuple_hash (#131529)
* gh-131525: Cache the result of tuple_hash * Fix debug builds * Add blurb * Fix formatting * Pre-compute empty tuple singleton * Mostly set the cache within tuple_alloc * Fixes for TSAN * Pre-compute empty tuple singleton * Fix for 32-bit platforms * Assert that op != NULL in _PyTuple_RESET_HASH_CACHE * Use FT_ATOMIC_STORE_SSIZE_RELAXED macro * Update Include/internal/pycore_tuple.h Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> * Fix alignment * atomic load * Update Objects/tupleobject.c Co-authored-by: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> --------- Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Chris Eibl <138194463+chris-eibl@users.noreply.github.com>
Diffstat (limited to 'Objects')
-rw-r--r--Objects/clinic/bytearrayobject.c.h16
-rw-r--r--Objects/clinic/bytesobject.c.h16
-rw-r--r--Objects/clinic/codeobject.c.h6
-rw-r--r--Objects/clinic/complexobject.c.h4
-rw-r--r--Objects/clinic/descrobject.c.h6
-rw-r--r--Objects/clinic/enumobject.c.h4
-rw-r--r--Objects/clinic/funcobject.c.h4
-rw-r--r--Objects/clinic/listobject.c.h4
-rw-r--r--Objects/clinic/longobject.c.h8
-rw-r--r--Objects/clinic/memoryobject.c.h12
-rw-r--r--Objects/clinic/moduleobject.c.h4
-rw-r--r--Objects/clinic/odictobject.c.h12
-rw-r--r--Objects/clinic/structseq.c.h4
-rw-r--r--Objects/clinic/typevarobject.c.h14
-rw-r--r--Objects/clinic/unicodeobject.c.h16
-rw-r--r--Objects/dictobject.c9
-rw-r--r--Objects/enumobject.c9
-rw-r--r--Objects/odictobject.c5
-rw-r--r--Objects/stringlib/clinic/transmogrify.h.h4
-rw-r--r--Objects/structseq.c1
-rw-r--r--Objects/tupleobject.c50
21 files changed, 151 insertions, 57 deletions
diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h
index 262438f..ffb45ad 100644
--- a/Objects/clinic/bytearrayobject.c.h
+++ b/Objects/clinic/bytearrayobject.c.h
@@ -24,9 +24,11 @@ bytearray___init__(PyObject *self, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(source), &_Py_ID(encoding), &_Py_ID(errors), },
};
#undef NUM_KEYWORDS
@@ -658,9 +660,11 @@ bytearray_translate(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyO
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(delete), },
};
#undef NUM_KEYWORDS
@@ -850,9 +854,11 @@ bytearray_split(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObjec
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sep), &_Py_ID(maxsplit), },
};
#undef NUM_KEYWORDS
@@ -1005,9 +1011,11 @@ bytearray_rsplit(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sep), &_Py_ID(maxsplit), },
};
#undef NUM_KEYWORDS
@@ -1420,9 +1428,11 @@ bytearray_decode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(encoding), &_Py_ID(errors), },
};
#undef NUM_KEYWORDS
@@ -1545,9 +1555,11 @@ bytearray_splitlines(PyObject *self, PyObject *const *args, Py_ssize_t nargs, Py
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(keepends), },
};
#undef NUM_KEYWORDS
@@ -1653,9 +1665,11 @@ bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sep), &_Py_ID(bytes_per_sep), },
};
#undef NUM_KEYWORDS
@@ -1782,4 +1796,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_sizeof_impl((PyByteArrayObject *)self);
}
-/*[clinic end generated code: output=0d1d1abc8b701ad9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=be6d28193bc96a2c input=a9049054013a1b77]*/
diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h
index f1f16de..00cf13d 100644
--- a/Objects/clinic/bytesobject.c.h
+++ b/Objects/clinic/bytesobject.c.h
@@ -57,9 +57,11 @@ bytes_split(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *k
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sep), &_Py_ID(maxsplit), },
};
#undef NUM_KEYWORDS
@@ -224,9 +226,11 @@ bytes_rsplit(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sep), &_Py_ID(maxsplit), },
};
#undef NUM_KEYWORDS
@@ -693,9 +697,11 @@ bytes_translate(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObjec
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(delete), },
};
#undef NUM_KEYWORDS
@@ -1055,9 +1061,11 @@ bytes_decode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(encoding), &_Py_ID(errors), },
};
#undef NUM_KEYWORDS
@@ -1150,9 +1158,11 @@ bytes_splitlines(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(keepends), },
};
#undef NUM_KEYWORDS
@@ -1256,9 +1266,11 @@ bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sep), &_Py_ID(bytes_per_sep), },
};
#undef NUM_KEYWORDS
@@ -1319,9 +1331,11 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(source), &_Py_ID(encoding), &_Py_ID(errors), },
};
#undef NUM_KEYWORDS
@@ -1397,4 +1411,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=c607024162df3ea8 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=08b9507244f73638 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/codeobject.c.h b/Objects/clinic/codeobject.c.h
index 2184742..0cd6e0b 100644
--- a/Objects/clinic/codeobject.c.h
+++ b/Objects/clinic/codeobject.c.h
@@ -183,9 +183,11 @@ code_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(co_argcount), &_Py_ID(co_posonlyargcount), &_Py_ID(co_kwonlyargcount), &_Py_ID(co_nlocals), &_Py_ID(co_stacksize), &_Py_ID(co_flags), &_Py_ID(co_firstlineno), &_Py_ID(co_code), &_Py_ID(co_consts), &_Py_ID(co_names), &_Py_ID(co_varnames), &_Py_ID(co_freevars), &_Py_ID(co_cellvars), &_Py_ID(co_filename), &_Py_ID(co_name), &_Py_ID(co_qualname), &_Py_ID(co_linetable), &_Py_ID(co_exceptiontable), },
};
#undef NUM_KEYWORDS
@@ -430,9 +432,11 @@ code__varname_from_oparg(PyObject *self, PyObject *const *args, Py_ssize_t nargs
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(oparg), },
};
#undef NUM_KEYWORDS
@@ -466,4 +470,4 @@ code__varname_from_oparg(PyObject *self, PyObject *const *args, Py_ssize_t nargs
exit:
return return_value;
}
-/*[clinic end generated code: output=73861c79e93aaee5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c5c6e40fc357defe input=a9049054013a1b77]*/
diff --git a/Objects/clinic/complexobject.c.h b/Objects/clinic/complexobject.c.h
index 2988664..c730338 100644
--- a/Objects/clinic/complexobject.c.h
+++ b/Objects/clinic/complexobject.c.h
@@ -114,9 +114,11 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(real), &_Py_ID(imag), },
};
#undef NUM_KEYWORDS
@@ -183,4 +185,4 @@ complex_from_number(PyObject *type, PyObject *number)
return return_value;
}
-/*[clinic end generated code: output=307531cd6d6e7544 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=05d2ff43fc409733 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/descrobject.c.h b/Objects/clinic/descrobject.c.h
index 2f96adb..a0cfbec 100644
--- a/Objects/clinic/descrobject.c.h
+++ b/Objects/clinic/descrobject.c.h
@@ -27,9 +27,11 @@ mappingproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(mapping), },
};
#undef NUM_KEYWORDS
@@ -114,9 +116,11 @@ property_init(PyObject *self, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(fget), &_Py_ID(fset), &_Py_ID(fdel), &_Py_ID(doc), },
};
#undef NUM_KEYWORDS
@@ -175,4 +179,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=2f43f9297a36aa40 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=2e8df497abc4f915 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/enumobject.c.h b/Objects/clinic/enumobject.c.h
index 998b2eb..29ff11e 100644
--- a/Objects/clinic/enumobject.c.h
+++ b/Objects/clinic/enumobject.c.h
@@ -36,9 +36,11 @@ enum_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(iterable), &_Py_ID(start), },
};
#undef NUM_KEYWORDS
@@ -108,4 +110,4 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=2e339ade8bedb3a0 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=3300305b351674d3 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/funcobject.c.h b/Objects/clinic/funcobject.c.h
index efc579d..fec7431 100644
--- a/Objects/clinic/funcobject.c.h
+++ b/Objects/clinic/funcobject.c.h
@@ -215,9 +215,11 @@ func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(code), &_Py_ID(globals), &_Py_ID(name), &_Py_ID(argdefs), &_Py_ID(closure), &_Py_ID(kwdefaults), },
};
#undef NUM_KEYWORDS
@@ -288,4 +290,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=3cdce22867efe617 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=12cb900088d41bdb input=a9049054013a1b77]*/
diff --git a/Objects/clinic/listobject.c.h b/Objects/clinic/listobject.c.h
index 3f4e7e7..26ba5b9 100644
--- a/Objects/clinic/listobject.c.h
+++ b/Objects/clinic/listobject.c.h
@@ -224,9 +224,11 @@ list_sort(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(key), &_Py_ID(reverse), },
};
#undef NUM_KEYWORDS
@@ -466,4 +468,4 @@ list___reversed__(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return list___reversed___impl((PyListObject *)self);
}
-/*[clinic end generated code: output=bc45e43a621ac833 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ae13fc2b56dc27c2 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/longobject.c.h b/Objects/clinic/longobject.c.h
index 9043ab3..a236a32 100644
--- a/Objects/clinic/longobject.c.h
+++ b/Objects/clinic/longobject.c.h
@@ -22,9 +22,11 @@ long_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(base), },
};
#undef NUM_KEYWORDS
@@ -291,9 +293,11 @@ int_to_bytes(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(length), &_Py_ID(byteorder), &_Py_ID(signed), },
};
#undef NUM_KEYWORDS
@@ -403,9 +407,11 @@ int_from_bytes(PyObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(bytes), &_Py_ID(byteorder), &_Py_ID(signed), },
};
#undef NUM_KEYWORDS
@@ -479,4 +485,4 @@ int_is_integer(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return int_is_integer_impl(self);
}
-/*[clinic end generated code: output=591cffa2b80b5184 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=d23f8ce5bdf08a30 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/memoryobject.c.h b/Objects/clinic/memoryobject.c.h
index b3240c7..28cfd1a 100644
--- a/Objects/clinic/memoryobject.c.h
+++ b/Objects/clinic/memoryobject.c.h
@@ -27,9 +27,11 @@ memoryview(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(object), },
};
#undef NUM_KEYWORDS
@@ -85,9 +87,11 @@ memoryview__from_flags(PyObject *type, PyObject *const *args, Py_ssize_t nargs,
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(object), &_Py_ID(flags), },
};
#undef NUM_KEYWORDS
@@ -165,9 +169,11 @@ memoryview_cast(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObjec
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(format), &_Py_ID(shape), },
};
#undef NUM_KEYWORDS
@@ -274,9 +280,11 @@ memoryview_tobytes(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyOb
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(order), },
};
#undef NUM_KEYWORDS
@@ -370,9 +378,11 @@ memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sep), &_Py_ID(bytes_per_sep), },
};
#undef NUM_KEYWORDS
@@ -486,4 +496,4 @@ skip_optional:
exit:
return return_value;
}
-/*[clinic end generated code: output=ae3414e9311c02fb input=a9049054013a1b77]*/
+/*[clinic end generated code: output=154f4c04263ccb24 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/moduleobject.c.h b/Objects/clinic/moduleobject.c.h
index 5535a2f..455b883 100644
--- a/Objects/clinic/moduleobject.c.h
+++ b/Objects/clinic/moduleobject.c.h
@@ -29,9 +29,11 @@ module___init__(PyObject *self, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(name), &_Py_ID(doc), },
};
#undef NUM_KEYWORDS
@@ -75,4 +77,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=d7da56d5c2eb6d30 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=523344ad09ab2ea1 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/odictobject.c.h b/Objects/clinic/odictobject.c.h
index 65eee37..e71c29a 100644
--- a/Objects/clinic/odictobject.c.h
+++ b/Objects/clinic/odictobject.c.h
@@ -30,9 +30,11 @@ OrderedDict_fromkeys(PyObject *type, PyObject *const *args, Py_ssize_t nargs, Py
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(iterable), &_Py_ID(value), },
};
#undef NUM_KEYWORDS
@@ -96,9 +98,11 @@ OrderedDict_setdefault(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(key), &_Py_ID(default), },
};
#undef NUM_KEYWORDS
@@ -163,9 +167,11 @@ OrderedDict_pop(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObjec
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(key), &_Py_ID(default), },
};
#undef NUM_KEYWORDS
@@ -228,9 +234,11 @@ OrderedDict_popitem(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyO
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(last), },
};
#undef NUM_KEYWORDS
@@ -294,9 +302,11 @@ OrderedDict_move_to_end(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(key), &_Py_ID(last), },
};
#undef NUM_KEYWORDS
@@ -337,4 +347,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=6f84d0649fcd0c1f input=a9049054013a1b77]*/
+/*[clinic end generated code: output=7d8206823bb1f419 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/structseq.c.h b/Objects/clinic/structseq.c.h
index 0afb21a..9642b48 100644
--- a/Objects/clinic/structseq.c.h
+++ b/Objects/clinic/structseq.c.h
@@ -21,9 +21,11 @@ structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sequence), &_Py_ID(dict), },
};
#undef NUM_KEYWORDS
@@ -63,4 +65,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=ef2406240ce0ad3f input=a9049054013a1b77]*/
+/*[clinic end generated code: output=112d59f5e98d652b input=a9049054013a1b77]*/
diff --git a/Objects/clinic/typevarobject.c.h b/Objects/clinic/typevarobject.c.h
index 87e0fd7..9ae2f51 100644
--- a/Objects/clinic/typevarobject.c.h
+++ b/Objects/clinic/typevarobject.c.h
@@ -30,9 +30,11 @@ typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(default), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), },
};
#undef NUM_KEYWORDS
@@ -226,9 +228,11 @@ paramspecargs_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(origin), },
};
#undef NUM_KEYWORDS
@@ -281,9 +285,11 @@ paramspeckwargs_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(origin), },
};
#undef NUM_KEYWORDS
@@ -339,9 +345,11 @@ paramspec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(default), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), },
};
#undef NUM_KEYWORDS
@@ -528,9 +536,11 @@ typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(name), &_Py_ID(default), },
};
#undef NUM_KEYWORDS
@@ -697,9 +707,11 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(name), &_Py_ID(value), &_Py_ID(type_params), },
};
#undef NUM_KEYWORDS
@@ -745,4 +757,4 @@ skip_optional_kwonly:
exit:
return return_value;
}
-/*[clinic end generated code: output=d0cdf708e2e315a4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=9dad71445e079303 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h
index c299cf2..1819fba 100644
--- a/Objects/clinic/unicodeobject.c.h
+++ b/Objects/clinic/unicodeobject.c.h
@@ -222,9 +222,11 @@ unicode_encode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(encoding), &_Py_ID(errors), },
};
#undef NUM_KEYWORDS
@@ -316,9 +318,11 @@ unicode_expandtabs(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyOb
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(tabsize), },
};
#undef NUM_KEYWORDS
@@ -934,9 +938,11 @@ unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObjec
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(count), },
};
#undef NUM_KEYWORDS
@@ -1260,9 +1266,11 @@ unicode_split(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sep), &_Py_ID(maxsplit), },
};
#undef NUM_KEYWORDS
@@ -1383,9 +1391,11 @@ unicode_rsplit(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(sep), &_Py_ID(maxsplit), },
};
#undef NUM_KEYWORDS
@@ -1465,9 +1475,11 @@ unicode_splitlines(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyOb
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(keepends), },
};
#undef NUM_KEYWORDS
@@ -1816,9 +1828,11 @@ unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(object), &_Py_ID(encoding), &_Py_ID(errors), },
};
#undef NUM_KEYWORDS
@@ -1894,4 +1908,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=81d703159f829f1f input=a9049054013a1b77]*/
+/*[clinic end generated code: output=238917fe66120bde input=a9049054013a1b77]*/
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index f302fc5..25ad525 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -129,6 +129,7 @@ As a consequence of this, split keys have a maximum size of 16.
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_setobject.h" // _PySet_NextEntry()
+#include "pycore_tuple.h" // _PyTuple_Recycle()
#include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal()
#include "stringlib/eq.h" // unicode_eq()
@@ -5624,9 +5625,7 @@ dictiter_iternextitem(PyObject *self)
Py_DECREF(oldvalue);
// bpo-42536: The GC may have untracked this result tuple. Since we're
// recycling it, make sure it's tracked again:
- if (!_PyObject_GC_IS_TRACKED(result)) {
- _PyObject_GC_TRACK(result);
- }
+ _PyTuple_Recycle(result);
}
else {
result = PyTuple_New(2);
@@ -5749,9 +5748,7 @@ dictreviter_iter_lock_held(PyDictObject *d, PyObject *self)
Py_DECREF(oldvalue);
// bpo-42536: The GC may have untracked this result tuple. Since
// we're recycling it, make sure it's tracked again:
- if (!_PyObject_GC_IS_TRACKED(result)) {
- _PyObject_GC_TRACK(result);
- }
+ _PyTuple_Recycle(result);
}
else {
result = PyTuple_New(2);
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index f5d9d41..1123b14 100644
--- a/Objects/enumobject.c
+++ b/Objects/enumobject.c
@@ -6,6 +6,7 @@
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_GC_TRACK()
#include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString
+#include "pycore_tuple.h" // _PyTuple_Recycle()
#include "clinic/enumobject.c.h"
@@ -220,9 +221,7 @@ enum_next_long(enumobject *en, PyObject* next_item)
Py_DECREF(old_item);
// bpo-42536: The GC may have untracked this result tuple. Since we're
// recycling it, make sure it's tracked again:
- if (!_PyObject_GC_IS_TRACKED(result)) {
- _PyObject_GC_TRACK(result);
- }
+ _PyTuple_Recycle(result);
return result;
}
result = PyTuple_New(2);
@@ -272,9 +271,7 @@ enum_next(PyObject *op)
Py_DECREF(old_item);
// bpo-42536: The GC may have untracked this result tuple. Since we're
// recycling it, make sure it's tracked again:
- if (!_PyObject_GC_IS_TRACKED(result)) {
- _PyObject_GC_TRACK(result);
- }
+ _PyTuple_Recycle(result);
return result;
}
result = PyTuple_New(2);
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index c112622..1412acb 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -471,6 +471,7 @@ later:
#include "pycore_dict.h" // _Py_dict_lookup()
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
+#include "pycore_tuple.h" // _PyTuple_Recycle()
#include <stddef.h> // offsetof()
#include "clinic/odictobject.c.h"
@@ -1762,9 +1763,7 @@ odictiter_iternext(PyObject *op)
Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
// bpo-42536: The GC may have untracked this result tuple. Since we're
// recycling it, make sure it's tracked again:
- if (!_PyObject_GC_IS_TRACKED(result)) {
- _PyObject_GC_TRACK(result);
- }
+ _PyTuple_Recycle(result);
}
else {
result = PyTuple_New(2);
diff --git a/Objects/stringlib/clinic/transmogrify.h.h b/Objects/stringlib/clinic/transmogrify.h.h
index 5b82c2d..588fc10 100644
--- a/Objects/stringlib/clinic/transmogrify.h.h
+++ b/Objects/stringlib/clinic/transmogrify.h.h
@@ -33,9 +33,11 @@ stringlib_expandtabs(PyObject *self, PyObject *const *args, Py_ssize_t nargs, Py
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
.ob_item = { &_Py_ID(tabsize), },
};
#undef NUM_KEYWORDS
@@ -322,4 +324,4 @@ stringlib_zfill(PyObject *self, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=0e24a10bac3ec053 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=8363b4b6cdaad556 input=a9049054013a1b77]*/
diff --git a/Objects/structseq.c b/Objects/structseq.c
index a1b6dd6..c05bcde 100644
--- a/Objects/structseq.c
+++ b/Objects/structseq.c
@@ -73,6 +73,7 @@ PyStructSequence_New(PyTypeObject *type)
obj = PyObject_GC_NewVar(PyStructSequence, type, size);
if (obj == NULL)
return NULL;
+ _PyTuple_RESET_HASH_CACHE(obj);
/* Hack the size of the variable object, so invisible fields don't appear
to Python code. */
Py_SET_SIZE(obj, vsize);
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 78ee3fa..737c4e6 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -45,6 +45,7 @@ tuple_alloc(Py_ssize_t size)
if (index < PyTuple_MAXSAVESIZE) {
PyTupleObject *op = _Py_FREELIST_POP(PyTupleObject, tuples[index]);
if (op != NULL) {
+ _PyTuple_RESET_HASH_CACHE(op);
return op;
}
}
@@ -53,7 +54,11 @@ tuple_alloc(Py_ssize_t size)
sizeof(PyObject *))) / sizeof(PyObject *)) {
return (PyTupleObject *)PyErr_NoMemory();
}
- return PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
+ PyTupleObject *result = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
+ if (result != NULL) {
+ _PyTuple_RESET_HASH_CACHE(result);
+ }
+ return result;
}
// The empty tuple singleton is not tracked by the GC.
@@ -296,50 +301,41 @@ error:
For the xxHash specification, see
https://github.com/Cyan4973/xxHash/blob/master/doc/xxhash_spec.md
- Below are the official constants from the xxHash specification. Optimizing
- compilers should emit a single "rotate" instruction for the
- _PyHASH_XXROTATE() expansion. If that doesn't happen for some important
- platform, the macro could be changed to expand to a platform-specific rotate
- spelling instead.
+ The constants for the hash function are defined in pycore_tuple.h.
*/
-#if SIZEOF_PY_UHASH_T > 4
-#define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
-#define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
-#define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
-#define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33)) /* Rotate left 31 bits */
-#else
-#define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
-#define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
-#define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
-#define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19)) /* Rotate left 13 bits */
-#endif
-/* Tests have shown that it's not worth to cache the hash value, see
- https://bugs.python.org/issue9685 */
static Py_hash_t
tuple_hash(PyObject *op)
{
PyTupleObject *v = _PyTuple_CAST(op);
+
+ Py_uhash_t acc = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->ob_hash);
+ if (acc != (Py_uhash_t)-1) {
+ return acc;
+ }
+
Py_ssize_t len = Py_SIZE(v);
PyObject **item = v->ob_item;
-
- Py_uhash_t acc = _PyHASH_XXPRIME_5;
+ acc = _PyTuple_HASH_XXPRIME_5;
for (Py_ssize_t i = 0; i < len; i++) {
Py_uhash_t lane = PyObject_Hash(item[i]);
if (lane == (Py_uhash_t)-1) {
return -1;
}
- acc += lane * _PyHASH_XXPRIME_2;
- acc = _PyHASH_XXROTATE(acc);
- acc *= _PyHASH_XXPRIME_1;
+ acc += lane * _PyTuple_HASH_XXPRIME_2;
+ acc = _PyTuple_HASH_XXROTATE(acc);
+ acc *= _PyTuple_HASH_XXPRIME_1;
}
/* Add input length, mangled to keep the historical value of hash(()). */
- acc += len ^ (_PyHASH_XXPRIME_5 ^ 3527539UL);
+ acc += len ^ (_PyTuple_HASH_XXPRIME_5 ^ 3527539UL);
if (acc == (Py_uhash_t)-1) {
- return 1546275796;
+ acc = 1546275796;
}
+
+ FT_ATOMIC_STORE_SSIZE_RELAXED(v->ob_hash, acc);
+
return acc;
}
@@ -764,6 +760,8 @@ tuple_subtype_new(PyTypeObject *type, PyObject *iterable)
}
Py_DECREF(tmp);
+ _PyTuple_RESET_HASH_CACHE(newobj);
+
// Don't track if a subclass tp_alloc is PyType_GenericAlloc()
if (!_PyObject_GC_IS_TRACKED(newobj)) {
_PyObject_GC_TRACK(newobj);