@@ -5975,53 +5975,59 @@ PyObject_GetItemData(PyObject *obj)
59755975}
59765976
59775977/* Internal API to look for a name through the MRO, bypassing the method cache.
5978- This returns a borrowed reference, and might set an exception.
5979- 'error' is set to: -1: error with exception; 1: error without exception; 0: ok */
5980- static PyObject *
5981- find_name_in_mro (PyTypeObject * type , PyObject * name , int * error )
5978+ The result is stored as a _PyStackRef in `out`. It never set an exception.
5979+ Returns -1 if there was an error, 0 if the name was not found, and 1 if
5980+ the name was found. */
5981+ static int
5982+ find_name_in_mro (PyTypeObject * type , PyObject * name , _PyStackRef * out )
59825983{
59835984 Py_hash_t hash = _PyObject_HashFast (name );
59845985 if (hash == -1 ) {
5985- * error = -1 ;
5986- return NULL ;
5986+ PyErr_Clear () ;
5987+ return -1 ;
59875988 }
59885989
59895990 /* Look in tp_dict of types in MRO */
59905991 PyObject * mro = lookup_tp_mro (type );
59915992 if (mro == NULL ) {
59925993 if (!is_readying (type )) {
59935994 if (PyType_Ready (type ) < 0 ) {
5994- * error = -1 ;
5995- return NULL ;
5995+ PyErr_Clear () ;
5996+ return -1 ;
59965997 }
59975998 mro = lookup_tp_mro (type );
59985999 }
59996000 if (mro == NULL ) {
6000- * error = 1 ;
6001- return NULL ;
6001+ return -1 ;
60026002 }
60036003 }
60046004
6005- PyObject * res = NULL ;
6005+ int res = 0 ;
6006+ PyThreadState * tstate = _PyThreadState_GET ();
60066007 /* Keep a strong reference to mro because type->tp_mro can be replaced
60076008 during dict lookup, e.g. when comparing to non-string keys. */
6008- Py_INCREF (mro );
6009+ _PyCStackRef mro_ref ;
6010+ _PyThreadState_PushCStackRef (tstate , & mro_ref );
6011+ mro_ref .ref = PyStackRef_FromPyObjectNew (mro );
60096012 Py_ssize_t n = PyTuple_GET_SIZE (mro );
60106013 for (Py_ssize_t i = 0 ; i < n ; i ++ ) {
60116014 PyObject * base = PyTuple_GET_ITEM (mro , i );
60126015 PyObject * dict = lookup_tp_dict (_PyType_CAST (base ));
60136016 assert (dict && PyDict_Check (dict ));
6014- if (_PyDict_GetItemRef_KnownHash ((PyDictObject * )dict , name , hash , & res ) < 0 ) {
6015- * error = -1 ;
6017+ Py_ssize_t ix = _Py_dict_lookup_threadsafe_stackref (
6018+ (PyDictObject * )dict , name , hash , out );
6019+ if (ix == DKIX_ERROR ) {
6020+ PyErr_Clear ();
6021+ res = -1 ;
60166022 goto done ;
60176023 }
6018- if (res != NULL ) {
6024+ if (!PyStackRef_IsNull (* out )) {
6025+ res = 1 ;
60196026 break ;
60206027 }
60216028 }
6022- * error = 0 ;
60236029done :
6024- Py_DECREF ( mro );
6030+ _PyThreadState_PopCStackRef ( tstate , & mro_ref );
60256031 return res ;
60266032}
60276033
@@ -6176,11 +6182,11 @@ _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef
61766182 // We need to atomically do the lookup and capture the version before
61776183 // anyone else can modify our mro or mutate the type.
61786184
6179- PyObject * res ;
6180- int error ;
6185+ int res ;
61816186 PyInterpreterState * interp = _PyInterpreterState_GET ();
61826187 int has_version = 0 ;
61836188 unsigned int assigned_version = 0 ;
6189+
61846190 BEGIN_TYPE_LOCK ();
61856191 // We must assign the version before doing the lookup. If
61866192 // find_name_in_mro() blocks and releases the critical section
@@ -6189,35 +6195,24 @@ _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef
61896195 has_version = assign_version_tag (interp , type );
61906196 assigned_version = type -> tp_version_tag ;
61916197 }
6192- res = find_name_in_mro (type , name , & error );
6198+ res = find_name_in_mro (type , name , out );
61936199 END_TYPE_LOCK ();
61946200
61956201 /* Only put NULL results into cache if there was no error. */
6196- if (error ) {
6197- /* It's not ideal to clear the error condition,
6198- but this function is documented as not setting
6199- an exception, and I don't want to change that.
6200- E.g., when PyType_Ready() can't proceed, it won't
6201- set the "ready" flag, so future attempts to ready
6202- the same type will call it again -- hopefully
6203- in a context that propagates the exception out.
6204- */
6205- if (error == -1 ) {
6206- PyErr_Clear ();
6207- }
6202+ if (res < 0 ) {
62086203 * out = PyStackRef_NULL ;
62096204 return 0 ;
62106205 }
62116206
62126207 if (has_version ) {
6208+ PyObject * res_obj = PyStackRef_AsPyObjectBorrow (* out );
62136209#if Py_GIL_DISABLED
6214- update_cache_gil_disabled (entry , name , assigned_version , res );
6210+ update_cache_gil_disabled (entry , name , assigned_version , res_obj );
62156211#else
6216- PyObject * old_value = update_cache (entry , name , assigned_version , res );
6212+ PyObject * old_value = update_cache (entry , name , assigned_version , res_obj );
62176213 Py_DECREF (old_value );
62186214#endif
62196215 }
6220- * out = res ? PyStackRef_FromPyObjectSteal (res ) : PyStackRef_NULL ;
62216216 return has_version ? assigned_version : 0 ;
62226217}
62236218
@@ -11706,7 +11701,6 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p,
1170611701 int use_generic = 0 ;
1170711702
1170811703 int offset = p -> offset ;
11709- int error ;
1171011704 void * * ptr = slotptr (type , offset );
1171111705
1171211706 if (ptr == NULL ) {
@@ -11722,19 +11716,15 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p,
1172211716 assert (!PyErr_Occurred ());
1172311717 do {
1172411718 /* Use faster uncached lookup as we won't get any cache hits during type setup. */
11725- descr = find_name_in_mro (type , p -> name_strobj , & error );
11726- if (descr == NULL ) {
11727- if (error == -1 ) {
11728- /* It is unlikely but not impossible that there has been an exception
11729- during lookup. Since this function originally expected no errors,
11730- we ignore them here in order to keep up the interface. */
11731- PyErr_Clear ();
11732- }
11719+ _PyStackRef descr_ref ;
11720+ int res = find_name_in_mro (type , p -> name_strobj , & descr_ref );
11721+ if (res <= 0 ) {
1173311722 if (ptr == (void * * )& type -> tp_iternext ) {
1173411723 specific = (void * )_PyObject_NextNotImplemented ;
1173511724 }
1173611725 continue ;
1173711726 }
11727+ descr = PyStackRef_AsPyObjectBorrow (descr_ref );
1173811728 if (Py_IS_TYPE (descr , & PyWrapperDescr_Type ) &&
1173911729 ((PyWrapperDescrObject * )descr )-> d_base -> name_strobj == p -> name_strobj ) {
1174011730 void * * tptr ;
@@ -11812,7 +11802,7 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p,
1181211802 }
1181311803 }
1181411804 }
11815- Py_DECREF ( descr );
11805+ PyStackRef_CLOSE ( descr_ref );
1181611806 } while ((++ p )-> offset == offset );
1181711807
1181811808 void * slot_value ;
0 commit comments