@@ -43,7 +43,8 @@ class object "PyObject *" "&PyBaseObject_Type"
43
43
& ((1 << MCACHE_SIZE_EXP) - 1))
44
44
45
45
#define MCACHE_HASH_METHOD (type , name ) \
46
- MCACHE_HASH((type)->tp_version_tag, ((Py_ssize_t)(name)) >> 3)
46
+ MCACHE_HASH(FT_ATOMIC_LOAD_UINT32_RELAXED((type)->tp_version_tag), \
47
+ ((Py_ssize_t)(name)) >> 3)
47
48
#define MCACHE_CACHEABLE_NAME (name ) \
48
49
PyUnicode_CheckExact(name) && \
49
50
PyUnicode_IS_READY(name) && \
@@ -907,7 +908,7 @@ type_modified_unlocked(PyTypeObject *type)
907
908
}
908
909
909
910
type -> tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG ;
910
- type -> tp_version_tag = 0 ; /* 0 is not a valid version tag */
911
+ FT_ATOMIC_STORE_UINT32_RELAXED ( type -> tp_version_tag , 0 ) ; /* 0 is not a valid version tag */
911
912
if (PyType_HasFeature (type , Py_TPFLAGS_HEAPTYPE )) {
912
913
// This field *must* be invalidated if the type is modified (see the
913
914
// comment on struct _specialization_cache):
@@ -984,7 +985,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
984
985
clear :
985
986
assert (!(type -> tp_flags & _Py_TPFLAGS_STATIC_BUILTIN ));
986
987
type -> tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG ;
987
- type -> tp_version_tag = 0 ; /* 0 is not a valid version tag */
988
+ FT_ATOMIC_STORE_UINT32_RELAXED ( type -> tp_version_tag , 0 ) ; /* 0 is not a valid version tag */
988
989
if (PyType_HasFeature (type , Py_TPFLAGS_HEAPTYPE )) {
989
990
// This field *must* be invalidated if the type is modified (see the
990
991
// comment on struct _specialization_cache):
@@ -1020,7 +1021,8 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
1020
1021
/* We have run out of version numbers */
1021
1022
return 0 ;
1022
1023
}
1023
- type -> tp_version_tag = NEXT_GLOBAL_VERSION_TAG ++ ;
1024
+ FT_ATOMIC_STORE_UINT32_RELAXED (type -> tp_version_tag ,
1025
+ NEXT_GLOBAL_VERSION_TAG ++ );
1024
1026
assert (type -> tp_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
1025
1027
}
1026
1028
else {
@@ -1029,7 +1031,8 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
1029
1031
/* We have run out of version numbers */
1030
1032
return 0 ;
1031
1033
}
1032
- type -> tp_version_tag = NEXT_VERSION_TAG (interp )++ ;
1034
+ FT_ATOMIC_STORE_UINT32_RELAXED (type -> tp_version_tag ,
1035
+ NEXT_VERSION_TAG (interp )++ );
1033
1036
assert (type -> tp_version_tag != 0 );
1034
1037
}
1035
1038
@@ -5047,7 +5050,9 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
5047
5050
// synchronize-with other writing threads by doing an acquire load on the sequence
5048
5051
while (1 ) {
5049
5052
int sequence = _PySeqLock_BeginRead (& entry -> sequence );
5050
- if (_Py_atomic_load_uint32_relaxed (& entry -> version ) == type -> tp_version_tag &&
5053
+ uint32_t entry_version = _Py_atomic_load_uint32_relaxed (& entry -> version );
5054
+ uint32_t type_version = _Py_atomic_load_uint32_relaxed (& type -> tp_version_tag );
5055
+ if (entry_version == type_version &&
5051
5056
_Py_atomic_load_ptr_relaxed (& entry -> name ) == name ) {
5052
5057
assert (_PyType_HasFeature (type , Py_TPFLAGS_VALID_VERSION_TAG ));
5053
5058
OBJECT_STAT_INC_COND (type_cache_hits , !is_dunder_name (name ));
0 commit comments