@@ -54,7 +54,6 @@ class object "PyObject *" "&PyBaseObject_Type"
54
54
PyUnicode_CheckExact(name) && \
55
55
(PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE)
56
56
57
- #define NEXT_GLOBAL_VERSION_TAG _PyRuntime.types.next_version_tag
58
57
#define NEXT_VERSION_TAG (interp ) \
59
58
(interp)->types.next_version_tag
60
59
@@ -157,8 +156,8 @@ static_ext_type_lookup(PyInterpreterState *interp, size_t index,
157
156
assert (index < _Py_MAX_MANAGED_STATIC_EXT_TYPES );
158
157
159
158
size_t full_index = index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES ;
160
- int64_t interp_count =
161
- _PyRuntime .types .managed_static .types [full_index ].interp_count ;
159
+ int64_t interp_count = _Py_atomic_load_int64 (
160
+ & _PyRuntime .types .managed_static .types [full_index ].interp_count ) ;
162
161
assert ((interp_count == 0 ) ==
163
162
(_PyRuntime .types .managed_static .types [full_index ].type == NULL ));
164
163
* p_interp_count = interp_count ;
@@ -235,7 +234,7 @@ managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self,
235
234
: index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES ;
236
235
237
236
assert ((initial == 1 ) ==
238
- (_PyRuntime .types .managed_static .types [full_index ].interp_count == 0 ));
237
+ (_Py_atomic_load_int64 ( & _PyRuntime .types .managed_static .types [full_index ].interp_count ) == 0 ));
239
238
(void )_Py_atomic_add_int64 (
240
239
& _PyRuntime .types .managed_static .types [full_index ].interp_count , 1 );
241
240
@@ -284,7 +283,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
284
283
: & (interp -> types .for_extensions .initialized [index ]);
285
284
assert (state != NULL );
286
285
287
- assert (_PyRuntime .types .managed_static .types [full_index ].interp_count > 0 );
286
+ assert (_Py_atomic_load_int64 ( & _PyRuntime .types .managed_static .types [full_index ].interp_count ) > 0 );
288
287
assert (_PyRuntime .types .managed_static .types [full_index ].type == state -> type );
289
288
290
289
assert (state -> type != NULL );
@@ -294,7 +293,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
294
293
(void )_Py_atomic_add_int64 (
295
294
& _PyRuntime .types .managed_static .types [full_index ].interp_count , -1 );
296
295
if (final ) {
297
- assert (!_PyRuntime .types .managed_static .types [full_index ].interp_count );
296
+ assert (!_Py_atomic_load_int64 ( & _PyRuntime .types .managed_static .types [full_index ].interp_count ) );
298
297
_PyRuntime .types .managed_static .types [full_index ].type = NULL ;
299
298
300
299
managed_static_type_index_clear (self );
@@ -1258,6 +1257,19 @@ _PyType_GetVersionForCurrentState(PyTypeObject *tp)
1258
1257
#error "_Py_ATTR_CACHE_UNUSED must be bigger than max"
1259
1258
#endif
1260
1259
1260
+ static inline unsigned int
1261
+ next_global_version_tag (void )
1262
+ {
1263
+ unsigned int old ;
1264
+ do {
1265
+ old = _Py_atomic_load_uint_relaxed (& _PyRuntime .types .next_version_tag );
1266
+ if (old >= _Py_MAX_GLOBAL_TYPE_VERSION_TAG ) {
1267
+ return 0 ;
1268
+ }
1269
+ } while (!_Py_atomic_compare_exchange_uint (& _PyRuntime .types .next_version_tag , & old , old + 1 ));
1270
+ return old + 1 ;
1271
+ }
1272
+
1261
1273
static int
1262
1274
assign_version_tag (PyInterpreterState * interp , PyTypeObject * type )
1263
1275
{
@@ -1288,11 +1300,12 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
1288
1300
}
1289
1301
if (type -> tp_flags & Py_TPFLAGS_IMMUTABLETYPE ) {
1290
1302
/* static types */
1291
- if (NEXT_GLOBAL_VERSION_TAG > _Py_MAX_GLOBAL_TYPE_VERSION_TAG ) {
1303
+ unsigned int next_version_tag = next_global_version_tag ();
1304
+ if (next_version_tag == 0 ) {
1292
1305
/* We have run out of version numbers */
1293
1306
return 0 ;
1294
1307
}
1295
- set_version_unlocked (type , NEXT_GLOBAL_VERSION_TAG ++ );
1308
+ set_version_unlocked (type , next_version_tag );
1296
1309
assert (type -> tp_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
1297
1310
}
1298
1311
else {
@@ -8704,7 +8717,11 @@ type_ready_set_new(PyTypeObject *type, int initial)
8704
8717
&& base == & PyBaseObject_Type
8705
8718
&& !(type -> tp_flags & Py_TPFLAGS_HEAPTYPE ))
8706
8719
{
8707
- type_add_flags (type , Py_TPFLAGS_DISALLOW_INSTANTIATION );
8720
+ if (initial ) {
8721
+ type_add_flags (type , Py_TPFLAGS_DISALLOW_INSTANTIATION );
8722
+ } else {
8723
+ assert (type -> tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION );
8724
+ }
8708
8725
}
8709
8726
8710
8727
if (!(type -> tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION )) {
@@ -8718,13 +8735,17 @@ type_ready_set_new(PyTypeObject *type, int initial)
8718
8735
}
8719
8736
}
8720
8737
else {
8721
- // tp_new is NULL: inherit tp_new from base
8722
- type -> tp_new = base -> tp_new ;
8738
+ if (initial ) {
8739
+ // tp_new is NULL: inherit tp_new from base
8740
+ type -> tp_new = base -> tp_new ;
8741
+ }
8723
8742
}
8724
8743
}
8725
8744
else {
8726
8745
// Py_TPFLAGS_DISALLOW_INSTANTIATION sets tp_new to NULL
8727
- type -> tp_new = NULL ;
8746
+ if (initial ) {
8747
+ type -> tp_new = NULL ;
8748
+ }
8728
8749
}
8729
8750
return 0 ;
8730
8751
}
@@ -8857,7 +8878,12 @@ type_ready(PyTypeObject *type, int initial)
8857
8878
}
8858
8879
8859
8880
/* All done -- set the ready flag */
8860
- type_add_flags (type , Py_TPFLAGS_READY );
8881
+ if (initial ) {
8882
+ type_add_flags (type , Py_TPFLAGS_READY );
8883
+ } else {
8884
+ assert (type -> tp_flags & Py_TPFLAGS_READY );
8885
+ }
8886
+
8861
8887
stop_readying (type );
8862
8888
8863
8889
assert (_PyType_CheckConsistency (type ));
@@ -8906,15 +8932,16 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self,
8906
8932
assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_DICT ));
8907
8933
assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_WEAKREF ));
8908
8934
8909
- if (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 ) {
8910
- assert (initial );
8935
+ if (initial ) {
8936
+ assert (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 );
8911
8937
8912
8938
type_add_flags (self , _Py_TPFLAGS_STATIC_BUILTIN );
8913
8939
type_add_flags (self , Py_TPFLAGS_IMMUTABLETYPE );
8914
8940
8915
- assert (NEXT_GLOBAL_VERSION_TAG <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
8916
8941
if (self -> tp_version_tag == 0 ) {
8917
- _PyType_SetVersion (self , NEXT_GLOBAL_VERSION_TAG ++ );
8942
+ unsigned int next_version_tag = next_global_version_tag ();
8943
+ assert (next_version_tag != 0 );
8944
+ _PyType_SetVersion (self , next_version_tag );
8918
8945
}
8919
8946
}
8920
8947
else {
0 commit comments