@@ -6540,28 +6540,11 @@ compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, const char*
65406540    return  0 ;
65416541}
65426542
6543- static  int 
6544- object_set_class (PyObject  * self , PyObject  * value , void  * closure )
6545- {
6546- 
6547-     if  (value  ==  NULL ) {
6548-         PyErr_SetString (PyExc_TypeError ,
6549-                         "can't delete __class__ attribute" );
6550-         return  -1 ;
6551-     }
6552-     if  (!PyType_Check (value )) {
6553-         PyErr_Format (PyExc_TypeError ,
6554-           "__class__ must be set to a class, not '%s' object" ,
6555-           Py_TYPE (value )-> tp_name );
6556-         return  -1 ;
6557-     }
6558-     PyTypeObject  * newto  =  (PyTypeObject  * )value ;
65596543
6560-     if  (PySys_Audit ("object.__setattr__" , "OsO" ,
6561-                     self , "__class__" , value ) <  0 ) {
6562-         return  -1 ;
6563-     }
65646544
6545+ static  int 
6546+ object_set_class_world_stopped (PyObject  * self , PyTypeObject  * newto )
6547+ {
65656548    PyTypeObject  * oldto  =  Py_TYPE (self );
65666549
65676550    /* In versions of CPython prior to 3.5, the code in 
@@ -6627,49 +6610,74 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
66276610        /* Changing the class will change the implicit dict keys, 
66286611         * so we must materialize the dictionary first. */ 
66296612        if  (oldto -> tp_flags  &  Py_TPFLAGS_INLINE_VALUES ) {
6630-             PyDictObject  * dict  =  _PyObject_MaterializeManagedDict (self );
6613+             PyDictObject  * dict  =  _PyObject_GetManagedDict (self );
66316614            if  (dict  ==  NULL ) {
6632-                 return  -1 ;
6615+                 dict  =  _PyObject_MaterializeManagedDict_LockHeld (self );
6616+                 if  (dict  ==  NULL ) {
6617+                     return  -1 ;
6618+                 }
66336619            }
66346620
6635-             bool  error  =  false;
6636- 
6637-             Py_BEGIN_CRITICAL_SECTION2 (self , dict );
6638- 
6639-             // If we raced after materialization and replaced the dict 
6640-             // then the materialized dict should no longer have the 
6641-             // inline values in which case detach is a nop. 
6642-             assert (_PyObject_GetManagedDict (self ) ==  dict  || 
6643-                    dict -> ma_values  !=  _PyObject_InlineValues (self ));
6621+             assert (_PyObject_GetManagedDict (self ) ==  dict );
66446622
66456623            if  (_PyDict_DetachFromObject (dict , self ) <  0 ) {
6646-                 error  =  true;
6647-             }
6648- 
6649-             Py_END_CRITICAL_SECTION2 ();
6650-             if  (error ) {
66516624                return  -1 ;
66526625            }
6626+ 
66536627        }
66546628        if  (newto -> tp_flags  &  Py_TPFLAGS_HEAPTYPE ) {
66556629            Py_INCREF (newto );
66566630        }
6657-         Py_BEGIN_CRITICAL_SECTION (self );
6658-         // The real Py_TYPE(self) (`oldto`) may have changed from 
6659-         // underneath us in another thread, so we re-fetch it here. 
6660-         oldto  =  Py_TYPE (self );
6631+ 
66616632        Py_SET_TYPE (self , newto );
6662-         Py_END_CRITICAL_SECTION ();
6633+ 
6634+         return  0 ;
6635+     }
6636+     else  {
6637+         return  -1 ;
6638+     }
6639+ }
6640+ 
6641+ static  int 
6642+ object_set_class (PyObject  * self , PyObject  * value , void  * closure )
6643+ {
6644+ 
6645+     if  (value  ==  NULL ) {
6646+         PyErr_SetString (PyExc_TypeError ,
6647+                         "can't delete __class__ attribute" );
6648+         return  -1 ;
6649+     }
6650+     if  (!PyType_Check (value )) {
6651+         PyErr_Format (PyExc_TypeError ,
6652+           "__class__ must be set to a class, not '%s' object" ,
6653+           Py_TYPE (value )-> tp_name );
6654+         return  -1 ;
6655+     }
6656+     PyTypeObject  * newto  =  (PyTypeObject  * )value ;
6657+ 
6658+     if  (PySys_Audit ("object.__setattr__" , "OsO" ,
6659+                     self , "__class__" , value ) <  0 ) {
6660+         return  -1 ;
6661+     }
6662+ 
6663+ #ifdef  Py_GIL_DISABLED 
6664+     PyInterpreterState  * interp  =  _PyInterpreterState_GET ();
6665+     _PyEval_StopTheWorld (interp );
6666+ #endif 
6667+     PyTypeObject  * oldto  =  Py_TYPE (self );
6668+     int  res  =  object_set_class_world_stopped (self , newto );
6669+ #ifdef  Py_GIL_DISABLED 
6670+     _PyEval_StartTheWorld (interp );
6671+ #endif 
6672+     if  (res  ==  0 ) {
66636673        if  (oldto -> tp_flags  &  Py_TPFLAGS_HEAPTYPE ) {
66646674            Py_DECREF (oldto );
66656675        }
66666676
66676677        RARE_EVENT_INC (set_class );
66686678        return  0 ;
66696679    }
6670-     else  {
6671-         return  -1 ;
6672-     }
6680+     return  res ;
66736681}
66746682
66756683static  PyGetSetDef  object_getsets [] =  {
0 commit comments