@@ -54,7 +54,6 @@ class object "PyObject *" "&PyBaseObject_Type"
5454 PyUnicode_CheckExact(name) && \
5555 (PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE)
5656
57- #define NEXT_GLOBAL_VERSION_TAG _PyRuntime.types.next_version_tag
5857#define NEXT_VERSION_TAG (interp ) \
5958 (interp)->types.next_version_tag
6059
@@ -1359,6 +1358,19 @@ _PyType_LookupByVersion(unsigned int version)
13591358#error "_Py_ATTR_CACHE_UNUSED must be bigger than max"
13601359#endif
13611360
1361+ static inline unsigned int
1362+ get_next_global_version_tag (void )
1363+ {
1364+ unsigned int old ;
1365+ do {
1366+ old = _Py_atomic_load_uint_relaxed (& _PyRuntime .types .next_version_tag );
1367+ if (old >= _Py_MAX_GLOBAL_TYPE_VERSION_TAG ) {
1368+ return (unsigned int )-1 ;
1369+ }
1370+ } while (!_Py_atomic_compare_exchange_uint (& _PyRuntime .types .next_version_tag , & old , old + 1 ));
1371+ return old + 1 ;
1372+ }
1373+
13621374static int
13631375assign_version_tag (PyInterpreterState * interp , PyTypeObject * type )
13641376{
@@ -1389,11 +1401,12 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
13891401 }
13901402 if (type -> tp_flags & Py_TPFLAGS_IMMUTABLETYPE ) {
13911403 /* static types */
1392- if (NEXT_GLOBAL_VERSION_TAG > _Py_MAX_GLOBAL_TYPE_VERSION_TAG ) {
1404+ unsigned int next_version_tag = get_next_global_version_tag ();
1405+ if (next_version_tag == (unsigned int )-1 ) {
13931406 /* We have run out of version numbers */
13941407 return 0 ;
13951408 }
1396- set_version_unlocked (type , NEXT_GLOBAL_VERSION_TAG ++ );
1409+ set_version_unlocked (type , next_version_tag );
13971410 assert (type -> tp_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
13981411 }
13991412 else {
@@ -9005,7 +9018,7 @@ type_ready_set_new(PyTypeObject *type, int initial)
90059018 default also inherit object.__new__. */
90069019 if (type -> tp_new == NULL
90079020 && base == & PyBaseObject_Type
9008- && !(type -> tp_flags & Py_TPFLAGS_HEAPTYPE ))
9021+ && !(type -> tp_flags & Py_TPFLAGS_HEAPTYPE ) && initial )
90099022 {
90109023 type_add_flags (type , Py_TPFLAGS_DISALLOW_INSTANTIATION );
90119024 }
@@ -9021,13 +9034,21 @@ type_ready_set_new(PyTypeObject *type, int initial)
90219034 }
90229035 }
90239036 else {
9024- // tp_new is NULL: inherit tp_new from base
9025- type -> tp_new = base -> tp_new ;
9037+ if (initial ) {
9038+ // tp_new is NULL: inherit tp_new from base
9039+ type -> tp_new = base -> tp_new ;
9040+ } else {
9041+ assert (type -> tp_new = base -> tp_new );
9042+ }
90269043 }
90279044 }
90289045 else {
90299046 // Py_TPFLAGS_DISALLOW_INSTANTIATION sets tp_new to NULL
9030- type -> tp_new = NULL ;
9047+ if (initial ) {
9048+ type -> tp_new = NULL ;
9049+ } else {
9050+ assert (type -> tp_new == NULL );
9051+ }
90319052 }
90329053 return 0 ;
90339054}
@@ -9160,7 +9181,9 @@ type_ready(PyTypeObject *type, int initial)
91609181 }
91619182
91629183 /* All done -- set the ready flag */
9163- type_add_flags (type , Py_TPFLAGS_READY );
9184+ if (initial ) {
9185+ type_add_flags (type , Py_TPFLAGS_READY );
9186+ }
91649187 stop_readying (type );
91659188
91669189 assert (_PyType_CheckConsistency (type ));
@@ -9209,15 +9232,16 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self,
92099232 assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_DICT ));
92109233 assert (!(self -> tp_flags & Py_TPFLAGS_MANAGED_WEAKREF ));
92119234
9212- if (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 ) {
9213- assert (initial );
9235+ if (initial ) {
9236+ assert (( self -> tp_flags & Py_TPFLAGS_READY ) == 0 );
92149237
92159238 type_add_flags (self , _Py_TPFLAGS_STATIC_BUILTIN );
92169239 type_add_flags (self , Py_TPFLAGS_IMMUTABLETYPE );
92179240
9218- assert (NEXT_GLOBAL_VERSION_TAG <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG );
92199241 if (self -> tp_version_tag == 0 ) {
9220- _PyType_SetVersion (self , NEXT_GLOBAL_VERSION_TAG ++ );
9242+ unsigned int next_version_tag = get_next_global_version_tag ();
9243+ assert (next_version_tag != (unsigned int )-1 );
9244+ _PyType_SetVersion (self , next_version_tag );
92219245 }
92229246 }
92239247 else {
0 commit comments